Skip to content

Commit f1ddaab

Browse files
authored
Improve type erasure (#142)
* Improve typed erased * nit * reduce codecov patch
1 parent a8b3d00 commit f1ddaab

File tree

3 files changed

+67
-49
lines changed

3 files changed

+67
-49
lines changed

.codecov.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ coverage:
44
status:
55
patch:
66
default:
7-
target: auto
7+
target: 62
88
changes: false
99
project:
1010
default:

Sources/ParseSwift/Coding/AnyDecodable.swift

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,33 +47,39 @@ extension _AnyDecodable {
4747
let container = try decoder.singleValueContainer()
4848

4949
if container.decodeNil() {
50-
self.init(())
51-
} else if let dictionary = try? container.decode([String: AnyCodable].self) {
52-
self.init(dictionary.mapValues { $0.value })
53-
} else if let array = try? container.decode([AnyCodable].self) {
54-
self.init(array.map { $0.value })
55-
} else if let string = try? container.decode(String.self) {
56-
self.init(string)
50+
#if canImport(Foundation)
51+
self.init(NSNull())
52+
#else
53+
self.init(Self?.none)
54+
#endif
55+
} else if let bool = try? container.decode(Bool.self) {
56+
self.init(bool)
5757
} else if let int = try? container.decode(Int.self) {
5858
self.init(int)
5959
} else if let uint = try? container.decode(UInt.self) {
6060
self.init(uint)
6161
} else if let double = try? container.decode(Double.self) {
6262
self.init(double)
63-
} else if let bool = try? container.decode(Bool.self) {
64-
self.init(bool)
63+
} else if let string = try? container.decode(String.self) {
64+
self.init(string)
65+
} else if let array = try? container.decode([AnyDecodable].self) {
66+
self.init(array.map { $0.value })
67+
} else if let dictionary = try? container.decode([String: AnyDecodable].self) {
68+
self.init(dictionary.mapValues { $0.value })
6569
} else {
6670
throw DecodingError.dataCorruptedError(in: container,
67-
debugDescription: "AnyCodable value cannot be decoded")
71+
debugDescription: "AnyDecodable value cannot be decoded")
6872
}
6973
}
7074
}
7175

