Skip to content

Commit b3789f8

Browse files
Updated primitive value unwrapping to enable static type optimizations during compilation
This should be faster than the previous case, since the compiler should be able to optimize the switch away when it inlines the function for a specific generic type.
1 parent d63220f commit b3789f8

File tree

1 file changed

+21
-23
lines changed

1 file changed

+21
-23
lines changed

Sources/DynamicCodable/CoderInternals.swift

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -71,30 +71,28 @@ extension DynamicCodable {
7171

7272
@inline(__always)
7373
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 = ()
74+
switch T.self {
75+
case is Keyed.Type: if case .keyed(let keyed) = self { return unsafeBitCast(keyed, to: T.self) }
76+
case is Unkeyed.Type: if case .unkeyed(let unkeyed) = self { return unsafeBitCast(unkeyed, to: T.self) }
77+
case is Nil.Type: if case .nil = self { return unsafeBitCast(Nil.none, to: T.self) }
78+
case is Bool.Type: if case .bool(let bool) = self { return unsafeBitCast(bool, to: T.self) }
79+
case is String.Type: if case .string(let string) = self { return unsafeBitCast(string, to: T.self) }
80+
case is Float64.Type: if case .float64(let float64) = self { return unsafeBitCast(float64, to: T.self) }
81+
case is Float32.Type: if case .float64(let float32) = self { return unsafeBitCast(float32, to: T.self) }
82+
case is Int.Type: if case .int(let int) = self { return unsafeBitCast(int, to: T.self) }
83+
case is Int8.Type: if case .int8(let int8) = self { return unsafeBitCast(int8, to: T.self) }
84+
case is Int16.Type: if case .int16(let int16) = self { return unsafeBitCast(int16, to: T.self) }
85+
case is Int32.Type: if case .int32(let int32) = self { return unsafeBitCast(int32, to: T.self) }
86+
case is Int64.Type: if case .int64(let int64) = self { return unsafeBitCast(int64, to: T.self) }
87+
case is UInt.Type: if case .uint(let uint) = self { return unsafeBitCast(uint, to: T.self) }
88+
case is UInt8.Type: if case .uint8(let uint8) = self { return unsafeBitCast(uint8, to: T.self) }
89+
case is UInt16.Type: if case .uint16(let uint16) = self { return unsafeBitCast(uint16, to: T.self) }
90+
case is UInt32.Type: if case .uint32(let uint32) = self { return unsafeBitCast(uint32, to: T.self) }
91+
case is UInt64.Type: if case .uint64(let uint64) = self { return unsafeBitCast(uint64, to: T.self) }
92+
case is Empty.Type: if case .empty = self { return unsafeBitCast((), to: T.self) }
93+
default: break // TODO: We should do something different here, so we can ignore this case in the caller. Perhaps return a specialized error?
9594
}
9695

97-
guard let value = value as? T else { try errorHandler() }
98-
return value
96+
try errorHandler()
9997
}
10098
}

0 commit comments

Comments
 (0)