A fast, safe, and efficient CBOR serialization library for Swift on any platform.
swiftpackageindex.com/thecoolwinter/CBOR/1.1.1/documentation/cbor
atproto
swift
cbor
1// From https://github.com/Flight-School/AnyCodable/blob/master/Sources/AnyCodable/AnyDecodable.swift
2
3// swiftlint:disable cyclomatic_complexity
4// swiftlint:disable line_length
5// swiftlint:disable type_name
6
7#if canImport(FoundationEssentials)
8import FoundationEssentials
9#else
10import Foundation
11#endif
12
13/**
14 A type-erased `Decodable` value.
15
16 The `AnyDecodable` type forwards decoding responsibilities
17 to an underlying value, hiding its specific underlying type.
18
19 You can decode mixed-type values in dictionaries
20 and other collections that require `Decodable` conformance
21 by declaring their contained type to be `AnyDecodable`:
22
23 let json = """
24 {
25 "boolean": true,
26 "integer": 42,
27 "double": 3.141592653589793,
28 "string": "string",
29 "array": [1, 2, 3],
30 "nested": {
31 "a": "alpha",
32 "b": "bravo",
33 "c": "charlie"
34 },
35 "null": null
36 }
37 """.data(using: .utf8)!
38
39 let decoder = JSONDecoder()
40 let dictionary = try! decoder.decode([String: AnyDecodable].self, from: json)
41 */
42struct AnyDecodable: Decodable {
43 let value: Any
44
45 init<T>(_ value: T?) {
46 self.value = value ?? ()
47 }
48}
49
50@usableFromInline
51protocol _AnyDecodable {
52 var value: Any { get }
53 init<T>(_ value: T?)
54}
55
56extension AnyDecodable: _AnyDecodable {}
57
58extension _AnyDecodable {
59 init(from decoder: Decoder) throws {
60 let container = try decoder.singleValueContainer()
61
62 if container.decodeNil() {
63 self.init(Optional<Self>.none)
64 } else if let bool = try? container.decode(Bool.self) {
65 self.init(bool)
66 } else if let int = try? container.decode(Int.self) {
67 self.init(int)
68 } else if let uint = try? container.decode(UInt.self) {
69 self.init(uint)
70 } else if let double = try? container.decode(Double.self) {
71 self.init(double)
72 } else if let string = try? container.decode(String.self) {
73 self.init(string)
74 } else if let array = try? container.decode([AnyDecodable].self) {
75 self.init(array.map { $0.value })
76 } else if let dictionary = try? container.decode([String: AnyDecodable].self) {
77 self.init(dictionary.mapValues { $0.value })
78 } else {
79 throw DecodingError.dataCorruptedError(in: container, debugDescription: "AnyDecodable value cannot be decoded")
80 }
81 }
82}
83
84extension AnyDecodable: Equatable {
85 static func == (lhs: AnyDecodable, rhs: AnyDecodable) -> Bool {
86 switch (lhs.value, rhs.value) {
87 case (Optional<Self>.none, Optional<Self>.none), is (Void, Void):
88 return true
89 case let (lhs as Bool, rhs as Bool):
90 return lhs == rhs
91 case let (lhs as Int, rhs as Int):
92 return lhs == rhs
93 case let (lhs as Int8, rhs as Int8):
94 return lhs == rhs
95 case let (lhs as Int16, rhs as Int16):
96 return lhs == rhs
97 case let (lhs as Int32, rhs as Int32):
98 return lhs == rhs
99 case let (lhs as Int64, rhs as Int64):
100 return lhs == rhs
101 case let (lhs as UInt, rhs as UInt):
102 return lhs == rhs
103 case let (lhs as UInt8, rhs as UInt8):
104 return lhs == rhs
105 case let (lhs as UInt16, rhs as UInt16):
106 return lhs == rhs
107 case let (lhs as UInt32, rhs as UInt32):
108 return lhs == rhs
109 case let (lhs as UInt64, rhs as UInt64):
110 return lhs == rhs
111 case let (lhs as Float, rhs as Float):
112 return lhs == rhs
113 case let (lhs as Double, rhs as Double):
114 return lhs == rhs
115 case let (lhs as String, rhs as String):
116 return lhs == rhs
117 case let (lhs as [String: AnyDecodable], rhs as [String: AnyDecodable]):
118 return lhs == rhs
119 case let (lhs as [AnyDecodable], rhs as [AnyDecodable]):
120 return lhs == rhs
121 default:
122 return false
123 }
124 }
125}
126
127extension AnyDecodable: CustomStringConvertible {
128 var description: String {
129 switch value {
130 case is Void:
131 return String(describing: nil as Any?)
132 case let value as CustomStringConvertible:
133 return value.description
134 default:
135 return String(describing: value)
136 }
137 }
138}
139
140extension AnyDecodable: CustomDebugStringConvertible {
141 var debugDescription: String {
142 switch value {
143 case let value as CustomDebugStringConvertible:
144 return "AnyDecodable(\(value.debugDescription))"
145 default:
146 return "AnyDecodable(\(description))"
147 }
148 }
149}
150
151extension AnyDecodable: Hashable {
152 func hash(into hasher: inout Hasher) {
153 switch value {
154 case let value as Bool:
155 hasher.combine(value)
156 case let value as Int:
157 hasher.combine(value)
158 case let value as Int8:
159 hasher.combine(value)
160 case let value as Int16:
161 hasher.combine(value)
162 case let value as Int32:
163 hasher.combine(value)
164 case let value as Int64:
165 hasher.combine(value)
166 case let value as UInt:
167 hasher.combine(value)
168 case let value as UInt8:
169 hasher.combine(value)
170 case let value as UInt16:
171 hasher.combine(value)
172 case let value as UInt32:
173 hasher.combine(value)
174 case let value as UInt64:
175 hasher.combine(value)
176 case let value as Float:
177 hasher.combine(value)
178 case let value as Double:
179 hasher.combine(value)
180 case let value as String:
181 hasher.combine(value)
182 case let value as [String: AnyDecodable]:
183 hasher.combine(value)
184 case let value as [AnyDecodable]:
185 hasher.combine(value)
186 default:
187 break
188 }
189 }
190}
191
192// swiftlint:enable cyclomatic_complexity
193// swiftlint:enable line_length
194// swiftlint:enable type_name