|
35 | 35 | /// Libraries may also want to provide an extension, offering the values that users are expected to reach for
|
36 | 36 | /// using the following pattern:
|
37 | 37 | ///
|
38 |
| -/// extension BaggageContext { |
| 38 | +/// extension BaggageContextProtocol { |
39 | 39 | /// var testID: TestIDKey.Value {
|
40 | 40 | /// get {
|
41 | 41 | /// self[TestIDKey.self]
|
|
44 | 44 | /// }
|
45 | 45 | /// }
|
46 | 46 | /// }
|
47 |
| -public struct BaggageContext { |
| 47 | +public struct BaggageContext: BaggageContextProtocol { |
48 | 48 | private var _storage = [AnyBaggageContextKey: ValueContainer]()
|
49 | 49 |
|
50 | 50 | /// Create an empty `BaggageContext`.
|
@@ -77,10 +77,34 @@ public struct BaggageContext {
|
77 | 77 |
|
78 | 78 | extension BaggageContext: CustomStringConvertible {
|
79 | 79 | public var description: String {
|
80 |
| - "\(Self.self)(keys: \(self._storage.map(\.key.name)))" |
| 80 | + "\(Self.self)(keys: \(self._storage.map { $0.key.name }))" |
81 | 81 | }
|
82 | 82 | }
|
83 | 83 |
|
| 84 | +public protocol BaggageContextProtocol { |
| 85 | + /// Provides type-safe access to the baggage's values. |
| 86 | + /// |
| 87 | + /// Rather than using this subscript directly, users are encouraged to offer a convenience accessor to their values, |
| 88 | + /// using the following pattern: |
| 89 | + /// |
| 90 | + /// extension BaggageContextProtocol { |
| 91 | + /// var testID: TestIDKey.Value { |
| 92 | + /// get { |
| 93 | + /// self[TestIDKey.self] |
| 94 | + /// } set { |
| 95 | + /// self[TestIDKey.self] = newValue |
| 96 | + /// } |
| 97 | + /// } |
| 98 | + /// } |
| 99 | + subscript<Key: BaggageContextKey>(_ key: Key.Type) -> Key.Value? { get set } |
| 100 | + |
| 101 | + /// Iterates over the baggage context's contents invoking the callback one-by one. |
| 102 | + func forEach(_ callback: (AnyBaggageContextKey, Any) -> Void) |
| 103 | +} |
| 104 | + |
| 105 | +// ==== ------------------------------------------------------------------------ |
| 106 | +// MARK: Baggage keys |
| 107 | + |
84 | 108 | /// `BaggageContextKey`s are used as keys in a `BaggageContext`. Their associated type `Value` gurantees type-safety.
|
85 | 109 | /// To give your `BaggageContextKey` an explicit name you may override the `name` property.
|
86 | 110 | public protocol BaggageContextKey {
|
@@ -121,3 +145,36 @@ extension AnyBaggageContextKey: Hashable {
|
121 | 145 | hasher.combine(ObjectIdentifier(self.keyType))
|
122 | 146 | }
|
123 | 147 | }
|
| 148 | + |
| 149 | +// ==== ---------------------------------------------------------------------------------------------------------------- |
| 150 | +// MARK: Framework Context Protocols |
| 151 | + |
| 152 | +public protocol BaggageContextCarrier: BaggageContextProtocol { |
| 153 | + var baggage: BaggageContext { get set } |
| 154 | +} |
| 155 | + |
| 156 | +extension BaggageContextCarrier { |
| 157 | + public subscript<Key: BaggageContextKey>(baggageKey: Key.Type) -> Key.Value? { |
| 158 | + get { |
| 159 | + self.baggage[baggageKey] |
| 160 | + } set { |
| 161 | + self.baggage[baggageKey] = newValue |
| 162 | + } |
| 163 | + } |
| 164 | + |
| 165 | + public func forEach(_ callback: (AnyBaggageContextKey, Any) -> Void) { |
| 166 | + self.baggage.forEach(callback) |
| 167 | + } |
| 168 | +} |
| 169 | + |
| 170 | +/// A baggage itself also is a carrier of "itself". |
| 171 | +extension BaggageContext: BaggageContextCarrier { |
| 172 | + public var baggage: BaggageContext { |
| 173 | + get { |
| 174 | + self |
| 175 | + } |
| 176 | + set { |
| 177 | + self = newValue |
| 178 | + } |
| 179 | + } |
| 180 | +} |
0 commit comments