Skip to content

Commit f4c7a38

Browse files
Added a DynamicCodableDecoder
1 parent 9f4a25f commit f4c7a38

File tree

3 files changed

+541
-0
lines changed

3 files changed

+541
-0
lines changed

Sources/DynamicCodable/CoderInternals.swift

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,95 @@
66
// Copyright © 2021 Mochi Development, Inc. All rights reserved.
77
//
88

9+
extension Dictionary where Key == DynamicCodable.Key, Value == DynamicCodable {
10+
@inline(__always)
11+
subscript(key: CodingKey) -> DynamicCodable? {
12+
if let intKey = key.intValue, let value = self[intKey] {
13+
return value
14+
} else if let value = self[key.stringValue] {
15+
return value
16+
}
17+
return nil
18+
}
19+
}
20+
21+
struct DynamicCoderCodingKey: CodingKey {
22+
public var stringValue: String
23+
public var intValue: Int?
24+
25+
public init?(stringValue: String) {
26+
self.stringValue = stringValue
27+
self.intValue = nil
28+
}
29+
30+
public init?(intValue: Int) {
31+
self.stringValue = "\(intValue)"
32+
self.intValue = intValue
33+
}
34+
35+
init(stringValue: String, intValue: Int?) {
36+
self.stringValue = stringValue
37+
self.intValue = intValue
38+
}
39+
40+
init(index: Int) {
41+
self.stringValue = "Index \(index)"
42+
self.intValue = index
43+
}
44+
45+
static let `super` = DynamicCoderCodingKey(stringValue: "super", intValue: nil)
46+
}
47+
48+
extension DynamicCodable {
49+
var debugDataTypeDescription: String {
50+
switch self {
51+
case .keyed(_): return "a keyed container"
52+
case .unkeyed(_): return "an unkeyed container"
53+
case .nil: return "nil"
54+
case .bool(_): return "a boolean"
55+
case .string(_): return "a string"
56+
case .float64(_): return "a float64"
57+
case .float32(_): return "a float32"
58+
case .int(_): return "an int"
59+
case .int8(_): return "an int8"
60+
case .int16(_): return "an int16"
61+
case .int32(_): return "an int32"
62+
case .int64(_): return "an int64"
63+
case .uint(_): return "a uint"
64+
case .uint8(_): return "a uint8"
65+
case .uint16(_): return "a uint16"
66+
case .uint32(_): return "a uint32"
67+
case .uint64(_): return "a uint64"
68+
case .empty: return "an empty container"
69+
}
70+
}
71+
72+
@inline(__always)
73+
func unwrap<T>(errorHandler: () throws -> Never) rethrows -> T {
74+
let value: Any
75+
76+
switch self {
77+
case .keyed(let keyed): value = keyed
78+
case .unkeyed(let unkeyed): value = unkeyed
79+
case .nil: value = Nil.none as Any
80+
case .bool(let bool): value = bool
81+
case .string(let string): value = string
82+
case .float64(let float64): value = float64
83+
case .float32(let float32): value = float32
84+
case .int(let int): value = int
85+
case .int8(let int8): value = int8
86+
case .int16(let int16): value = int16
87+
case .int32(let int32): value = int32
88+
case .int64(let int64): value = int64
89+
case .uint(let uint): value = uint
90+
case .uint8(let uint8): value = uint8
91+
case .uint16(let uint16): value = uint16
92+
case .uint32(let uint32): value = uint32
93+
case .uint64(let uint64): value = uint64
94+
case .empty: value = ()
95+
}
96+
97+
guard let value = value as? T else { try errorHandler() }
98+
return value
99+
}
100+
}

0 commit comments

Comments
 (0)