Last active
December 14, 2022 20:58
-
-
Save EricRabil/8ddbd03f4a63315e3e40a5fa613b6bad to your computer and use it in GitHub Desktop.
Property wrappers providing access to shared logs identified by StaticStrings
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import OSLog | |
extension StaticString: Hashable { | |
public static func == (lhs: StaticString, rhs: StaticString) -> Bool { | |
if lhs.hasPointerRepresentation || rhs.hasPointerRepresentation { | |
guard lhs.hasPointerRepresentation && rhs.hasPointerRepresentation else { | |
return false | |
} | |
return strcmp(lhs.utf8Start, rhs.utf8Start) == 0 | |
} else { | |
return lhs.unicodeScalar == rhs.unicodeScalar | |
} | |
} | |
public func hash(into hasher: inout Hasher) { | |
if hasPointerRepresentation { | |
withUTF8Buffer { | |
hasher.combine(bytes: UnsafeRawBufferPointer($0)) | |
} | |
} else { | |
unicodeScalar.hash(into: &hasher) | |
} | |
} | |
} | |
extension String { | |
init(_ string: StaticString) { | |
if string.hasPointerRepresentation { | |
self = NSString(bytesNoCopy: UnsafeMutableRawPointer(mutating: UnsafeRawPointer(string.utf8Start)), length: string.utf8CodeUnitCount, encoding: NSUTF8StringEncoding, freeWhenDone: false)! as String | |
} else { | |
self = string.description | |
} | |
} | |
} | |
struct Loggers { | |
} | |
private extension Loggers { | |
private static var lock: UnsafeMutablePointer<pthread_rwlock_t> = { | |
let lock = UnsafeMutablePointer<pthread_rwlock_t>.allocate(capacity: 1) | |
pthread_rwlock_init(lock, nil) | |
return lock | |
}() | |
typealias Logs = [StaticString: Logger] | |
private static var logs: Logs = [:] | |
static func withRead<P>(_ callback: (Logs) -> P) -> P { | |
pthread_rwlock_rdlock(lock) | |
let result = callback(logs) | |
pthread_rwlock_unlock(lock) | |
return result | |
} | |
static func withWrite<P>(_ callback: (inout Logs) -> P) -> P { | |
pthread_rwlock_wrlock(lock) | |
let result = callback(&logs) | |
pthread_rwlock_unlock(lock) | |
return result | |
} | |
} | |
extension Loggers { | |
static func logger(_ name: StaticString) -> Logger { | |
if let logger = withRead ({ $0[name] }) { | |
return logger | |
} | |
return withWrite ({ | |
if let logger = $0[name] { | |
return logger | |
} | |
let logger = Logger(subsystem: "com.ericrabil.kctool", category: String(name)) | |
$0[name] = logger | |
return logger | |
}) | |
} | |
} | |
@propertyWrapper | |
struct Log { | |
let name: StaticString | |
var wrappedValue: Logger { | |
Loggers.logger(name) | |
} | |
init(_ name: StaticString) { | |
self.name = name | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment