wip
This commit is contained in:
David Roman 2023-06-06 22:47:18 +01:00
parent c29b50a475
commit 28761e580d
No known key found for this signature in database
GPG Key ID: 7058646EEFCB70A7
3 changed files with 37 additions and 28 deletions

View File

@ -65,8 +65,8 @@ extension PlatformEntity {
}
@_spi(Internals)
public var allDescendants: [Base] {
self.descendants.reduce([self~]) { $0 + $1.allDescendants~ }
public var allDescendants: some Sequence<Base> {
recursiveSequence([self~], children: { $0.descendants~ }).dropFirst()
}
func nearestCommonAncestor(with other: Base) -> Base? {
@ -79,21 +79,11 @@ extension PlatformEntity {
return nearestAncestor
}
func descendantsBetween(_ bottomEntity: Base, and topEntity: Base) -> [Base] {
var result: [Base] = []
var entered = false
for descendant in self.allDescendants {
if descendant === bottomEntity {
entered = true
} else if descendant === topEntity {
break
} else if entered {
result.append(descendant)
}
}
return result
func allDescendants(between bottomEntity: Base, and topEntity: Base) -> some Sequence<Base> {
self.allDescendants
.lazy
.drop(while: { $0 !== bottomEntity })
.prefix(while: { $0 !== topEntity })
}
func receiver<PlatformSpecificEntity: PlatformEntity>(
@ -102,14 +92,14 @@ extension PlatformEntity {
) -> PlatformSpecificEntity? {
let frontEntity = self
guard
let backEntity = Array(frontEntity.ancestors).last?.entityWithTag(anchorID.hashValue),
let backEntity = ContiguousArray(frontEntity.ancestors).last?.entityWithTag(anchorID.hashValue),
let commonAncestor = backEntity.nearestCommonAncestor(with: frontEntity~)
else {
return nil
}
return commonAncestor
.descendantsBetween(backEntity~, and: frontEntity~)
.allDescendants(between: backEntity~, and: frontEntity~)
.compactMap { $0 as? PlatformSpecificEntity }
.first
}

28
Sources/Utils.swift Normal file
View File

@ -0,0 +1,28 @@
postfix operator ~
postfix func ~ <LHS, T>(lhs: LHS) -> T {
lhs as! T
}
postfix func ~ <LHS, T>(lhs: LHS?) -> T? {
lhs as? T
}
func recursiveSequence<S: Sequence>(_ sequence: S, children: @escaping (S.Element) -> S) -> AnySequence<S.Element> {
AnySequence {
var mainIterator = sequence.makeIterator()
// Current iterator, or `nil` if all sequences are exhausted:
var iterator: AnyIterator<S.Element>?
return AnyIterator {
guard let iterator, let element = iterator.next() else {
if let element = mainIterator.next() {
iterator = recursiveSequence(children(element), children: children).makeIterator()
return element
}
return nil
}
return element
}
}
}

View File

@ -1,9 +0,0 @@
postfix operator ~
postfix func ~ <LHS, T>(lhs: LHS) -> T {
lhs as! T
}
postfix func ~ <LHS, T>(lhs: LHS?) -> T? {
lhs as? T
}