@@ -32,207 +32,81 @@ import Foundation
32
32
and other collections that require `Encodable` or `Decodable` conformance
33
33
by declaring their contained type to be `AnyCodable`.
34
34
*/
35
- public struct AnyCodable {
36
- public let value : Any
37
-
38
- public init < T> ( _ value: T ? ) {
39
- self . value = value ?? ( )
40
- }
35
+ public enum AnyCodable : Equatable {
36
+
37
+ case string( String )
38
+ case bool( Bool )
39
+ case int( Int )
40
+ case double( Double )
41
+ case object( [ String : AnyCodable ] )
42
+ case array( [ AnyCodable ] )
43
+ case null
41
44
}
42
45
43
46
extension AnyCodable : Encodable {
44
47
public func encode( to encoder: Encoder ) throws {
45
- var container = encoder. singleValueContainer ( )
46
-
47
- switch value {
48
- #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
49
- case let number as NSNumber :
50
- try encode ( nsnumber: number, into: & container)
51
- #endif
52
- case is NSNull , is Void :
48
+ switch self {
49
+ case let . string( value) : try value. encode ( to: encoder)
50
+ case let . bool( value) : try value. encode ( to: encoder)
51
+ case let . int( value) : try value. encode ( to: encoder)
52
+ case let . double( value) : try value. encode ( to: encoder)
53
+ case let . object( value) : try value. encode ( to: encoder)
54
+ case let . array( value) : try value. encode ( to: encoder)
55
+ case . null:
56
+ var container = encoder. singleValueContainer ( )
53
57
try container. encodeNil ( )
54
- case let bool as Bool :
55
- try container. encode ( bool)
56
- case let int as Int :
57
- try container. encode ( int)
58
- case let int8 as Int8 :
59
- try container. encode ( int8)
60
- case let int16 as Int16 :
61
- try container. encode ( int16)
62
- case let int32 as Int32 :
63
- try container. encode ( int32)
64
- case let int64 as Int64 :
65
- try container. encode ( int64)
66
- case let uint as UInt :
67
- try container. encode ( uint)
68
- case let uint8 as UInt8 :
69
- try container. encode ( uint8)
70
- case let uint16 as UInt16 :
71
- try container. encode ( uint16)
72
- case let uint32 as UInt32 :
73
- try container. encode ( uint32)
74
- case let uint64 as UInt64 :
75
- try container. encode ( uint64)
76
- case let float as Float :
77
- try container. encode ( float)
78
- case let double as Double :
79
- try container. encode ( double)
80
- case let string as String :
81
- try container. encode ( string)
82
- case let date as Date :
83
- try container. encode ( date)
84
- case let url as URL :
85
- try container. encode ( url)
86
- case let array as [ Any ? ] :
87
- try container. encode ( array. map { AnyCodable ( $0) } )
88
- case let dictionary as [ String : Any ? ] :
89
- try container. encode ( dictionary. mapValues { AnyCodable ( $0) } )
90
- default :
91
- let context = EncodingError . Context ( codingPath: container. codingPath, debugDescription: " AnyCodable value cannot be encoded " )
92
- throw EncodingError . invalidValue ( value, context)
93
- }
94
- }
95
-
96
- #if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
97
- private func encode( nsnumber: NSNumber , into container: inout SingleValueEncodingContainer ) throws {
98
- switch CFNumberGetType ( nsnumber) {
99
- case . charType:
100
- try container. encode ( nsnumber. boolValue)
101
- case . sInt8Type:
102
- try container. encode ( nsnumber. int8Value)
103
- case . sInt16Type:
104
- try container. encode ( nsnumber. int16Value)
105
- case . sInt32Type:
106
- try container. encode ( nsnumber. int32Value)
107
- case . sInt64Type:
108
- try container. encode ( nsnumber. int64Value)
109
- case . shortType:
110
- try container. encode ( nsnumber. uint16Value)
111
- case . longType:
112
- try container. encode ( nsnumber. uint32Value)
113
- case . longLongType:
114
- try container. encode ( nsnumber. uint64Value)
115
- case . intType, . nsIntegerType, . cfIndexType:
116
- try container. encode ( nsnumber. intValue)
117
- case . floatType, . float32Type:
118
- try container. encode ( nsnumber. floatValue)
119
- case . doubleType, . float64Type, . cgFloatType:
120
- try container. encode ( nsnumber. doubleValue)
121
- #if swift(>=5.0)
122
- @unknown default :
123
- fatalError ( )
124
- #endif
125
58
}
126
59
}
127
- #endif
128
60
}
129
61
130
62
extension AnyCodable : Decodable {
131
63
public init ( from decoder: Decoder ) throws {
132
64
let container = try decoder. singleValueContainer ( )
133
65
134
66
if container. decodeNil ( ) {
135
- self . init ( NSNull ( ) )
67
+ self = . null
136
68
} else if let bool = try ? container. decode ( Bool . self) {
137
- self . init ( bool)
69
+ self = . bool ( bool)
138
70
} else if let int = try ? container. decode ( Int . self) {
139
- self . init ( int)
140
- } else if let uint = try ? container. decode ( UInt . self) {
141
- self . init ( uint)
71
+ self = . int( int)
142
72
} else if let double = try ? container. decode ( Double . self) {
143
- self . init ( double)
73
+ self = . double ( double)
144
74
} else if let string = try ? container. decode ( String . self) {
145
- self . init ( string)
75
+ self = . string ( string)
146
76
} else if let array = try ? container. decode ( [ AnyCodable ] . self) {
147
- self . init ( array . map { $0 . value } )
77
+ self = . array ( array )
148
78
} else if let dictionary = try ? container. decode ( [ String : AnyCodable ] . self) {
149
- self . init ( dictionary . mapValues { $0 . value } )
79
+ self = . object ( dictionary )
150
80
} else {
151
81
throw DecodingError . dataCorruptedError ( in: container, debugDescription: " AnyCodable value cannot be decoded " )
152
82
}
153
83
}
154
84
}
155
85
156
- extension AnyCodable : Equatable {
157
- public static func == ( lhs: AnyCodable , rhs: AnyCodable ) -> Bool {
158
- switch ( lhs. value, rhs. value) {
159
- case is ( Void , Void ) :
160
- return true
161
- case let ( lhs as Bool , rhs as Bool ) :
162
- return lhs == rhs
163
- case let ( lhs as Int , rhs as Int ) :
164
- return lhs == rhs
165
- case let ( lhs as Int8 , rhs as Int8 ) :
166
- return lhs == rhs
167
- case let ( lhs as Int16 , rhs as Int16 ) :
168
- return lhs == rhs
169
- case let ( lhs as Int32 , rhs as Int32 ) :
170
- return lhs == rhs
171
- case let ( lhs as Int64 , rhs as Int64 ) :
172
- return lhs == rhs
173
- case let ( lhs as UInt , rhs as UInt ) :
174
- return lhs == rhs
175
- case let ( lhs as UInt8 , rhs as UInt8 ) :
176
- return lhs == rhs
177
- case let ( lhs as UInt16 , rhs as UInt16 ) :
178
- return lhs == rhs
179
- case let ( lhs as UInt32 , rhs as UInt32 ) :
180
- return lhs == rhs
181
- case let ( lhs as UInt64 , rhs as UInt64 ) :
182
- return lhs == rhs
183
- case let ( lhs as Float , rhs as Float ) :
184
- return lhs == rhs
185
- case let ( lhs as Double , rhs as Double ) :
186
- return lhs == rhs
187
- case let ( lhs as String , rhs as String ) :
188
- return lhs == rhs
189
- case let ( lhs as [ String : String ] , rhs as [ String : String ] ) :
190
- return lhs == rhs
191
- case let ( lhs as [ String : Int ] , rhs as [ String : Int ] ) :
192
- return lhs == rhs
193
- case let ( lhs as [ String : Double ] , rhs as [ String : Double ] ) :
194
- return lhs == rhs
195
- case let ( lhs as [ String : Bool ] , rhs as [ String : Bool ] ) :
196
- return lhs == rhs
197
- case let ( lhs as [ String : AnyCodable ] , rhs as [ String : AnyCodable ] ) :
198
- return lhs == rhs
199
- case let ( lhs as [ String ] , rhs as [ String ] ) :
200
- return lhs == rhs
201
- case let ( lhs as [ Int ] , rhs as [ Int ] ) :
202
- return lhs == rhs
203
- case let ( lhs as [ Double ] , rhs as [ Double ] ) :
204
- return lhs == rhs
205
- case let ( lhs as [ Bool ] , rhs as [ Bool ] ) :
206
- return lhs == rhs
207
- case let ( lhs as [ AnyCodable ] , rhs as [ AnyCodable ] ) :
208
- return lhs == rhs
209
- default :
210
- return false
211
- }
212
- }
213
- }
214
-
215
86
extension AnyCodable : CustomStringConvertible {
216
87
public var description : String {
217
- switch value {
218
- case is Void :
219
- return String ( describing: nil as Any ? )
220
- case let value as CustomStringConvertible :
221
- return value. description
222
- default :
223
- return String ( describing: value)
88
+ switch self {
89
+ case . string( let string) :
90
+ return " \" \( string. description) \" "
91
+ case . bool( let bool) :
92
+ return bool. description
93
+ case . int( let int) :
94
+ return int. description
95
+ case . double( let double) :
96
+ return double. description
97
+ case . object( let dictionary) :
98
+ return " [ \( dictionary. sorted ( by: { $0. key < $1. key } ) . map { " \" \( $0) \" : \( $1. description) " } . joined ( separator: " , " ) ) ] "
99
+ case . array( let array) :
100
+ return " [ \( array. map { $0. description } . joined ( separator: " , " ) ) ] "
101
+ case . null:
102
+ return " nil "
224
103
}
225
104
}
226
105
}
227
106
228
107
extension AnyCodable : CustomDebugStringConvertible {
229
108
public var debugDescription : String {
230
- switch value {
231
- case let value as CustomDebugStringConvertible :
232
- return " AnyCodable( \( value. debugDescription) ) "
233
- default :
234
- return " AnyCodable( \( description) ) "
235
- }
109
+ " AnyCodable( \( description) ) "
236
110
}
237
111
}
238
112
@@ -246,31 +120,81 @@ extension AnyCodable: ExpressibleByDictionaryLiteral {}
246
120
247
121
extension AnyCodable {
248
122
public init ( nilLiteral _: ( ) ) {
249
- self . init ( nil as Any ? )
123
+ self = . null
250
124
}
251
125
252
126
public init ( booleanLiteral value: Bool ) {
253
- self . init ( value)
127
+ self = . bool ( value)
254
128
}
255
129
256
130
public init ( integerLiteral value: Int ) {
257
- self . init ( value)
131
+ self = . int ( value)
258
132
}
259
133
260
134
public init ( floatLiteral value: Double ) {
261
- self . init ( value)
135
+ self = . double ( value)
262
136
}
263
137
264
138
public init ( stringLiteral value: String ) {
265
- self . init ( value)
139
+ self = . string ( value)
266
140
}
267
141
268
- public init ( arrayLiteral elements: Any ... ) {
269
- self . init ( elements)
142
+ public init ( arrayLiteral elements: AnyCodable ... ) {
143
+ self = . array ( elements)
270
144
}
271
145
272
- public init ( dictionaryLiteral elements: ( AnyHashable , Any ) ... ) {
273
- self . init ( [ AnyHashable: Any] ( elements, uniquingKeysWith: { first, _ in first } ) )
146
+ public init ( dictionaryLiteral elements: ( String , AnyCodable ) ... ) {
147
+ self = . object( [ String: AnyCodable] ( elements, uniquingKeysWith: { first, _ in first } ) )
148
+ }
149
+ }
150
+
151
+ // MARK: Backward compatibility
152
+ extension AnyCodable {
153
+ public var value : Any {
154
+ switch self {
155
+ case . string( let string) :
156
+ return string
157
+ case . bool( let bool) :
158
+ return bool
159
+ case . int( let int) :
160
+ return int
161
+ case . double( let double) :
162
+ return double
163
+ case . object( let dictionary) :
164
+ return dictionary. mapValues { $0. value }
165
+ case . array( let array) :
166
+ return array. map { $0. value }
167
+ case . null:
168
+ return Optional < Any > . none as Any
169
+ }
170
+ }
171
+
172
+ public init ( _ value: Bool ) {
173
+ self = . bool( value)
174
+ }
175
+
176
+ public init < T: BinaryInteger > ( _ value: T ) {
177
+ self = . int( Int ( value) )
178
+ }
179
+
180
+ public init < T: StringProtocol > ( _ value: T ) {
181
+ self = . string( String ( value) )
182
+ }
183
+
184
+ public init < T: BinaryFloatingPoint > ( _ value: T ) {
185
+ self = . double( Double ( value) )
186
+ }
187
+
188
+ public init ( _ value: [ AnyCodable ] ) {
189
+ self = . array( value)
190
+ }
191
+
192
+ public init ( _ value: [ String : AnyCodable ] ) {
193
+ self = . object( value)
194
+ }
195
+
196
+ public init ( _ value: ( ) ) {
197
+ self = . null
274
198
}
275
199
}
276
200
0 commit comments