Skip to content

Commit 6640d9d

Browse files
feat: Adds AnyVal type
This centralizes operations performed across all vals.
1 parent 4202901 commit 6640d9d

File tree

3 files changed

+59
-12
lines changed

3 files changed

+59
-12
lines changed

Sources/Haystack/Dict.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,8 @@ public extension Dict {
105105
)
106106
}
107107
} else {
108-
typeLoop: for type in ValType.allCases {
109-
if let val = try? container.decode(type.type, forKey: key) {
110-
elements[key.stringValue] = val
111-
break typeLoop
112-
}
113-
}
108+
let val = try container.decode(AnyVal.self, forKey: key)
109+
elements[key.stringValue] = val.val
114110
}
115111
}
116112
self.elements = elements

Sources/Haystack/List.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,8 @@ public extension List {
4242

4343
var elements = [any Val]()
4444
containerLoop: while !container.isAtEnd {
45-
typeLoop: for type in ValType.allCases {
46-
if let val = try? container.decode(type.type) {
47-
elements.append(val)
48-
break typeLoop
49-
}
50-
}
45+
let val = try container.decode(AnyVal.self)
46+
elements.append(val.val)
5147
}
5248
self.elements = elements
5349
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/// This type-erased struct centralizes general operations that may act across different Haystack value types unknown
2+
/// at compile time like equality, decoding, and comparison.
3+
struct AnyVal: Codable, Hashable, Sendable {
4+
/// The underlying value of the AnyVal, which conforms to the Val protocol.
5+
let val: any Val
6+
7+
init(_ val: any Val) {
8+
self.val = val
9+
}
10+
11+
func toZinc() -> String {
12+
return val.toZinc()
13+
}
14+
}
15+
16+
// AnyVal + Equatable
17+
extension AnyVal {
18+
static func == (lhs: AnyVal, rhs: AnyVal) -> Bool {
19+
return lhs.val.equals(rhs.val)
20+
}
21+
}
22+
23+
// AnyVal + Codable
24+
extension AnyVal {
25+
/// Read from decodable data
26+
/// See [JSON format](https://project-haystack.org/doc/docHaystack/Json#list)
27+
init(from decoder: Decoder) throws {
28+
typeLoop: for type in ValType.allCases {
29+
if let val = try? type.type.init(from: decoder) {
30+
self = .init(val)
31+
return
32+
}
33+
}
34+
throw DecodingError.typeMismatch(
35+
AnyVal.self,
36+
.init(
37+
codingPath: decoder.codingPath,
38+
debugDescription: "No Val type matched"
39+
)
40+
)
41+
}
42+
43+
/// Write to encodable data
44+
/// See [JSON format](https://project-haystack.org/doc/docHaystack/Json#list)
45+
func encode(to encoder: Encoder) throws {
46+
try val.encode(to: encoder)
47+
}
48+
}
49+
50+
// AnyVal + Hashable
51+
extension AnyVal {
52+
func hash(into hasher: inout Hasher) {
53+
hasher.combine(val)
54+
}
55+
}

0 commit comments

Comments
 (0)