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