parent
c29b50a475
commit
28761e580d
|
@ -65,8 +65,8 @@ extension PlatformEntity {
|
||||||
}
|
}
|
||||||
|
|
||||||
@_spi(Internals)
|
@_spi(Internals)
|
||||||
public var allDescendants: [Base] {
|
public var allDescendants: some Sequence<Base> {
|
||||||
self.descendants.reduce([self~]) { $0 + $1.allDescendants~ }
|
recursiveSequence([self~], children: { $0.descendants~ }).dropFirst()
|
||||||
}
|
}
|
||||||
|
|
||||||
func nearestCommonAncestor(with other: Base) -> Base? {
|
func nearestCommonAncestor(with other: Base) -> Base? {
|
||||||
|
@ -79,21 +79,11 @@ extension PlatformEntity {
|
||||||
return nearestAncestor
|
return nearestAncestor
|
||||||
}
|
}
|
||||||
|
|
||||||
func descendantsBetween(_ bottomEntity: Base, and topEntity: Base) -> [Base] {
|
func allDescendants(between bottomEntity: Base, and topEntity: Base) -> some Sequence<Base> {
|
||||||
var result: [Base] = []
|
self.allDescendants
|
||||||
var entered = false
|
.lazy
|
||||||
|
.drop(while: { $0 !== bottomEntity })
|
||||||
for descendant in self.allDescendants {
|
.prefix(while: { $0 !== topEntity })
|
||||||
if descendant === bottomEntity {
|
|
||||||
entered = true
|
|
||||||
} else if descendant === topEntity {
|
|
||||||
break
|
|
||||||
} else if entered {
|
|
||||||
result.append(descendant)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func receiver<PlatformSpecificEntity: PlatformEntity>(
|
func receiver<PlatformSpecificEntity: PlatformEntity>(
|
||||||
|
@ -102,14 +92,14 @@ extension PlatformEntity {
|
||||||
) -> PlatformSpecificEntity? {
|
) -> PlatformSpecificEntity? {
|
||||||
let frontEntity = self
|
let frontEntity = self
|
||||||
guard
|
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~)
|
let commonAncestor = backEntity.nearestCommonAncestor(with: frontEntity~)
|
||||||
else {
|
else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return commonAncestor
|
return commonAncestor
|
||||||
.descendantsBetween(backEntity~, and: frontEntity~)
|
.allDescendants(between: backEntity~, and: frontEntity~)
|
||||||
.compactMap { $0 as? PlatformSpecificEntity }
|
.compactMap { $0 as? PlatformSpecificEntity }
|
||||||
.first
|
.first
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
|
||||||
}
|
|
Loading…
Reference in New Issue