// Package nodeset provides Set, the engine's node-id set: the substrate // query results compose through (intersect, union, subtract). Roaring-backed // behind a private representation; the Rust NodeSet's adaptive dense // small-set arm can be added later without any API change, so callers must // never assume the backing.
package nodeset import ( ) // Set is a set of node ids. type Set struct { bm *roaring.Bitmap } // New returns an empty set. func () *Set { return &Set{bm: roaring.New()} } // Of returns a set of the given ids. func ( ...uint32) *Set { return &Set{bm: roaring.BitmapOf(...)} } // FromBitmap wraps a roaring bitmap. The set takes ownership; the caller // must not mutate bm afterwards. func ( *roaring.Bitmap) *Set { return &Set{bm: } } // Bitmap exposes the underlying roaring bitmap for serialization and // interop. Callers must not mutate it. func ( *Set) () *roaring.Bitmap { return .bm } // Clone returns an independent copy. func ( *Set) () *Set { return &Set{bm: .bm.Clone()} } // Len is the number of ids in the set (cardinality). func ( *Set) () int { return int(.bm.GetCardinality()) } // IsEmpty reports whether the set holds no ids. func ( *Set) () bool { return .bm.IsEmpty() } // Contains reports whether id is in the set. func ( *Set) ( uint32) bool { return .bm.Contains() } // Insert adds id, reporting whether it was newly added. func ( *Set) ( uint32) bool { return .bm.CheckedAdd() } // Remove deletes id, reporting whether it had been present. func ( *Set) ( uint32) bool { return .bm.CheckedRemove() } // Min is the smallest id; ok is false for an empty set. func ( *Set) () ( uint32, bool) { if .bm.IsEmpty() { return 0, false } return .bm.Minimum(), true } // Max is the largest id; ok is false for an empty set. func ( *Set) () ( uint32, bool) { if .bm.IsEmpty() { return 0, false } return .bm.Maximum(), true } // AsRange reports the set as a contiguous half-open [lo, hi) range, iff it // is non-empty and gap-free (a set of n ids spanning [min, max] is gap-free // exactly when max-min+1 == n, so this is O(1)). Callers must keep a correct // fallback (Iter) for when ok is false. func ( *Set) () (, uint32, bool) { , := .Min() if ! { return 0, 0, false } , := .Max() := uint64() - uint64() + 1 if != uint64(.Len()) || == ^uint32(0) { return 0, 0, false } return , + 1, true } // Iter iterates the set's ids in ascending order. The accessor is a // thin inlinable closure constructor over iterYield, so a direct // `for range` over it devirtualizes at the call site and the loop body // compiles as straight code rather than a heap-allocated yield closure. func ( *Set) () iter.Seq[uint32] { return func( func(uint32) bool) { .iterYield() } } // iterYield walks the bitmap in ascending order via the buffered many // iterator (one 64-id chunk at a time); yield never escapes. func ( *Set) ( func(uint32) bool) { := .bm.ManyIterator() var [64]uint32 for { := .NextMany([:]) if == 0 { return } for , := range [:] { if !() { return } } } } // ToSlice returns the ids in ascending order. func ( *Set) () []uint32 { return .bm.ToArray() } // And returns the intersection of s and other; neither operand is mutated. func ( *Set) ( *Set) *Set { return &Set{bm: roaring.And(.bm, .bm)} } // Or returns the union of s and other; neither operand is mutated. func ( *Set) ( *Set) *Set { return &Set{bm: roaring.Or(.bm, .bm)} } // AndNot returns the difference s - other; neither operand is mutated. func ( *Set) ( *Set) *Set { return &Set{bm: roaring.AndNot(.bm, .bm)} } // Equals reports element-for-element equality. func ( *Set) ( *Set) bool { return .bm.Equals(.bm) } // IterChunks walks the set in ascending order one buf-sized chunk at a // time, reusing buf; yield returning false stops the walk. The chunk // form lets batch consumers sweep columnar predicates over many ids per // dispatch instead of paying a closure per id. func ( *Set) ( []uint32, func([]uint32) bool) { := .bm.ManyIterator() for { := .NextMany() if == 0 { return } if !([:]) { return } } }