CommandLineToolkit
43 строки · 1.3 Кб
1import Foundation
2
3protocol ConsoleContextKey {
4associatedtype Value
5
6static var defaultValue: Value { get }
7}
8
9struct ConsoleContext {
10@TaskLocal
11static var current: ConsoleContext = .init()
12
13private var storage: [ObjectIdentifier: Any] = [:]
14
15subscript <Key: ConsoleContextKey>(_ key: Key.Type) -> Key.Value {
16get { storage[ObjectIdentifier(key)] as? Key.Value ?? key.defaultValue }
17set { storage[ObjectIdentifier(key)] = newValue }
18}
19
20func withUpdated<Value>(key: WritableKeyPath<ConsoleContext, Value>, value: Value) -> ConsoleContext {
21var newContext = self
22newContext[keyPath: key] = value
23return newContext
24}
25}
26
27extension TaskLocal where Value == ConsoleContext {
28func withUpdated<R, ContextValue>(
29key: WritableKeyPath<ConsoleContext, ContextValue>,
30value: ContextValue,
31operation: () throws -> R
32) rethrows -> R {
33try self.withValue(wrappedValue.withUpdated(key: key, value: value), operation: operation)
34}
35
36func withUpdated<R, ContextValue>(
37key: WritableKeyPath<ConsoleContext, ContextValue>,
38value: ContextValue,
39operation: () async throws -> R
40) async rethrows -> R {
41try await self.withValue(wrappedValue.withUpdated(key: key, value: value), operation: operation)
42}
43}
44