Skip to content

Commit f42d492

Browse files
authored
Add AnyHashable2 implementation (#190)
1 parent a577f66 commit f42d492

File tree

3 files changed

+123
-1
lines changed

3 files changed

+123
-1
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
//
2+
// AnyHashable2.swift
3+
// OpenSwiftUICore
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Complete
7+
// ID: 12EE2013F9611424839A13CDF1FE08D2 (SwiftUICore)
8+
9+
fileprivate class AnyHashableBox {
10+
func `as`<T>(type: T.Type) -> T? where T: Hashable { nil }
11+
var description: String { "" }
12+
var anyValue: any Hashable { preconditionFailure("") }
13+
func isEqual(to other: AnyHashableBox) -> Bool { false }
14+
func hash(into hasher: inout Hasher) {}
15+
}
16+
17+
fileprivate class _AnyHashableBox<Value>: AnyHashableBox where Value: Hashable {
18+
let value: Value
19+
20+
init(_ value: Value) {
21+
self.value = value
22+
}
23+
24+
override func `as`<T>(type: T.Type) -> T? where T: Hashable {
25+
value as? T
26+
}
27+
28+
override var description: String {
29+
String(describing: value)
30+
}
31+
32+
override var anyValue: any Hashable {
33+
value
34+
}
35+
36+
override func isEqual(to other: AnyHashableBox) -> Bool {
37+
guard let otherBox = other as? _AnyHashableBox<Value> else {
38+
return false
39+
}
40+
return value == otherBox.value
41+
}
42+
43+
override func hash(into hasher: inout Hasher) {
44+
hasher.combine(ObjectIdentifier(Value.self))
45+
hasher.combine(value)
46+
}
47+
}
48+
49+
package struct AnyHashable2: Hashable, CustomStringConvertible {
50+
private var box: AnyHashableBox
51+
52+
package init<T>(_ value: T) where T: Hashable {
53+
box = _AnyHashableBox(value)
54+
}
55+
56+
package func `as`<T>(type: T.Type) -> T? where T: Hashable {
57+
box.as(type: type)
58+
}
59+
60+
package var anyValue: any Hashable {
61+
box.anyValue
62+
}
63+
64+
package var anyHashable: AnyHashable {
65+
AnyHashable(box.anyValue)
66+
}
67+
68+
package var description: String {
69+
box.description
70+
}
71+
72+
package static func == (lhs: AnyHashable2, rhs: AnyHashable2) -> Bool {
73+
guard lhs.box !== rhs.box else {
74+
return true
75+
}
76+
return lhs.box.isEqual(to: rhs.box)
77+
}
78+
79+
package func hash(into hasher: inout Hasher) {
80+
box.hash(into: &hasher)
81+
}
82+
}
83+
84+
extension AnyHashable2: _HasCustomAnyHashableRepresentation {
85+
package func _toCustomAnyHashable() -> AnyHashable? {
86+
anyHashable
87+
}
88+
}

Sources/OpenSwiftUICore/Data/Other/BitVector.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//
55
// Audited for iOS 18.0
66
// Status: Complete
7-
// ID: 8433FC349A42D7F59B64CD7FA08D81A9
7+
// ID: 8433FC349A42D7F59B64CD7FA08D81A9 (SwiftUICore)
88

99
import Foundation
1010

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//
2+
// AnyHashable2Tests.swift
3+
// OpenSwiftUICoreTests
4+
5+
import OpenSwiftUICore
6+
import Testing
7+
8+
struct AnyHashable2Tests {
9+
@Test
10+
func value() {
11+
struct ValueA: Hashable {
12+
var value: Int
13+
}
14+
15+
struct ValueB: Hashable {
16+
var value: Int
17+
}
18+
19+
let valueA = ValueA(value: 1)
20+
let valueB = ValueB(value: 1)
21+
22+
let anyHashableA = AnyHashable(valueA)
23+
let anyHashableB = AnyHashable(valueB)
24+
25+
let anyHashable2A = AnyHashable2(valueA)
26+
let anyHashable2B = AnyHashable2(valueB)
27+
28+
#expect(anyHashableA.hashValue == anyHashableB.hashValue)
29+
#expect(anyHashableA != anyHashableB)
30+
31+
#expect(anyHashable2A.hashValue != anyHashable2B.hashValue)
32+
#expect(anyHashable2A != anyHashable2B)
33+
}
34+
}

0 commit comments

Comments
 (0)