this repo has no description
at main 340 lines 13 kB view raw
1// 2// DecodingContainer+SingleValue.swift 3// URLQueryItemCoder 4// 5// Created by Kyle Hughes on 2/21/23. 6// 7 8import Foundation 9 10extension DecodingContainer { 11 /// A decoding container that holds a single primitive value. 12 /// 13 /// **As Keyed Value Container** 14 /// 15 /// Only used for leaf node keyed containers that have no children (e.g. all nil properties). We can't detect that 16 /// they are actually keyed containers when building our decoding representation because we don't have type 17 /// information. The internal decoder system will know to ask for an keyed container and we will return this. 18 /// 19 /// **As Unkeyed Value Container** 20 /// 21 /// Only used for leaf node unkeyed containers that have no children. We can't detect that they are actually unkeyed 22 /// containers when building our decoding representation because we don't have type information. The internal 23 /// decoder system will know to ask for an unkeyed container and we will return this. 24 internal final class SingleValue { 25 internal let codingPath: [any CodingKey] 26 internal let configuration: DecodingStrategies 27 28 internal private(set) var value: PrimitiveValue? 29 30 // MARK: Internal Initialization 31 32 internal init(codingPath: [any CodingKey], configuration: DecodingStrategies) { 33 self.codingPath = codingPath 34 self.configuration = configuration 35 36 value = nil 37 } 38 39 // MARK: Internal Instance Interface 40 41 internal func store(_ value: PrimitiveValue?) { 42 precondition( 43 self.value == nil, 44 "A value was already stored in the single value container." 45 ) 46 47 self.value = value 48 } 49 50 // MARK: Private Instance Interface 51 52 private func nextCodingPath(appending key: any CodingKey) -> [any CodingKey] { 53 var nextCodingPath = codingPath 54 nextCodingPath.append(key) 55 56 return nextCodingPath 57 } 58 59 private func unwrapPrimitiveValue<Target>(for target: Target.Type) throws -> PrimitiveValue { 60 guard let value else { 61 throw DecodingError.valueNotFound(target, .foundNilInsteadOfPrimitiveValue(at: codingPath)) 62 } 63 64 return value 65 } 66 } 67} 68 69// MARK: - SingleValueDecodingContainer Extension 70 71extension DecodingContainer.SingleValue: SingleValueDecodingContainer { 72 // MARK: Internal Instance Interface 73 74 internal func decode(_ type: Bool.Type) throws -> Bool { 75 let primitiveValue = try unwrapPrimitiveValue(for: type) 76 77 guard let decodedValue = primitiveValue.decode(type) else { 78 throw DecodingError.typeMismatch(type, .primitiveValueMismatch(at: codingPath, for: type)) 79 } 80 81 return decodedValue 82 } 83 84 internal func decode(_ type: String.Type) throws -> String { 85 let primitiveValue = try unwrapPrimitiveValue(for: type) 86 87 guard let decodedValue = primitiveValue.decode(type) else { 88 throw DecodingError.typeMismatch(type, .primitiveValueMismatch(at: codingPath, for: type)) 89 } 90 91 return decodedValue 92 } 93 94 internal func decode(_ type: Double.Type) throws -> Double { 95 let lowLevelDecoder = LowLevelDecoder(container: .singleValue(self)) 96 97 return try configuration.nonConformingFloatStrategy.decode(insideOf: lowLevelDecoder) 98 } 99 100 internal func decode(_ type: Float.Type) throws -> Float { 101 let lowLevelDecoder = LowLevelDecoder(container: .singleValue(self)) 102 103 return try configuration.nonConformingFloatStrategy.decode(insideOf: lowLevelDecoder) 104 } 105 106 internal func decode(_ type: Int.Type) throws -> Int { 107 let primitiveValue = try unwrapPrimitiveValue(for: type) 108 109 guard let decodedValue = primitiveValue.decode(type) else { 110 throw DecodingError.typeMismatch(type, .primitiveValueMismatch(at: codingPath, for: type)) 111 } 112 113 return decodedValue 114 } 115 116 internal func decode(_ type: Int8.Type) throws -> Int8 { 117 let primitiveValue = try unwrapPrimitiveValue(for: type) 118 119 guard let decodedValue = primitiveValue.decode(type) else { 120 throw DecodingError.typeMismatch(type, .primitiveValueMismatch(at: codingPath, for: type)) 121 } 122 123 return decodedValue 124 } 125 126 internal func decode(_ type: Int16.Type) throws -> Int16 { 127 let primitiveValue = try unwrapPrimitiveValue(for: type) 128 129 guard let decodedValue = primitiveValue.decode(type) else { 130 throw DecodingError.typeMismatch(type, .primitiveValueMismatch(at: codingPath, for: type)) 131 } 132 133 return decodedValue 134 } 135 136 internal func decode(_ type: Int32.Type) throws -> Int32 { 137 let primitiveValue = try unwrapPrimitiveValue(for: type) 138 139 guard let decodedValue = primitiveValue.decode(type) else { 140 throw DecodingError.typeMismatch(type, .primitiveValueMismatch(at: codingPath, for: type)) 141 } 142 143 return decodedValue 144 } 145 146 internal func decode(_ type: Int64.Type) throws -> Int64 { 147 let primitiveValue = try unwrapPrimitiveValue(for: type) 148 149 guard let decodedValue = primitiveValue.decode(type) else { 150 throw DecodingError.typeMismatch(type, .primitiveValueMismatch(at: codingPath, for: type)) 151 } 152 153 return decodedValue 154 } 155 156 internal func decode(_ type: UInt.Type) throws -> UInt { 157 let primitiveValue = try unwrapPrimitiveValue(for: type) 158 159 guard let decodedValue = primitiveValue.decode(type) else { 160 throw DecodingError.typeMismatch(type, .primitiveValueMismatch(at: codingPath, for: type)) 161 } 162 163 return decodedValue 164 } 165 166 internal func decode(_ type: UInt8.Type) throws -> UInt8 { 167 let primitiveValue = try unwrapPrimitiveValue(for: type) 168 169 guard let decodedValue = primitiveValue.decode(type) else { 170 throw DecodingError.typeMismatch(type, .primitiveValueMismatch(at: codingPath, for: type)) 171 } 172 173 return decodedValue 174 } 175 176 internal func decode(_ type: UInt16.Type) throws -> UInt16 { 177 let primitiveValue = try unwrapPrimitiveValue(for: type) 178 179 guard let decodedValue = primitiveValue.decode(type) else { 180 throw DecodingError.typeMismatch(type, .primitiveValueMismatch(at: codingPath, for: type)) 181 } 182 183 return decodedValue 184 } 185 186 internal func decode(_ type: UInt32.Type) throws -> UInt32 { 187 let primitiveValue = try unwrapPrimitiveValue(for: type) 188 189 guard let decodedValue = primitiveValue.decode(type) else { 190 throw DecodingError.typeMismatch(type, .primitiveValueMismatch(at: codingPath, for: type)) 191 } 192 193 return decodedValue 194 } 195 196 internal func decode(_ type: UInt64.Type) throws -> UInt64 { 197 let primitiveValue = try unwrapPrimitiveValue(for: type) 198 199 guard let decodedValue = primitiveValue.decode(type) else { 200 throw DecodingError.typeMismatch(type, .primitiveValueMismatch(at: codingPath, for: type)) 201 } 202 203 return decodedValue 204 } 205 206 internal func decode<Target>(_ type: Target.Type) throws -> Target where Target: Decodable { 207 let lowLevelDecoder = LowLevelDecoder(container: .singleValue(self)) 208 209 return try lowLevelDecoder.decodeWithSpecialTreatment(as: type) 210 } 211 212 internal func decodeNil() -> Bool { 213 value == nil 214 } 215} 216 217// MARK: - KeyedDecodingContainerProtocol Extension 218 219extension DecodingContainer.SingleValue: KeyedDecodingContainerProtocol { 220 // MARK: Internal Instance Interface 221 222 internal var allKeys: [StringCodingKey] { 223 [] 224 } 225 226 internal func contains(_ key: StringCodingKey) -> Bool { 227 false 228 } 229 230 internal func decode(_ type: Bool.Type, forKey key: StringCodingKey) throws -> Bool { 231 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 232 } 233 234 internal func decode(_ type: String.Type, forKey key: StringCodingKey) throws -> String { 235 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 236 } 237 238 internal func decode(_ type: Double.Type, forKey key: StringCodingKey) throws -> Double { 239 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 240 } 241 242 internal func decode(_ type: Float.Type, forKey key: StringCodingKey) throws -> Float { 243 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 244 } 245 246 internal func decode(_ type: Int.Type, forKey key: StringCodingKey) throws -> Int { 247 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 248 } 249 250 internal func decode(_ type: Int8.Type, forKey key: StringCodingKey) throws -> Int8 { 251 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 252 } 253 254 internal func decode(_ type: Int16.Type, forKey key: StringCodingKey) throws -> Int16 { 255 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 256 } 257 258 internal func decode(_ type: Int32.Type, forKey key: StringCodingKey) throws -> Int32 { 259 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 260 } 261 262 internal func decode(_ type: Int64.Type, forKey key: StringCodingKey) throws -> Int64 { 263 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 264 } 265 266 internal func decode(_ type: UInt.Type, forKey key: StringCodingKey) throws -> UInt { 267 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 268 } 269 270 internal func decode(_ type: UInt8.Type, forKey key: StringCodingKey) throws -> UInt8 { 271 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 272 } 273 274 internal func decode(_ type: UInt16.Type, forKey key: StringCodingKey) throws -> UInt16 { 275 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 276 } 277 278 internal func decode(_ type: UInt32.Type, forKey key: StringCodingKey) throws -> UInt32 { 279 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 280 } 281 282 internal func decode(_ type: UInt64.Type, forKey key: StringCodingKey) throws -> UInt64 { 283 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 284 } 285 286 internal func decode<T>(_ type: T.Type, forKey key: StringCodingKey) throws -> T where T : Decodable { 287 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 288 } 289 290 internal func decodeNil(forKey key: StringCodingKey) throws -> Bool { 291 true 292 } 293 294 internal func nestedContainer<NestedKey>( 295 keyedBy type: NestedKey.Type, 296 forKey key: StringCodingKey 297 ) throws -> KeyedDecodingContainer<NestedKey> where NestedKey : CodingKey { 298 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 299 } 300 301 internal func nestedUnkeyedContainer(forKey key: StringCodingKey) throws -> UnkeyedDecodingContainer { 302 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 303 } 304 305 internal func superDecoder() throws -> Decoder { 306 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 307 } 308 309 internal func superDecoder(forKey key: StringCodingKey) throws -> Decoder { 310 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 311 } 312} 313 314// MARK: - UnkeyedDecodingContainer Extension 315 316extension DecodingContainer.SingleValue: UnkeyedDecodingContainer { 317 // MARK: Internal Instance Interface 318 319 internal var count: Int? { 320 value == nil ? 0 : 1 321 } 322 323 internal var isAtEnd: Bool { 324 true 325 } 326 327 internal var currentIndex: Int { 328 0 329 } 330 331 internal func nestedContainer<NestedKey>( 332 keyedBy type: NestedKey.Type 333 ) throws -> KeyedDecodingContainer<NestedKey> where NestedKey: CodingKey { 334 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 335 } 336 337 internal func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer { 338 throw DecodingError.dataCorrupted(.singleValueContainerCanOnlyActAsEmptyKeyedContainer(at: codingPath)) 339 } 340}