Skip to content

Commit 40811cf

Browse files
authored
Merge pull request #193 from lorentey/fleshing-out-PersistentSet
Fleshing out `PersistentSet`
2 parents 78a29df + 0b86bb1 commit 40811cf

31 files changed

+530
-95
lines changed

Sources/PersistentCollections/Node/_Node+Builder.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ extension _Node.Builder {
5959
assert(level.isAtRoot)
6060
switch self {
6161
case .empty:
62-
return _Node(storage: _emptySingleton, count: 0)
62+
return ._empty()
6363
case .item(let item, let h):
64-
return _Node._regularNode(item, h[level])
64+
return ._regularNode(item, h[level])
6565
case .node(let node, _):
6666
return node
6767
}

Sources/PersistentCollections/Node/_Node+Initializers.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
//===----------------------------------------------------------------------===//
1111

1212
extension _Node {
13+
@inlinable @inline(__always)
14+
internal static func _empty() -> _Node {
15+
_Node(storage: _emptySingleton, count: 0)
16+
}
17+
1318
@inlinable
1419
internal static func _collisionNode(
1520
_ hash: _Hash,

Sources/PersistentCollections/Node/_Node+Structural intersection.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111

1212
extension _Node {
1313
@inlinable
14-
internal func intersection(
14+
internal func intersection<Value2>(
1515
_ level: _Level,
1616
_ hashPrefix: _Hash,
17-
_ other: _Node
17+
_ other: _Node<Key, Value2>
1818
) -> Builder? {
1919
if self.raw.storage === other.raw.storage { return nil }
2020

@@ -102,10 +102,10 @@ extension _Node {
102102
}
103103

104104
@inlinable @inline(never)
105-
internal func _intersection_slow(
105+
internal func _intersection_slow<Value2>(
106106
_ level: _Level,
107107
_ hashPrefix: _Hash,
108-
_ other: _Node
108+
_ other: _Node<Key, Value2>
109109
) -> Builder? {
110110
let lc = self.isCollisionNode
111111
let rc = other.isCollisionNode

Sources/PersistentCollections/Node/_Node+Structural subtracting.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111

1212
extension _Node {
1313
@inlinable
14-
internal func subtracting(
14+
internal func subtracting<Value2>(
1515
_ level: _Level,
1616
_ hashPrefix: _Hash,
17-
_ other: _Node
17+
_ other: _Node<Key, Value2>
1818
) -> Builder? {
1919
if self.raw.storage === other.raw.storage { return .empty }
2020

@@ -107,10 +107,10 @@ extension _Node {
107107
}
108108

109109
@inlinable @inline(never)
110-
internal func _subtracting_slow(
110+
internal func _subtracting_slow<Value2>(
111111
_ level: _Level,
112112
_ hashPrefix: _Hash,
113-
_ other: _Node
113+
_ other: _Node<Key, Value2>
114114
) -> Builder? {
115115
let lc = self.isCollisionNode
116116
let rc = other.isCollisionNode

Sources/PersistentCollections/Node/_Node+Subtree Insertions.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@
1212
import _CollectionsUtilities
1313

1414
extension _Node {
15+
@inlinable
16+
internal mutating func insert(
17+
_ level: _Level,
18+
_ item: Element,
19+
_ hash: _Hash
20+
) -> (inserted: Bool, leaf: _UnmanagedNode, slot: _Slot) {
21+
insert(level, item.key, hash) { $0.initialize(to: item) }
22+
}
23+
1524
@inlinable
1625
internal mutating func insert(
1726
_ level: _Level,

Sources/PersistentCollections/PersistentDictionary/PersistentDictionary+Collection.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ extension PersistentDictionary: BidirectionalCollection {
109109
public subscript(i: Index) -> Element {
110110
precondition(_isValid(i), "Invalid index")
111111
precondition(i._path.isOnItem, "Can't get element at endIndex")
112-
return _Node.UnsafeHandle.read(i._path.node) {
112+
return _UnsafeHandle.read(i._path.node) {
113113
$0[item: i._path.currentItemSlot]
114114
}
115115
}

Sources/PersistentCollections/PersistentDictionary/PersistentDictionary+Initializers.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
extension PersistentDictionary {
1313
@inlinable
1414
public init() {
15-
self.init(_new: _Node(storage: _emptySingleton, count: 0))
15+
self.init(_new: ._empty())
1616
}
1717

1818
@inlinable
@@ -37,9 +37,7 @@ extension PersistentDictionary {
3737
self.init()
3838
for item in keysAndValues {
3939
let hash = _Hash(item.0)
40-
let r = _root.insert(.top, item.0, hash) {
41-
$0.initialize(to: item)
42-
}
40+
let r = _root.insert(.top, item, hash)
4341
precondition(r.inserted, "Duplicate key: '\(item.0)'")
4442
}
4543
_invariantCheck()

Sources/PersistentCollections/PersistentDictionary/PersistentDictionary+Values.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ extension PersistentDictionary {
1616
@usableFromInline
1717
internal typealias _Node = PersistentCollections._Node<Key, Value>
1818

19+
@usableFromInline
20+
internal typealias _UnsafeHandle = _Node.UnsafeHandle
21+
1922
@usableFromInline
2023
internal var _base: PersistentDictionary
2124

@@ -108,14 +111,14 @@ extension PersistentDictionary.Values: BidirectionalCollection {
108111
precondition(_base._isValid(index), "Invalid index")
109112
precondition(index._path.isOnItem, "Cannot set value at end index")
110113
let (leaf, slot) = _base._root.ensureUnique(level: .top, at: index._path)
111-
_Node.UnsafeHandle.update(leaf) { $0[item: slot].value = newValue }
114+
_UnsafeHandle.update(leaf) { $0[item: slot].value = newValue }
112115
_base._invalidateIndices()
113116
}
114117
_modify { // FIXME: Consider removing
115118
precondition(_base._isValid(index), "Invalid index")
116119
precondition(index._path.isOnItem, "Cannot set value at end index")
117120
let (leaf, slot) = _base._root.ensureUnique(level: .top, at: index._path)
118-
var item = _Node.UnsafeHandle.update(leaf) { $0.itemPtr(at: slot).move() }
121+
var item = _UnsafeHandle.update(leaf) { $0.itemPtr(at: slot).move() }
119122
defer {
120123
_Node.UnsafeHandle.update(leaf) {
121124
$0.itemPtr(at: slot).initialize(to: item)

Sources/PersistentCollections/PersistentDictionary/PersistentDictionary.swift

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ public struct PersistentDictionary<Key: Hashable, Value> {
1313
@usableFromInline
1414
internal typealias _Node = PersistentCollections._Node<Key, Value>
1515

16+
@usableFromInline
17+
internal typealias _UnsafeHandle = _Node.UnsafeHandle
18+
1619
@usableFromInline
1720
var _root: _Node
1821

@@ -284,7 +287,7 @@ extension PersistentDictionary {
284287
}
285288
_invalidateIndices()
286289
if r.inserted { return nil }
287-
return _Node.UnsafeHandle.update(r.leaf) {
290+
return _UnsafeHandle.update(r.leaf) {
288291
let p = $0.itemPtr(at: r.slot)
289292
let old = p.pointee.value
290293
p.pointee.value = value
@@ -302,7 +305,7 @@ extension PersistentDictionary {
302305
$0.initialize(to: (key, value))
303306
}
304307
if r.inserted { return true }
305-
_Node.UnsafeHandle.update(r.leaf) {
308+
_UnsafeHandle.update(r.leaf) {
306309
$0[item: r.slot].value = value
307310
}
308311
return false
@@ -335,7 +338,7 @@ extension PersistentDictionary {
335338
let r = _root.updateValue(.top, forKey: key, hash) {
336339
$0.initialize(to: (key, defaultValue()))
337340
}
338-
return try _Node.UnsafeHandle.update(r.leaf) {
341+
return try _UnsafeHandle.update(r.leaf) {
339342
try body(&$0[item: r.slot].value)
340343
}
341344
}

Sources/PersistentCollections/PersistentSet/PersistentSet+Collection.swift

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ extension PersistentSet: BidirectionalCollection {
109109
public subscript(i: Index) -> Element {
110110
precondition(_isValid(i), "Invalid index")
111111
precondition(i._path.isOnItem, "Can't get element at endIndex")
112-
return _Node.UnsafeHandle.read(i._path.node) {
112+
return _UnsafeHandle.read(i._path.node) {
113113
$0[item: i._path.currentItemSlot].key
114114
}
115115
}
@@ -173,4 +173,43 @@ extension PersistentSet: BidirectionalCollection {
173173
precondition(limited, "Index offset out of bounds")
174174
return nil
175175
}
176+
177+
@inlinable @inline(__always)
178+
public func _customIndexOfEquatableElement(
179+
_ element: Element
180+
) -> Index?? {
181+
_index(of: element)
182+
}
183+
184+
@inlinable @inline(__always)
185+
public func _customLastIndexOfEquatableElement(
186+
_ element: Element
187+
) -> Index?? {
188+
_index(of: element)
189+
}
190+
191+
@inlinable
192+
internal func _index(of element: Element) -> Index? {
193+
let hash = _Hash(element)
194+
guard let path = _root.path(to: element, hash) else { return nil }
195+
return Index(_root: _root.unmanaged, version: _version, path: path)
196+
}
197+
198+
public func _failEarlyRangeCheck(
199+
_ index: Index, bounds: Range<Index>
200+
) {
201+
precondition(_isValid(index))
202+
}
203+
204+
public func _failEarlyRangeCheck(
205+
_ index: Index, bounds: ClosedRange<Index>
206+
) {
207+
precondition(_isValid(index))
208+
}
209+
210+
public func _failEarlyRangeCheck(
211+
_ range: Range<Index>, bounds: Range<Index>
212+
) {
213+
precondition(_isValid(range.lowerBound) && _isValid(range.upperBound))
214+
}
176215
}

0 commit comments

Comments
 (0)