@@ -168,9 +168,60 @@ final class JSONDecoderImpl: Decoder {
168168 if type == Decimal . self {
169169 return try unboxDecimal ( from: value, for: codingPathNode, additionalKey) as! T
170170 }
171+ // Dictionary
171172 if !options. keyDecodingStrategy. isDefault, let dictType = type as? StringDecodableDictionary . Type {
172173 return try unboxDictionary ( from: value, as: dictType, for: codingPathNode, additionalKey)
173174 }
175+ // Array (Written for performance.)
176+ if type == [ String ] . self {
177+ return try unboxArray ( from: value, as: [ String ] . self, for: codingPathNode, additionalKey) as! T
178+ }
179+ if type == [ Double ] . self {
180+ return try unboxArray ( from: value, as: [ Double ] . self, for: codingPathNode, additionalKey) as! T
181+ }
182+ if type == [ Float ] . self {
183+ return try unboxArray ( from: value, as: [ Float ] . self, for: codingPathNode, additionalKey) as! T
184+ }
185+ if type == [ Int ] . self {
186+ return try unboxArray ( from: value, as: [ Int ] . self, for: codingPathNode, additionalKey) as! T
187+ }
188+ if type == [ Int8 ] . self {
189+ return try unboxArray ( from: value, as: [ Int8 ] . self, for: codingPathNode, additionalKey) as! T
190+ }
191+ if type == [ Int16 ] . self {
192+ return try unboxArray ( from: value, as: [ Int16 ] . self, for: codingPathNode, additionalKey) as! T
193+ }
194+ if type == [ Int32 ] . self {
195+ return try unboxArray ( from: value, as: [ Int32 ] . self, for: codingPathNode, additionalKey) as! T
196+ }
197+ if type == [ Int64 ] . self {
198+ return try unboxArray ( from: value, as: [ Int64 ] . self, for: codingPathNode, additionalKey) as! T
199+ }
200+ if type == [ UInt ] . self {
201+ return try unboxArray ( from: value, as: [ UInt ] . self, for: codingPathNode, additionalKey) as! T
202+ }
203+ if type == [ UInt8 ] . self {
204+ return try unboxArray ( from: value, as: [ UInt8 ] . self, for: codingPathNode, additionalKey) as! T
205+ }
206+ if type == [ UInt16 ] . self {
207+ return try unboxArray ( from: value, as: [ UInt16 ] . self, for: codingPathNode, additionalKey) as! T
208+ }
209+ if type == [ UInt32 ] . self {
210+ return try unboxArray ( from: value, as: [ UInt32 ] . self, for: codingPathNode, additionalKey) as! T
211+ }
212+ if type == [ UInt64 ] . self {
213+ return try unboxArray ( from: value, as: [ UInt64 ] . self, for: codingPathNode, additionalKey) as! T
214+ }
215+ #if compiler(>=6.0)
216+ if #available( macOS 15 . 0 , iOS 18 . 0 , tvOS 18 . 0 , watchOS 11 . 0 , visionOS 2 . 0 , * ) {
217+ if type == [ Int128 ] . self {
218+ return try unboxArray ( from: value, as: [ Int128 ] . self, for: codingPathNode, additionalKey) as! T
219+ }
220+ if type == [ UInt128 ] . self {
221+ return try unboxArray ( from: value, as: [ UInt128 ] . self, for: codingPathNode, additionalKey) as! T
222+ }
223+ }
224+ #endif
174225
175226 return try with ( value: value, path: codingPathNode. appending ( additionalKey) ) {
176227 try type. init ( from: self )
@@ -336,6 +387,113 @@ final class JSONDecoderImpl: Decoder {
336387 return result as! T
337388 }
338389
390+ private func unboxArray< T: Decodable , K: CodingKey > (
391+ from value: JSON ,
392+ as arrayType: [ T ] . Type,
393+ for codingPathNode: CodingPathNode ,
394+ _ additionalKey: K ? = nil
395+ ) throws -> [ T ] {
396+ try checkNotNull ( value, expectedType: [ T ] . self, for: codingPathNode, additionalKey)
397+
398+ guard value. isArray else {
399+ throw createTypeMismatchError (
400+ type: [ T ] . self,
401+ for: codingPathNode. path ( byAppending: additionalKey) ,
402+ value: value
403+ )
404+ }
405+
406+ let arraySize = yyjson_arr_size ( value. pointer)
407+ let arrayCodingPathNode = codingPathNode. appending ( additionalKey)
408+
409+ var result : [ T ] = [ ]
410+ result. reserveCapacity ( arraySize)
411+
412+ var iter = yyjson_arr_iter ( )
413+ guard yyjson_arr_iter_init ( value. pointer, & iter) else {
414+ if arraySize == 0 {
415+ return result
416+ }
417+ throw DecodingError . dataCorrupted ( . init(
418+ codingPath: codingPathNode. path ( byAppending: additionalKey) ,
419+ debugDescription: " Failed to initialize array iterator. "
420+ ) )
421+ }
422+ var index = 0
423+
424+ while let elementPtr = yyjson_arr_iter_next ( & iter) {
425+ let elementValue = JSON ( pointer: elementPtr)
426+ let indexKey = _CodingKey ( index: index)
427+
428+ let decodedValue : T
429+
430+ if T . self == String . self {
431+ guard let string = options. json5 ? elementValue. stringWhenJSON5 : elementValue. string else {
432+ throw createTypeMismatchError ( type: String . self, for: codingPathNode. path ( byAppending: additionalKey) , value: elementValue)
433+ }
434+ decodedValue = string as! T
435+ } else if T . self == Double . self {
436+ decodedValue = try unboxFloatingPoint ( from: elementValue, as: Double . self, for: arrayCodingPathNode, indexKey) as! T
437+ } else if T . self == Float . self {
438+ decodedValue = try unboxFloatingPoint ( from: elementValue, as: Float . self, for: arrayCodingPathNode, indexKey) as! T
439+ } else if T . self == Int . self {
440+ let intValue : Int = try unboxInteger ( elementValue, for: arrayCodingPathNode, indexKey)
441+ decodedValue = intValue as! T
442+ } else if T . self == Int8 . self {
443+ let intValue : Int8 = try unboxInteger ( elementValue, for: arrayCodingPathNode, indexKey)
444+ decodedValue = intValue as! T
445+ } else if T . self == Int16 . self {
446+ let intValue : Int16 = try unboxInteger ( elementValue, for: arrayCodingPathNode, indexKey)
447+ decodedValue = intValue as! T
448+ } else if T . self == Int32 . self {
449+ let intValue : Int32 = try unboxInteger ( elementValue, for: arrayCodingPathNode, indexKey)
450+ decodedValue = intValue as! T
451+ } else if T . self == Int64 . self {
452+ let intValue : Int64 = try unboxInteger ( elementValue, for: arrayCodingPathNode, indexKey)
453+ decodedValue = intValue as! T
454+ } else if T . self == UInt . self {
455+ let intValue : UInt = try unboxInteger ( elementValue, for: arrayCodingPathNode, indexKey)
456+ decodedValue = intValue as! T
457+ } else if T . self == UInt8 . self {
458+ let intValue : UInt8 = try unboxInteger ( elementValue, for: arrayCodingPathNode, indexKey)
459+ decodedValue = intValue as! T
460+ } else if T . self == UInt16 . self {
461+ let intValue : UInt16 = try unboxInteger ( elementValue, for: arrayCodingPathNode, indexKey)
462+ decodedValue = intValue as! T
463+ } else if T . self == UInt32 . self {
464+ let intValue : UInt32 = try unboxInteger ( elementValue, for: arrayCodingPathNode, indexKey)
465+ decodedValue = intValue as! T
466+ } else if T . self == UInt64 . self {
467+ let intValue : UInt64 = try unboxInteger ( elementValue, for: arrayCodingPathNode, indexKey)
468+ decodedValue = intValue as! T
469+ } else {
470+ #if compiler(>=6.0)
471+ if #available( macOS 15 . 0 , iOS 18 . 0 , tvOS 18 . 0 , watchOS 11 . 0 , visionOS 2 . 0 , * ) {
472+ if T . self == Int128 . self {
473+ let intValue : Int128 = try unboxInteger ( elementValue, for: arrayCodingPathNode, indexKey)
474+ decodedValue = intValue as! T
475+ } else if T . self == UInt128 . self {
476+ let intValue : UInt128 = try unboxInteger ( elementValue, for: arrayCodingPathNode, indexKey)
477+ decodedValue = intValue as! T
478+ } else {
479+ decodedValue = try unbox ( elementValue, as: T . self, for: arrayCodingPathNode, indexKey)
480+ }
481+ } else {
482+ decodedValue = try unbox ( elementValue, as: T . self, for: arrayCodingPathNode, indexKey)
483+ }
484+ #else
485+ decodedValue = try unbox ( elementValue, as: T . self, for: arrayCodingPathNode, indexKey)
486+ #endif
487+ }
488+
489+ result. append ( decodedValue)
490+ index += 1
491+ }
492+
493+ return result
494+ }
495+
496+
339497 func unboxString< K: CodingKey > ( from value: JSON , for codingPathNode: CodingPathNode , _ additionalKey: K ? = nil ) throws -> String {
340498 try checkNotNull ( value, expectedType: String . self, for: codingPathNode, additionalKey)
341499
@@ -386,6 +544,28 @@ final class JSONDecoderImpl: Decoder {
386544
387545 throw self . createTypeMismatchError ( type: F . self, for: codingPathNode. path ( byAppending: additionalKey) , value: value)
388546 }
547+
548+ @inline ( __always)
549+ private func unboxInteger< T: FixedWidthInteger > (
550+ _ jsonValue: JSON ,
551+ for codingPathNode: CodingPathNode ,
552+ _ additionalKey: ( some CodingKey ) ? = nil
553+ ) throws -> T {
554+ guard let int: T = jsonValue. integer ( ) else {
555+ guard jsonValue. isNumber else {
556+ throw createTypeMismatchError (
557+ type: T . self,
558+ for: codingPathNode. path ( byAppending: additionalKey) ,
559+ value: jsonValue
560+ )
561+ }
562+ throw DecodingError . dataCorrupted ( . init(
563+ codingPath: codingPath,
564+ debugDescription: " Number \( jsonValue. numberValue) is not representable in Swift. "
565+ ) )
566+ }
567+ return int
568+ }
389569}
390570
391571// MARK: - SingleValueDecodingContainer
@@ -1459,7 +1639,7 @@ private struct JSONUnkeyedDecodingContainer: UnkeyedDecodingContainer {
14591639
14601640 @inline ( __always)
14611641 private mutating func decodeInteger< T: FixedWidthInteger > ( _ jsonValue: JSON ) throws -> T {
1462- guard let int: T = jsonValue. integer ( ) else {
1642+ guard let int: T = jsonValue. integer ( ) else {
14631643 guard jsonValue. isNumber else {
14641644 throw impl. createTypeMismatchError ( type: T . self, for: currentCodingPath, value: jsonValue)
14651645 }
0 commit comments