@@ -11,9 +11,12 @@ import OrderedCollections
1111
1212private class ContextBox {
1313 var entries : [ ObjectIdentifier : StoredContextValue ]
14+ /// Mapping from ``CodableContextKey/identifier`` to base64 encoded data
15+ var decodedEntries : [ String : String ]
1416
15- init ( _ entries: [ ObjectIdentifier : StoredContextValue ] ) {
17+ init ( _ entries: [ ObjectIdentifier : StoredContextValue ] , _ decodedEntries : [ String : String ] ) {
1618 self . entries = entries
19+ self . decodedEntries = decodedEntries
1720 }
1821}
1922
@@ -26,15 +29,17 @@ struct StoredContextValue {
2629/// A `Context` holds a collection of values for predefined `ContextKey`s or `OptionalContextKey`s.
2730public struct Context : ContextKeyRetrievable {
2831 private var boxedEntries : ContextBox
32+
2933 private var entries : [ ObjectIdentifier : StoredContextValue ] {
3034 boxedEntries. entries
3135 }
32- /// Mapping from ``CodableContextKey/identifier`` to base64 encoded data
33- private let decodedEntries : [ String : String ]
36+
37+ private var decodedEntries : [ String : String ] {
38+ boxedEntries. decodedEntries
39+ }
3440
3541 init ( _ entries: [ ObjectIdentifier : StoredContextValue ] = [ : ] , _ decodedEntries: [ String : String ] = [ : ] ) {
36- self . boxedEntries = ContextBox ( entries)
37- self . decodedEntries = decodedEntries
42+ self . boxedEntries = ContextBox ( entries, decodedEntries)
3843 }
3944
4045 /// Create a new empty ``Context``.
@@ -97,14 +102,21 @@ public struct Context: ContextKeyRetrievable {
97102 precondition ( entries [ key] == nil || allowOverwrite, " Cannot overwrite existing ContextKey entry with `unsafeAdd`: \( C . self) : \( value) " )
98103 if let codableContextKey = contextKey as? AnyCodableContextKey . Type {
99104 // we need to prevent this. as Otherwise we would need to handle merging this stuff which get really complex
100- precondition ( decodedEntries [ codableContextKey. identifier] == nil , " Cannot overwrite existing CodableContextKey entry with `unsafeAdd`: \( C . self) : \( value) " )
105+ precondition (
106+ decodedEntries [ codableContextKey. identifier] == nil || allowOverwrite,
107+ " Cannot overwrite existing CodableContextKey entry with `unsafeAdd`: \( C . self) : \( value) "
108+ )
109+
110+ // if we reach this point, either the key doesn't exist or `allowOverwrite` was turned on
111+ // and we need to remove the existing entry in order to properly overwrite everything
112+ boxedEntries. decodedEntries. removeValue ( forKey: codableContextKey. identifier)
101113 }
102114
103115 boxedEntries. entries [ key] = StoredContextValue ( key: contextKey, value: value)
104116 }
105117
106118 private func checkForDecodedEntries< Key: CodableContextKey > ( for key: Key . Type = Key . self) -> Key . Value ? {
107- guard let dataValue = decodedEntries [ Key . identifier] else {
119+ guard let dataValue = boxedEntries . decodedEntries. removeValue ( forKey : Key . identifier) else {
108120 return nil
109121 }
110122
@@ -140,15 +152,13 @@ extension Context: Codable {
140152 public init ( from decoder: Decoder ) throws {
141153 let container = try decoder. container ( keyedBy: StringContextKey . self)
142154
143- self . boxedEntries = ContextBox ( [ : ] )
144-
145155 var decodedEntries : [ String : String ] = [ : ]
146156
147157 for key in container. allKeys {
148158 decodedEntries [ key. stringValue] = try container. decode ( String . self, forKey: key)
149159 }
150160
151- self . decodedEntries = decodedEntries
161+ self . boxedEntries = ContextBox ( [ : ] , decodedEntries)
152162 }
153163
154164 public func encode( to encoder: Encoder ) throws {
0 commit comments