Skip to content

Commit 12f3699

Browse files
committed
Add element-containment checking
1 parent c416e01 commit 12f3699

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

Sources/EmbeddedIntegerCollection/EmbeddedIntegerCollection.swift

+28
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ extension EmbeddedIntegerCollection: RandomAccessCollection, MutableCollection {
227227
return indices.distance(from: start, to: end)
228228
}
229229

230+
@inlinable
231+
public func _customContainsEquatableElement(_ element: Element) -> Bool? {
232+
return .some(hasElement(of: element))
233+
}
230234
public func withContiguousStorageIfAvailable<R>(
231235
_ body: (UnsafeBufferPointer<Element>) throws -> R
232236
) rethrows -> R? {
@@ -511,4 +515,28 @@ extension EmbeddedIntegerCollection {
511515
/// every embedded element.
512516
@usableFromInline
513517
static var allEmbeddedOnes: Wrapped { Wrapped.max / Wrapped(Element.max) }
518+
/// Generates a collection with every element having a value of
519+
/// just its highest bit set.
520+
@usableFromInline
521+
static var allEmbeddedHighBits: Wrapped {
522+
allEmbeddedOnes << (Element.bitWidth - 1)
523+
}
524+
525+
/// Whether at least one embedded element has a value of zero.
526+
@usableFromInline
527+
var hasZeroElement: Bool {
528+
(container &- Self.allEmbeddedOnes) & ~container & Self.allEmbeddedHighBits
529+
!= 0
530+
}
531+
/// Whether at least one embedded element has the given value.
532+
///
533+
/// - Parameter value: The value to compare against.
534+
/// - Returns: `true` if at least one embedded element equals `value`,
535+
/// `false` otherwise.
536+
@usableFromInline
537+
func hasElement(of value: Element) -> Bool {
538+
var values = Self(repeating: value, iteratingFrom: self.endianness)
539+
values.container ^= self.container
540+
return values.hasZeroElement
541+
}
514542
}

Tests/EmbeddedIntegerCollectionTests/EmbeddedIntegerCollectionTests.swift

+13
Original file line numberDiff line numberDiff line change
@@ -415,3 +415,16 @@ func nonOctetInspectContiguousStorage() async throws {
415415
} == nil
416416
)
417417
}
418+
419+
@Test("Element search", arguments: EmbeddedIterationDirection.allCases)
420+
func containment(_ endianness: EmbeddedIterationDirection) async throws {
421+
let collection = EmbeddedIntegerCollection(
422+
embedding: UInt8.self,
423+
within: 0x4501_6723 as UInt32,
424+
iteratingFrom: endianness
425+
)
426+
let fullRange: ClosedRange<UInt8> = 0...0xFF
427+
#expect(
428+
fullRange.filter { collection.contains($0) } == [0x01, 0x23, 0x45, 0x67]
429+
)
430+
}

0 commit comments

Comments
 (0)