this repo has no description
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}