|
22 | 22 | /// Libraries may also want to provide an extension, offering the values that users are expected to reach for
|
23 | 23 | /// using the following pattern:
|
24 | 24 | ///
|
25 |
| -/// extension BaggageContext { |
| 25 | +/// extension BaggageContextProtocol { |
26 | 26 | /// var testID: TestIDKey.Value {
|
27 | 27 | /// get {
|
28 | 28 | /// self[TestIDKey.self]
|
|
31 | 31 | /// }
|
32 | 32 | /// }
|
33 | 33 | /// }
|
34 |
| -public struct BaggageContext { |
| 34 | +public struct BaggageContext: BaggageContextProtocol { |
35 | 35 | private var _storage = [AnyBaggageContextKey: ValueContainer]()
|
36 | 36 |
|
37 | 37 | /// Create an empty `BaggageContext`.
|
@@ -64,10 +64,34 @@ public struct BaggageContext {
|
64 | 64 |
|
65 | 65 | extension BaggageContext: CustomStringConvertible {
|
66 | 66 | public var description: String {
|
67 |
| - "\(Self.self)(keys: \(self._storage.map(\.key.name)))" |
| 67 | + "\(Self.self)(keys: \(self._storage.map { $0.key.name }))" |
68 | 68 | }
|
69 | 69 | }
|
70 | 70 |
|
| 71 | +public protocol BaggageContextProtocol { |
| 72 | + /// Provides type-safe access to the baggage's values. |
| 73 | + /// |
| 74 | + /// Rather than using this subscript directly, users are encouraged to offer a convenience accessor to their values, |
| 75 | + /// using the following pattern: |
| 76 | + /// |
| 77 | + /// extension BaggageContextProtocol { |
| 78 | + /// var testID: TestIDKey.Value { |
| 79 | + /// get { |
| 80 | + /// self[TestIDKey.self] |
| 81 | + /// } set { |
| 82 | + /// self[TestIDKey.self] = newValue |
| 83 | + /// } |
| 84 | + /// } |
| 85 | + /// } |
| 86 | + subscript<Key: BaggageContextKey>(_ key: Key.Type) -> Key.Value? { get set } |
| 87 | + |
| 88 | + /// Iterates over the baggage context's contents invoking the callback one-by one. |
| 89 | + func forEach(_ callback: (AnyBaggageContextKey, Any) -> Void) |
| 90 | +} |
| 91 | + |
| 92 | +// ==== ------------------------------------------------------------------------ |
| 93 | +// MARK: Baggage keys |
| 94 | + |
71 | 95 | /// `BaggageContextKey`s are used as keys in a `BaggageContext`. Their associated type `Value` gurantees type-safety.
|
72 | 96 | /// To give your `BaggageContextKey` an explicit name you may override the `name` property.
|
73 | 97 | public protocol BaggageContextKey {
|
@@ -108,3 +132,36 @@ extension AnyBaggageContextKey: Hashable {
|
108 | 132 | hasher.combine(ObjectIdentifier(self.keyType))
|
109 | 133 | }
|
110 | 134 | }
|
| 135 | + |
| 136 | +// ==== ---------------------------------------------------------------------------------------------------------------- |
| 137 | +// MARK: Framework Context Protocols |
| 138 | + |
| 139 | +public protocol BaggageContextCarrier: BaggageContextProtocol { |
| 140 | + var baggage: BaggageContext { get set } |
| 141 | +} |
| 142 | + |
| 143 | +extension BaggageContextCarrier { |
| 144 | + public subscript<Key: BaggageContextKey>(baggageKey: Key.Type) -> Key.Value? { |
| 145 | + get { |
| 146 | + self.baggage[baggageKey] |
| 147 | + } set { |
| 148 | + self.baggage[baggageKey] = newValue |
| 149 | + } |
| 150 | + } |
| 151 | + |
| 152 | + public func forEach(_ callback: (AnyBaggageContextKey, Any) -> Void) { |
| 153 | + self.baggage.forEach(callback) |
| 154 | + } |
| 155 | +} |
| 156 | + |
| 157 | +/// A baggage itself also is a carrier of "itself". |
| 158 | +extension BaggageContext: BaggageContextCarrier { |
| 159 | + public var baggage: BaggageContext { |
| 160 | + get { |
| 161 | + self |
| 162 | + } |
| 163 | + set { |
| 164 | + self = newValue |
| 165 | + } |
| 166 | + } |
| 167 | +} |
0 commit comments