@@ -459,7 +459,7 @@ extension JSONEncoderImpl: _SpecialTreatmentEncoder {
459
459
case let url as URL :
460
460
return . string( url. absoluteString)
461
461
case let decimal as Decimal :
462
- return . number ( decimal. description)
462
+ return . outputNumber ( decimal. description)
463
463
case let object as [ String : Encodable ] : // this emits a warning, but it works perfectly
464
464
return try self . wrapObject ( object, for: nil )
465
465
case let date as Date :
@@ -507,7 +507,7 @@ extension _SpecialTreatmentEncoder {
507
507
if string. hasSuffix ( " .0 " ) {
508
508
string. removeLast ( 2 )
509
509
}
510
- return . number ( string)
510
+ return . outputNumber ( string)
511
511
}
512
512
513
513
fileprivate func wrapEncodable< E: Encodable > ( _ encodable: E , for additionalKey: CodingKey ? ) throws -> JSONValue ? {
@@ -519,7 +519,7 @@ extension _SpecialTreatmentEncoder {
519
519
case let url as URL :
520
520
return . string( url. absoluteString)
521
521
case let decimal as Decimal :
522
- return . number ( decimal. description)
522
+ return . outputNumber ( decimal. description)
523
523
case let object as [ String : Encodable ] :
524
524
return try self . wrapObject ( object, for: additionalKey)
525
525
default :
@@ -537,10 +537,10 @@ extension _SpecialTreatmentEncoder {
537
537
return encoder. value ?? . null
538
538
539
539
case . secondsSince1970:
540
- return . number ( date. timeIntervalSince1970. description)
540
+ return . outputNumber ( date. timeIntervalSince1970. description)
541
541
542
542
case . millisecondsSince1970:
543
- return . number ( ( date. timeIntervalSince1970 * 1000 ) . description)
543
+ return . outputNumber ( ( date. timeIntervalSince1970 * 1000 ) . description)
544
544
545
545
case . iso8601:
546
546
if #available( macOS 10 . 12 , iOS 10 . 0 , watchOS 3 . 0 , tvOS 10 . 0 , * ) {
@@ -751,7 +751,7 @@ extension JSONKeyedEncodingContainer {
751
751
}
752
752
753
753
@inline ( __always) private mutating func encodeFixedWidthInteger< N: FixedWidthInteger > ( _ value: N , key: CodingKey ) throws {
754
- self . object. set ( . number ( value. description) , for: key. stringValue)
754
+ self . object. set ( . outputNumber ( value. description) , for: key. stringValue)
755
755
}
756
756
}
757
757
@@ -872,7 +872,7 @@ private struct JSONUnkeyedEncodingContainer: UnkeyedEncodingContainer, _SpecialT
872
872
873
873
extension JSONUnkeyedEncodingContainer {
874
874
@inline ( __always) private mutating func encodeFixedWidthInteger< N: FixedWidthInteger > ( _ value: N ) throws {
875
- self . array. append ( . number ( value. description) )
875
+ self . array. append ( . outputNumber ( value. description) )
876
876
}
877
877
878
878
@inline ( __always) private mutating func encodeFloatingPoint< F: FloatingPoint & CustomStringConvertible > ( _ float: F ) throws {
@@ -971,7 +971,7 @@ private struct JSONSingleValueEncodingContainer: SingleValueEncodingContainer, _
971
971
extension JSONSingleValueEncodingContainer {
972
972
@inline ( __always) private mutating func encodeFixedWidthInteger< N: FixedWidthInteger > ( _ value: N ) throws {
973
973
self . preconditionCanEncodeNewValue ( )
974
- self . impl. singleValue = . number ( value. description)
974
+ self . impl. singleValue = . outputNumber ( value. description)
975
975
}
976
976
977
977
@inline ( __always) private mutating func encodeFloatingPoint< F: FloatingPoint & CustomStringConvertible > ( _ float: F ) throws {
@@ -1011,7 +1011,9 @@ extension JSONValue {
1011
1011
bytes. append ( contentsOf: [ UInt8 ] . _false)
1012
1012
case . string( let string) :
1013
1013
self . encodeString ( string, to: & bytes)
1014
- case . number( let string) :
1014
+ case . inputNumber( let jsonNumber) :
1015
+ bytes. append ( contentsOf: jsonNumber. description. utf8)
1016
+ case . outputNumber( let string) :
1015
1017
bytes. append ( contentsOf: string. utf8)
1016
1018
case . array( let array) :
1017
1019
var iterator = array. makeIterator ( )
@@ -1070,7 +1072,9 @@ extension JSONValue {
1070
1072
bytes. append ( contentsOf: [ UInt8 ] . _false)
1071
1073
case . string( let string) :
1072
1074
self . encodeString ( string, to: & bytes)
1073
- case . number( let string) :
1075
+ case . inputNumber( let jsonNumber) :
1076
+ bytes. append ( contentsOf: jsonNumber. description. utf8)
1077
+ case . outputNumber( let string) :
1074
1078
bytes. append ( contentsOf: string. utf8)
1075
1079
case . array( let array) :
1076
1080
var iterator = array. makeIterator ( )
@@ -1529,14 +1533,14 @@ extension JSONDecoderImpl: Decoder {
1529
1533
}
1530
1534
1531
1535
private func unwrapDecimal( ) throws -> Decimal {
1532
- guard case . number ( let numberString ) = self . json else {
1536
+ guard case . inputNumber ( let jsonNumber ) = self . json else {
1533
1537
throw DecodingError . typeMismatch ( Decimal . self, DecodingError . Context ( codingPath: self . codingPath, debugDescription: " " ) )
1534
1538
}
1535
1539
1536
- guard let decimal = Decimal ( string : numberString ) else {
1540
+ guard let decimal = jsonNumber . exactlyDecimal else {
1537
1541
throw DecodingError . dataCorrupted ( . init(
1538
1542
codingPath: self . codingPath,
1539
- debugDescription: " Parsed JSON number < \( numberString ) > does not fit in \( Decimal . self) . " ) )
1543
+ debugDescription: " Parsed JSON number < \( jsonNumber ) > does not fit in \( Decimal . self) . " ) )
1540
1544
}
1541
1545
1542
1546
return decimal
@@ -1572,18 +1576,20 @@ extension JSONDecoderImpl: Decoder {
1572
1576
for additionalKey: CodingKey ? = nil ,
1573
1577
as type: T . Type ) throws -> T
1574
1578
{
1575
- if case . number( let number) = value {
1576
- guard let floatingPoint = T ( number) else {
1577
- var path = self . codingPath
1578
- if let additionalKey = additionalKey {
1579
- path. append ( additionalKey)
1580
- }
1581
- throw DecodingError . dataCorrupted ( . init(
1582
- codingPath: path,
1583
- debugDescription: " Parsed JSON number < \( number) > does not fit in \( T . self) . " ) )
1579
+ if case . inputNumber( let jsonNumber) = value {
1580
+ if type == Double . self, let number = jsonNumber. exactlyDouble {
1581
+ return number as! T
1584
1582
}
1585
-
1586
- return floatingPoint
1583
+ if type == Float . self, let number = jsonNumber. exactlyFloat {
1584
+ return number as! T
1585
+ }
1586
+ var path = self . codingPath
1587
+ if let additionalKey = additionalKey {
1588
+ path. append ( additionalKey)
1589
+ }
1590
+ throw DecodingError . dataCorrupted ( . init(
1591
+ codingPath: path,
1592
+ debugDescription: " Parsed JSON number < \( jsonNumber) > does not fit in \( T . self) . " ) )
1587
1593
}
1588
1594
1589
1595
if case . string( let string) = value,
@@ -1607,57 +1613,48 @@ extension JSONDecoderImpl: Decoder {
1607
1613
for additionalKey: CodingKey ? = nil ,
1608
1614
as type: T . Type ) throws -> T
1609
1615
{
1610
- guard case . number ( let number ) = value else {
1616
+ guard case . inputNumber ( let jsonNumber ) = value else {
1611
1617
throw self . createTypeMismatchError ( type: T . self, for: additionalKey, value: value)
1612
1618
}
1613
1619
1614
- // this is the fast pass. Number directly convertible to Integer
1615
- if let integer = T ( number) {
1616
- return integer
1620
+ if type == UInt8 . self, let number = jsonNumber. exactlyUInt8 {
1621
+ return number as! T
1617
1622
}
1618
-
1619
- // this is the really slow path... If the fast path has failed. For example for "34.0" as
1620
- // an integer, we try to go through NSNumber
1621
- if let nsNumber = NSNumber . fromJSONNumber ( number) {
1622
- if type == UInt8 . self, NSNumber ( value: nsNumber. uint8Value) == nsNumber {
1623
- return nsNumber. uint8Value as! T
1624
- }
1625
- if type == Int8 . self, NSNumber ( value: nsNumber. int8Value) == nsNumber {
1626
- return nsNumber. uint8Value as! T
1627
- }
1628
- if type == UInt16 . self, NSNumber ( value: nsNumber. uint16Value) == nsNumber {
1629
- return nsNumber. uint16Value as! T
1630
- }
1631
- if type == Int16 . self, NSNumber ( value: nsNumber. int16Value) == nsNumber {
1632
- return nsNumber. uint16Value as! T
1633
- }
1634
- if type == UInt32 . self, NSNumber ( value: nsNumber. uint32Value) == nsNumber {
1635
- return nsNumber. uint32Value as! T
1636
- }
1637
- if type == Int32 . self, NSNumber ( value: nsNumber. int32Value) == nsNumber {
1638
- return nsNumber. uint32Value as! T
1639
- }
1640
- if type == UInt64 . self, NSNumber ( value: nsNumber. uint64Value) == nsNumber {
1641
- return nsNumber. uint64Value as! T
1642
- }
1643
- if type == Int64 . self, NSNumber ( value: nsNumber. int64Value) == nsNumber {
1644
- return nsNumber. uint64Value as! T
1645
- }
1646
- if type == UInt . self, NSNumber ( value: nsNumber. uintValue) == nsNumber {
1647
- return nsNumber. uintValue as! T
1648
- }
1649
- if type == Int . self, NSNumber ( value: nsNumber. uintValue) == nsNumber {
1650
- return nsNumber. intValue as! T
1651
- }
1623
+ if type == Int8 . self, let number = jsonNumber. exactlyInt8 {
1624
+ return number as! T
1652
1625
}
1653
-
1626
+ if type == UInt16 . self, let number = jsonNumber. exactlyUInt16 {
1627
+ return number as! T
1628
+ }
1629
+ if type == Int16 . self, let number = jsonNumber. exactlyInt16 {
1630
+ return number as! T
1631
+ }
1632
+ if type == UInt32 . self, let number = jsonNumber. exactlyUInt32 {
1633
+ return number as! T
1634
+ }
1635
+ if type == Int32 . self, let number = jsonNumber. exactlyInt32 {
1636
+ return number as! T
1637
+ }
1638
+ if type == UInt64 . self, let number = jsonNumber. exactlyUInt64 {
1639
+ return number as! T
1640
+ }
1641
+ if type == Int64 . self, let number = jsonNumber. exactlyInt64 {
1642
+ return number as! T
1643
+ }
1644
+ if type == UInt . self, let number = jsonNumber. exactlyUInt {
1645
+ return number as! T
1646
+ }
1647
+ if type == Int . self, let number = jsonNumber. exactlyInt {
1648
+ return number as! T
1649
+ }
1650
+
1654
1651
var path = self . codingPath
1655
1652
if let additionalKey = additionalKey {
1656
1653
path. append ( additionalKey)
1657
1654
}
1658
1655
throw DecodingError . dataCorrupted ( . init(
1659
1656
codingPath: path,
1660
- debugDescription: " Parsed JSON number < \( number ) > does not fit in \( T . self) . " ) )
1657
+ debugDescription: " Parsed JSON number < \( jsonNumber ) > does not fit in \( T . self) . " ) )
1661
1658
}
1662
1659
1663
1660
private func createTypeMismatchError( type: Any . Type , for additionalKey: CodingKey ? = nil , value: JSONValue ) -> DecodingError {
0 commit comments