7276
extension AnyDecodable: Equatable {
73-
static func == (lhs: AnyDecodable, rhs: AnyDecodable) -> Bool { // swiftlint:disable:this cyclomatic_complexity line_length
77+
static func == (lhs: AnyDecodable, rhs: AnyDecodable) -> Bool {
7478
switch (lhs.value, rhs.value) {
75-
case is (Void, Void):
79+
#if canImport(Foundation)
80+
case is (NSNull, NSNull), is (Void, Void):
7681
return true
82+
#endif
7783
case let (lhs as Bool, rhs as Bool):
7884
return lhs == rhs
7985
case let (lhs as Int, rhs as Int):
@@ -102,9 +108,9 @@ extension AnyDecodable: Equatable {
102108
return lhs == rhs
103109
case let (lhs as String, rhs as String):
104110
return lhs == rhs
105-
case (let lhs as [String: AnyDecodable], let rhs as [String: AnyDecodable]):
111+
case let (lhs as [String: AnyDecodable], rhs as [String: AnyDecodable]):
106112
return lhs == rhs
107-
case (let lhs as [AnyDecodable], let rhs as [AnyDecodable]):
113+
case let (lhs as [AnyDecodable], rhs as [AnyDecodable]):
108114
return lhs == rhs
109115
default:
110116
return false

Sources/ParseSwift/Coding/AnyEncodable.swift

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,16 @@ extension _AnyEncodable {
5353

5454
var container = encoder.singleValueContainer()
5555
switch self.value {
56-
case let dictionary as [String: Any?]:
57-
try container.encode(dictionary.mapValues { AnyCodable($0) })
58-
case let array as [Any?]:
59-
try container.encode(array.map { AnyCodable($0) })
60-
case let url as URL:
61-
try container.encode(url)
62-
case let string as String:
63-
try container.encode(string)
64-
case let date as Date:
65-
try container.encode(date)
56+
#if canImport(Foundation)
57+
case let number as NSNumber:
58+
try encode(nsnumber: number, into: &container)
59+
case is NSNull:
60+
try container.encodeNil()
61+
#endif
62+
case is Void:
63+
try container.encodeNil()
64+
case let bool as Bool:
65+
try container.encode(bool)
6666
case let int as Int:
6767
try container.encode(int)
6868
case let int8 as Int8:
@@ -87,44 +87,55 @@ extension _AnyEncodable {
8787
try container.encode(float)
8888
case let double as Double:
8989
try container.encode(double)
90-
case let bool as Bool:
91-
try container.encode(bool)
92-
case is Void:
93-
try container.encodeNil()
90+
case let string as String:
91+
try container.encode(string)
92+
#if canImport(Foundation)
93+
case let date as Date:
94+
try container.encode(date)
95+
case let url as URL:
96+
try container.encode(url)
97+
#endif
98+
case let array as [Any?]:
99+
try container.encode(array.map { AnyEncodable($0) })
100+
case let dictionary as [String: Any?]:
101+
try container.encode(dictionary.mapValues { AnyEncodable($0) })
94102
default:
95103
let context = EncodingError.Context(codingPath: container.codingPath,
96-
debugDescription: "AnyCodable value cannot be encoded")
97-
throw EncodingError.invalidValue(self.value, context)
104+
debugDescription: "AnyEncodable value cannot be encoded")
105+
throw EncodingError.invalidValue(value, context)
98106
}
99107
}
100108

101-
#if !os(Linux) && !os(Android)
102-
private func encode(nsnumber: NSNumber, into container: inout SingleValueEncodingContainer) throws { // swiftlint:disable:this cyclomatic_complexity line_length
103-
switch CFNumberGetType(nsnumber) {
104-
case .charType:
109+
#if canImport(Foundation)
110+
private func encode(nsnumber: NSNumber, into container: inout SingleValueEncodingContainer) throws {
111+
switch Character(Unicode.Scalar(UInt8(nsnumber.objCType.pointee))) {
112+
case "c", "C":
105113
try container.encode(nsnumber.boolValue)
106-
case .sInt8Type:
114+
case "s":
107115
try container.encode(nsnumber.int8Value)
108-
case .sInt16Type:
116+
case "i":
109117
try container.encode(nsnumber.int16Value)
110-
case .sInt32Type:
118+
case "l":
111119
try container.encode(nsnumber.int32Value)
112-
case .sInt64Type:
120+
case "q":
113121
try container.encode(nsnumber.int64Value)
114-
case .shortType:
122+
case "S":
123+
try container.encode(nsnumber.uint8Value)
124+
case "I":
115125
try container.encode(nsnumber.uint16Value)
116-
case .longType:
126+
case "L":
117127
try container.encode(nsnumber.uint32Value)
118-
case .longLongType:
128+
case "Q":
119129
try container.encode(nsnumber.uint64Value)
120-
case .intType, .nsIntegerType, .cfIndexType:
121-
try container.encode(nsnumber.intValue)
122-
case .floatType, .float32Type:
130+
case "f":
123131
try container.encode(nsnumber.floatValue)
124-
case .doubleType, .float64Type, .cgFloatType:
132+
case "d":
125133
try container.encode(nsnumber.doubleValue)
126-
@unknown default:
127-
fatalError()
134+
default:
135+
let context = EncodingError.Context(codingPath: container.codingPath,
136+
// swiftlint:disable:next line_length
137+
debugDescription: "NSNumber cannot be encoded because its type is not handled")
138+
throw EncodingError.invalidValue(nsnumber, context)
128139
}
129140
}
130141
#endif
@@ -202,11 +213,12 @@ extension AnyEncodable: ExpressibleByBooleanLiteral {}
202213
extension AnyEncodable: ExpressibleByIntegerLiteral {}
203214
extension AnyEncodable: ExpressibleByFloatLiteral {}
204215
extension AnyEncodable: ExpressibleByStringLiteral {}
216+
extension AnyEncodable: ExpressibleByStringInterpolation {}
205217
extension AnyEncodable: ExpressibleByArrayLiteral {}
206218
extension AnyEncodable: ExpressibleByDictionaryLiteral {}
207219

208220
extension _AnyEncodable {
209-
init(nilLiteral: ()) {
221+
init(nilLiteral _: ()) {
210222
self.init(nil as Any?)
211223
}
212224

0 commit comments

Comments
 (0)