Documentation
¶
Index ¶
- Constants
- func CidrForFringe(octets []byte, depth int, is4 bool, lastOctet uint8) netip.Prefix
- func CidrFromPath(path StridePath, depth int, is4 bool, idx uint8) netip.Prefix
- func CmpIndexRank(aIdx, bIdx uint8) int
- func CmpPrefix(a, b netip.Prefix) int
- func IsFringe(depth int, pfx netip.Prefix) bool
- func LastOctetPlusOneAndLastBits(pfx netip.Prefix) (lastOctetPlusOne int, lastBits uint8)
- type BartNode
- func (n *BartNode[V]) AllChildren() iter.Seq2[uint8, any]
- func (n *BartNode[V]) AllIndices() iter.Seq2[uint8, V]
- func (n *BartNode[V]) AllRec(path StridePath, depth int, is4 bool, yield func(netip.Prefix, V) bool) bool
- func (n *BartNode[V]) AllRecSorted(path StridePath, depth int, is4 bool, yield func(netip.Prefix, V) bool) bool
- func (n *BartNode[V]) ChildCount() int
- func (n *BartNode[V]) CloneFlat(cloneFn value.CloneFunc[V]) *BartNode[V]
- func (n *BartNode[V]) CloneRec(cloneFn value.CloneFunc[V]) *BartNode[V]
- func (n *BartNode[V]) Contains(idx uint8) bool
- func (n *BartNode[V]) Delete(pfx netip.Prefix) (exists bool)
- func (n *BartNode[V]) DeleteChild(addr uint8) (exists bool)
- func (n *BartNode[V]) DeletePersist(cloneFn value.CloneFunc[V], pfx netip.Prefix) (exists bool)
- func (n *BartNode[V]) DeletePrefix(idx uint8) (exists bool)
- func (n *BartNode[V]) DirectItemsRec(parentIdx uint8, path StridePath, depth int, is4 bool) (directItems []TrieItem[V])
- func (n *BartNode[V]) DumpRec(w io.Writer, path StridePath, depth int, is4 bool)
- func (n *BartNode[V]) DumpString(octets []uint8, depth int, is4 bool) string
- func (n *BartNode[V]) EachLookupPrefix(ip netip.Addr, depth int, pfxIdx uint8, yield func(netip.Prefix, V) bool) (ok bool)
- func (n *BartNode[V]) EachSubnet(octets []byte, depth int, is4 bool, pfxIdx uint8, ...) bool
- func (n *BartNode[V]) EqualRec(o *BartNode[V]) bool
- func (n *BartNode[V]) FprintRec(w io.Writer, parent TrieItem[V], pad string) error
- func (n *BartNode[V]) Get(pfx netip.Prefix) (val V, exists bool)
- func (n *BartNode[V]) GetChild(addr uint8) (any, bool)
- func (n *BartNode[V]) GetPrefix(idx uint8) (val V, exists bool)
- func (n *BartNode[V]) Insert(pfx netip.Prefix, val V, depth int) (exists bool)
- func (n *BartNode[V]) InsertChild(addr uint8, child any) (exists bool)
- func (n *BartNode[V]) InsertPersist(cloneFn value.CloneFunc[V], pfx netip.Prefix, val V, depth int) (exists bool)
- func (n *BartNode[V]) InsertPrefix(idx uint8, val V) (exists bool)
- func (n *BartNode[V]) IsEmpty() bool
- func (n *BartNode[V]) Lookup(idx uint8) (val V, ok bool)
- func (n *BartNode[V]) LookupIdx(idx uint8) (top uint8, val V, ok bool)
- func (n *BartNode[V]) Modify(pfx netip.Prefix, cb func(val V, found bool) (_ V, del bool)) (delta int)
- func (n *BartNode[V]) MustGetChild(addr uint8) any
- func (n *BartNode[V]) MustGetPrefix(idx uint8) (val V)
- func (n *BartNode[V]) Overlaps(o *BartNode[V], depth int) bool
- func (n *BartNode[V]) OverlapsChildrenIn(o *BartNode[V]) bool
- func (n *BartNode[V]) OverlapsIdx(idx uint8) bool
- func (n *BartNode[V]) OverlapsPrefixAtDepth(pfx netip.Prefix, depth int) bool
- func (n *BartNode[V]) OverlapsRoutes(o *BartNode[V]) bool
- func (n *BartNode[V]) OverlapsSameChildren(o *BartNode[V], depth int) bool
- func (n *BartNode[V]) OverlapsTwoChildren(nChild, oChild any, depth int) bool
- func (n *BartNode[V]) PrefixCount() int
- func (n *BartNode[V]) PurgeAndCompress(stack []*BartNode[V], octets []uint8, is4 bool)
- func (n *BartNode[V]) Stats() (s StatsT)
- func (n *BartNode[V]) StatsRec() (s StatsT)
- func (n *BartNode[V]) Subnets(pfx netip.Prefix, yield func(netip.Prefix, V) bool)
- func (n *BartNode[V]) Supernets(pfx netip.Prefix, yield func(netip.Prefix, V) bool)
- func (n *BartNode[V]) UnionRec(cloneFn value.CloneFunc[V], o *BartNode[V], depth int) (duplicates int)
- func (n *BartNode[V]) UnionRecPersist(cloneFn value.CloneFunc[V], o *BartNode[V], depth int) (duplicates int)
- type FastNode
- func (n *FastNode[V]) AllChildren() iter.Seq2[uint8, any]
- func (n *FastNode[V]) AllIndices() iter.Seq2[uint8, V]
- func (n *FastNode[V]) AllRec(path StridePath, depth int, is4 bool, yield func(netip.Prefix, V) bool) bool
- func (n *FastNode[V]) AllRecSorted(path StridePath, depth int, is4 bool, yield func(netip.Prefix, V) bool) bool
- func (n *FastNode[V]) ChildCount() int
- func (n *FastNode[V]) CloneFlat(cloneFn value.CloneFunc[V]) *FastNode[V]
- func (n *FastNode[V]) CloneRec(cloneFn value.CloneFunc[V]) *FastNode[V]
- func (n *FastNode[V]) Contains(idx uint8) (ok bool)
- func (n *FastNode[V]) Delete(pfx netip.Prefix) (exists bool)
- func (n *FastNode[V]) DeleteChild(addr uint8) (exists bool)
- func (n *FastNode[V]) DeletePersist(cloneFn value.CloneFunc[V], pfx netip.Prefix) (exists bool)
- func (n *FastNode[V]) DeletePrefix(idx uint8) (exists bool)
- func (n *FastNode[V]) DirectItemsRec(parentIdx uint8, path StridePath, depth int, is4 bool) (directItems []TrieItem[V])
- func (n *FastNode[V]) DumpRec(w io.Writer, path StridePath, depth int, is4 bool)
- func (n *FastNode[V]) DumpString(octets []uint8, depth int, is4 bool) string
- func (n *FastNode[V]) EachLookupPrefix(ip netip.Addr, depth int, pfxIdx uint8, yield func(netip.Prefix, V) bool) (ok bool)
- func (n *FastNode[V]) EachSubnet(octets []byte, depth int, is4 bool, pfxIdx uint8, ...) bool
- func (n *FastNode[V]) EqualRec(o *FastNode[V]) bool
- func (n *FastNode[V]) FprintRec(w io.Writer, parent TrieItem[V], pad string) error
- func (n *FastNode[V]) Get(pfx netip.Prefix) (val V, exists bool)
- func (n *FastNode[V]) GetChild(addr uint8) (any, bool)
- func (n *FastNode[V]) GetPrefix(idx uint8) (val V, exists bool)
- func (n *FastNode[V]) Insert(pfx netip.Prefix, val V, depth int) (exists bool)
- func (n *FastNode[V]) InsertChild(addr uint8, child any) (exists bool)
- func (n *FastNode[V]) InsertPersist(cloneFn value.CloneFunc[V], pfx netip.Prefix, val V, depth int) (exists bool)
- func (n *FastNode[V]) InsertPrefix(idx uint8, val V) (exists bool)
- func (n *FastNode[V]) IsEmpty() bool
- func (n *FastNode[V]) Lookup(idx uint8) (val V, ok bool)
- func (n *FastNode[V]) LookupIdx(idx uint8) (top uint8, val V, ok bool)
- func (n *FastNode[V]) Modify(pfx netip.Prefix, cb func(val V, found bool) (_ V, del bool)) (delta int)
- func (n *FastNode[V]) MustGetChild(addr uint8) any
- func (n *FastNode[V]) MustGetPrefix(idx uint8) V
- func (n *FastNode[V]) Overlaps(o *FastNode[V], depth int) bool
- func (n *FastNode[V]) OverlapsChildrenIn(o *FastNode[V]) bool
- func (n *FastNode[V]) OverlapsIdx(idx uint8) bool
- func (n *FastNode[V]) OverlapsPrefixAtDepth(pfx netip.Prefix, depth int) bool
- func (n *FastNode[V]) OverlapsRoutes(o *FastNode[V]) bool
- func (n *FastNode[V]) OverlapsSameChildren(o *FastNode[V], depth int) bool
- func (n *FastNode[V]) OverlapsTwoChildren(nChild, oChild any, depth int) bool
- func (n *FastNode[V]) PrefixCount() int
- func (n *FastNode[V]) PurgeAndCompress(stack []*FastNode[V], octets []uint8, is4 bool)
- func (n *FastNode[V]) Stats() (s StatsT)
- func (n *FastNode[V]) StatsRec() (s StatsT)
- func (n *FastNode[V]) Subnets(pfx netip.Prefix, yield func(netip.Prefix, V) bool)
- func (n *FastNode[V]) Supernets(pfx netip.Prefix, yield func(netip.Prefix, V) bool)
- func (n *FastNode[V]) UnionRec(cloneFn value.CloneFunc[V], o *FastNode[V], depth int) (duplicates int)
- func (n *FastNode[V]) UnionRecPersist(cloneFn value.CloneFunc[V], o *FastNode[V], depth int) (duplicates int)
- type FringeNode
- type LeafNode
- type LiteNode
- func (n *LiteNode[V]) AllChildren() iter.Seq2[uint8, any]
- func (n *LiteNode[V]) AllIndices() iter.Seq2[uint8, V]
- func (n *LiteNode[V]) AllRec(path StridePath, depth int, is4 bool, yield func(netip.Prefix, V) bool) bool
- func (n *LiteNode[V]) AllRecSorted(path StridePath, depth int, is4 bool, yield func(netip.Prefix, V) bool) bool
- func (n *LiteNode[V]) ChildCount() int
- func (n *LiteNode[V]) CloneFlat(_ value.CloneFunc[V]) *LiteNode[V]
- func (n *LiteNode[V]) CloneRec(_ value.CloneFunc[V]) *LiteNode[V]
- func (n *LiteNode[V]) Contains(idx uint8) bool
- func (n *LiteNode[V]) Delete(pfx netip.Prefix) (exists bool)
- func (n *LiteNode[V]) DeleteChild(addr uint8) (exists bool)
- func (n *LiteNode[V]) DeletePersist(cloneFn value.CloneFunc[V], pfx netip.Prefix) (exists bool)
- func (n *LiteNode[V]) DeletePrefix(idx uint8) (exists bool)
- func (n *LiteNode[V]) DirectItemsRec(parentIdx uint8, path StridePath, depth int, is4 bool) (directItems []TrieItem[V])
- func (n *LiteNode[V]) DumpRec(w io.Writer, path StridePath, depth int, is4 bool)
- func (n *LiteNode[V]) DumpString(octets []uint8, depth int, is4 bool) string
- func (n *LiteNode[V]) EachLookupPrefix(ip netip.Addr, depth int, pfxIdx uint8, yield func(netip.Prefix, V) bool) (ok bool)
- func (n *LiteNode[V]) EachSubnet(octets []byte, depth int, is4 bool, pfxIdx uint8, ...) bool
- func (n *LiteNode[V]) EqualRec(o *LiteNode[V]) bool
- func (n *LiteNode[V]) FprintRec(w io.Writer, parent TrieItem[V], pad string) error
- func (n *LiteNode[V]) Get(pfx netip.Prefix) (val V, exists bool)
- func (n *LiteNode[V]) GetChild(addr uint8) (any, bool)
- func (n *LiteNode[V]) GetPrefix(idx uint8) (_ V, exists bool)
- func (n *LiteNode[V]) Insert(pfx netip.Prefix, val V, depth int) (exists bool)
- func (n *LiteNode[V]) InsertChild(addr uint8, child any) (exists bool)
- func (n *LiteNode[V]) InsertPersist(cloneFn value.CloneFunc[V], pfx netip.Prefix, val V, depth int) (exists bool)
- func (n *LiteNode[V]) InsertPrefix(idx uint8, _ V) (exists bool)
- func (n *LiteNode[V]) IsEmpty() bool
- func (n *LiteNode[V]) Lookup(idx uint8) (_ V, ok bool)
- func (n *LiteNode[V]) LookupIdx(idx uint8) (top uint8, _ V, ok bool)
- func (n *LiteNode[V]) Modify(pfx netip.Prefix, cb func(val V, found bool) (_ V, del bool)) (delta int)
- func (n *LiteNode[V]) MustGetChild(addr uint8) any
- func (n *LiteNode[V]) MustGetPrefix(idx uint8) (_ V)
- func (n *LiteNode[V]) Overlaps(o *LiteNode[V], depth int) bool
- func (n *LiteNode[V]) OverlapsChildrenIn(o *LiteNode[V]) bool
- func (n *LiteNode[V]) OverlapsIdx(idx uint8) bool
- func (n *LiteNode[V]) OverlapsPrefixAtDepth(pfx netip.Prefix, depth int) bool
- func (n *LiteNode[V]) OverlapsRoutes(o *LiteNode[V]) bool
- func (n *LiteNode[V]) OverlapsSameChildren(o *LiteNode[V], depth int) bool
- func (n *LiteNode[V]) OverlapsTwoChildren(nChild, oChild any, depth int) bool
- func (n *LiteNode[V]) PrefixCount() int
- func (n *LiteNode[V]) PurgeAndCompress(stack []*LiteNode[V], octets []uint8, is4 bool)
- func (n *LiteNode[V]) Stats() (s StatsT)
- func (n *LiteNode[V]) StatsRec() (s StatsT)
- func (n *LiteNode[V]) Subnets(pfx netip.Prefix, yield func(netip.Prefix, V) bool)
- func (n *LiteNode[V]) Supernets(pfx netip.Prefix, yield func(netip.Prefix, V) bool)
- func (n *LiteNode[V]) UnionRec(cloneFn value.CloneFunc[V], o *LiteNode[V], depth int) (duplicates int)
- func (n *LiteNode[V]) UnionRecPersist(cloneFn value.CloneFunc[V], o *LiteNode[V], depth int) (duplicates int)
- type StatsT
- type StridePath
- type TrieItem
Constants ¶
const DepthMask = MaxTreeDepth - 1
DepthMask is used for bounds check elimination (BCE) when accessing depth-indexed arrays.
const MaxItems = 256
MaxItems defines the maximum number of prefixes or children that can be stored in a single node. This corresponds to 256 possible values for an 8-bit stride.
const MaxTreeDepth = 16
MaxTreeDepth represents the maximum depth of the trie structure. For IPv6 addresses, this allows up to 16 bytes of depth.
Variables ¶
This section is empty.
Functions ¶
func CidrForFringe ¶
CidrForFringe reconstructs a CIDR prefix for a fringe node from the traversal path. Since fringe nodes don't store their prefix explicitly, it's derived entirely from the node's position in the trie.
Parameters:
- octets: The path of octets leading to the fringe
- depth: Current depth in the trie
- is4: True for IPv4 processing, false for IPv6
- lastOctet: The final octet where the fringe is located
Returns the reconstructed netip.Prefix for the fringe.
func CidrFromPath ¶
CidrFromPath reconstructs a CIDR prefix from a stride path, depth, and index. The prefix is determined by the node's position in the trie and the base index from the ART algorithm's complete binary tree representation.
Parameters:
- path: The stride path through the trie
- depth: Current depth in the trie
- is4: True for IPv4 processing, false for IPv6
- idx: The base index from the prefix table
Returns the reconstructed netip.Prefix.
func CmpIndexRank ¶
cmpIndexRank, sort indexes in prefix sort order.
func CmpPrefix ¶
CmpPrefix, helper function, compare func for prefix sort, all cidrs are already normalized
func IsFringe ¶
IsFringe determines whether a prefix qualifies as a "fringe node" - that is, a special kind of path-compressed leaf inserted at the final possible trie level (depth == lastOctet).
Both "leaves" and "fringes" are path-compressed terminal entries; the distinction lies in their position within the trie:
A leaf is inserted at any intermediate level if no further stride boundary matches (depth < lastOctet).
A fringe is inserted at the last possible stride level (depth == lastOctet) before a prefix would otherwise land as a direct prefix (depth == lastOctet+1).
Special property:
- A fringe acts as a default route for all downstream bit patterns extending beyond its prefix.
Examples:
e.g. prefix is addr/8, or addr/16, or ... addr/128 depth < lastOctet : a leaf, path-compressed depth == lastOctet : a fringe, path-compressed depth == lastOctet+1: a prefix with octet/pfx == 0/0 => idx == 1, a strides default route
Logic:
- A prefix qualifies as a fringe if: depth == lastOctet && lastBits == 0 (i.e., aligned on stride boundary, /8, /16, ... /128 bits)
func LastOctetPlusOneAndLastBits ¶
LastOctetPlusOneAndLastBits returns the count of full 8‑bit strides (bits/8) and the leftover bits in the final stride (bits%8) for pfx.
lastOctetPlusOne is the count of full 8‑bit strides (bits/8). lastBits is the remaining bit count in the final stride (bits%8),
ATTENTION: Split the IP prefixes at 8bit borders, count from 0.
/7, /15, /23, /31, ..., /127 BitPos: [0-7],[8-15],[16-23],[24-31],[32] BitPos: [0-7],[8-15],[16-23],[24-31],[32-39],[40-47],[48-55],[56-63],...,[120-127],[128] 0.0.0.0/0 => lastOctetPlusOne: 0, lastBits: 0 (default route) 0.0.0.0/7 => lastOctetPlusOne: 0, lastBits: 7 0.0.0.0/8 => lastOctetPlusOne: 1, lastBits: 0 (possible fringe) 10.0.0.0/8 => lastOctetPlusOne: 1, lastBits: 0 (possible fringe) 10.0.0.0/22 => lastOctetPlusOne: 2, lastBits: 6 10.0.0.0/29 => lastOctetPlusOne: 3, lastBits: 5 10.0.0.0/32 => lastOctetPlusOne: 4, lastBits: 0 (possible fringe) ::/0 => lastOctetPlusOne: 0, lastBits: 0 (default route) ::1/128 => lastOctetPlusOne: 16, lastBits: 0 (possible fringe) 2001:db8::/42 => lastOctetPlusOne: 5, lastBits: 2 2001:db8::/56 => lastOctetPlusOne: 7, lastBits: 0 (possible fringe) /32 and /128 prefixes are special, they never form a new node, At the end of the trie (IPv4: depth 4, IPv6: depth 16) they are always inserted as a path‑compressed fringe.
We are not splitting at /8, /16, ..., because this would mean that the first node would have 512 prefixes, 9 bits from [0-8]. All remaining nodes would then only have 8 bits from [9-16], [17-24], [25..32], ... but the algorithm would then require a variable length bitset.
If you can commit to a fixed size of [4]uint64, then the algorithm is much faster due to modern CPUs.
Perhaps a future Go version that supports SIMD instructions for the [4]uint64 vectors will make the algorithm even faster on suitable hardware.
Types ¶
type BartNode ¶
BartNode is a trie level node in the multibit routing table.
Each BartNode contains two conceptually different arrays:
- Prefixes stores routing entries (prefix -> value), laid out as a complete binary tree using the baseIndex() function from the ART algorithm.
- Children: holding subtries or path-compressed leaves/fringes with a branching factor of 256 (8 bits per stride).
- Children holds subnodes for the 256 possible next-hop paths at this trie level (8-bit stride).
Entries in Children may be:
- *BartNode[V] -> internal child node for further traversal
- *LeafNode[V] -> path-comp. node (depth < maxDepth - 1)
- *FringeNode[V] -> path-comp. node (depth == maxDepth - 1, stride-aligned: /8, /16, ... /128)
Note: Both *LeafNode and *FringeNode entries are only created by path compression. Prefixes that match exactly at the maximum trie depth (depth == maxDepth) are never stored as Children, but always directly in the prefixes array at that level.
Unlike the original ART, this implementation uses popcount-compressed sparse arrays instead of fixed-size arrays. Array slots are not pre-allocated; insertion and lookup rely on fast bitset operations and precomputed rank indexes.
func (*BartNode[V]) AllChildren ¶
AllChildren returns an iterator over all child nodes. Each iteration yields the child's address (uint8) and the child node (any).
func (*BartNode[V]) AllIndices ¶
AllIndices returns an iterator over all prefix entries. Each iteration yields the prefix index (uint8) and its associated value (V).
func (*BartNode[V]) AllRec ¶
func (n *BartNode[V]) AllRec(path StridePath, depth int, is4 bool, yield func(netip.Prefix, V) bool) bool
AllRec recursively traverses the trie starting at the current node, applying the provided yield function to every stored prefix and value.
For each route entry (prefix and value), yield is invoked. If yield returns false, the traversal stops immediately, and false is propagated upwards, enabling early termination.
The function handles all prefix entries in the current node, as well as any children - including sub-nodes, leaf nodes with full prefixes, and fringe nodes representing path-compressed prefixes. IP prefix reconstruction is performed on-the-fly from the current path and depth.
The traversal order is not defined. This implementation favors simplicity and runtime efficiency over consistency of iteration sequence.
func (*BartNode[V]) AllRecSorted ¶
func (n *BartNode[V]) AllRecSorted(path StridePath, depth int, is4 bool, yield func(netip.Prefix, V) bool) bool
AllRecSorted recursively traverses the trie in prefix-sorted order and applies the given yield function to each stored prefix and value.
Unlike AllRec, this implementation ensures that route entries are visited in canonical prefix sort order. To achieve this, both the prefixes and children of the current node are gathered, sorted, and then interleaved during traversal based on logical octet positioning.
The function first sorts relevant entries by their prefix index and address value, using a comparison function that ranks prefixes according to their mask length and position. Then it walks the trie, always yielding child entries that fall before the current prefix, followed by the prefix itself. Remaining children are processed once all prefixes have been visited.
Prefixes are reconstructed on-the-fly from the traversal path, and iteration includes all child types: inner nodes (recursive descent), leaf nodes, and fringe (compressed) prefixes.
The order is stable and predictable, making the function suitable for use cases like table exports, comparisons or serialization.
Parameters:
- path: the current traversal path through the trie
- depth: current depth in the trie (0-based)
- is4: true for IPv4 processing, false for IPv6
- yield: callback function invoked for each prefix/value pair
Returns false if yield function requests early termination.
func (*BartNode[V]) ChildCount ¶
ChildCount returns the number of slots used in this node.
func (*BartNode[V]) CloneFlat ¶
CloneFlat returns a shallow copy of the current node, optionally performing deep copies of values.
If cloneFn is nil, the stored values in prefixes are copied directly without modification. Otherwise, cloneFn is applied to each stored value for deep cloning. Child nodes are cloned shallowly: LeafNode and FringeNode children are cloned via their clone methods, but child nodes of type *BartNode[V] (subnodes) are assigned as-is without recursive cloning. This method does not recursively clone descendants beyond the immediate children.
Note: The returned node is a new instance with copied slices but only shallow copies of nested nodes, except for LeafNode and FringeNode children which are cloned according to cloneFn.
func (*BartNode[V]) CloneRec ¶
CloneRec performs a recursive deep copy of the node and all its descendants.
If cloneFn is nil, the stored values are copied directly without modification. Otherwise cloneFn is applied to each stored value for deep cloning.
This method first creates a shallow clone of the current node using CloneFlat, applying cloneFn to values as described there. Then it recursively clones all child nodes of type *BartNode[V], performing a full deep clone down the subtree.
Child nodes of type *LeafNode[V] and *FringeNode[V] are already cloned by CloneFlat.
Returns a new instance of BartNode[V] which is a complete deep clone of the receiver node with all descendants.
func (*BartNode[V]) Contains ¶
Contains returns true if an index (idx) has any matching longest-prefix in the current node’s prefix table.
This function performs a presence check without retrieving the associated value. It is faster than a full lookup, as it only tests for intersection with the backtracking bitset for the given index.
The prefix table is structured as a complete binary tree (CBT), and LPM testing is done via a bitset operation that maps the traversal path from the given index toward its possible ancestors.
func (*BartNode[V]) Delete ¶
Delete deletes the prefix and returns true if the prefix existed, or false otherwise. The prefix must be in canonical form.
func (*BartNode[V]) DeleteChild ¶
DeleteChild removes the child node at the specified address. This operation is idempotent - removing a non-existent child is safe.
func (*BartNode[V]) DeletePersist ¶
DeletePersist is similar to delete but does not mutate the original trie. Assumes the caller has pre-cloned the root (COW). It clones the internal nodes along the descent path before mutating them.
func (*BartNode[V]) DeletePrefix ¶
DeletePrefix removes the prefix at the specified index. Returns true if the prefix existed, otherwise false.
func (*BartNode[V]) DirectItemsRec ¶
func (n *BartNode[V]) DirectItemsRec(parentIdx uint8, path StridePath, depth int, is4 bool) (directItems []TrieItem[V])
DirectItemsRec, returns the direct covered items by parent. It's a complex recursive function, you have to know the data structure by heart to understand this function!
func (*BartNode[V]) DumpRec ¶
DumpRec recursively descends the trie rooted at n and writes a human-readable representation of each visited node to w.
It returns immediately if n is nil or empty. For each visited internal node it calls dump to write the node's representation, then iterates its child addresses and recurses into children that implement nodeDumper[V] (internal subnodes). The path slice and depth together represent the byte-wise path from the root to the current node; depth is incremented for each recursion. The is4 flag controls IPv4/IPv6 formatting used by dump.
func (*BartNode[V]) DumpString ¶
DumpString traverses the trie to the node at the specified depth along the given octet path and returns its string representation via Dump.
If the path is invalid or encounters an unexpected node type during traversal, it returns an error message string instead.
Parameters:
- octets: The path of octets to follow from the root
- depth: Target depth to reach before dumping (0-based byte index)
- is4: True for IPv4 formatting, false for IPv6
Returns a formatted string representation of the target node or an error message.
func (*BartNode[V]) EachLookupPrefix ¶
func (n *BartNode[V]) EachLookupPrefix(ip netip.Addr, depth int, pfxIdx uint8, yield func(netip.Prefix, V) bool) (ok bool)
EachLookupPrefix performs a hierarchical lookup of all matching prefixes in the current node’s 8-bit stride-based prefix table.
The function walks up the trie-internal complete binary tree (CBT), testing each possible prefix length mask (in decreasing order of specificity), and invokes the yield function for every matching entry.
The given idx refers to the position for this stride's prefix and is used to derive a backtracking path through the CBT by repeatedly halving the index. At each step, if a prefix exists in the table, its corresponding CIDR is reconstructed and yielded. If yield returns false, traversal stops early.
This function is intended for internal use during supernet traversal and does not descend the trie further.
func (*BartNode[V]) EachSubnet ¶
func (n *BartNode[V]) EachSubnet(octets []byte, depth int, is4 bool, pfxIdx uint8, yield func(netip.Prefix, V) bool) bool
EachSubnet yields all prefix entries and child nodes covered by a given parent prefix, sorted in natural CIDR order, within the current node.
The function iterates through all prefixes and children from the node’s stride tables. Only entries that fall within the address range defined by the parent prefix index (pfxIdx) are included. Matching entries are buffered, sorted, and passed through to the yield function.
Child entries (nodes, leaves, fringes) that fall under the covered address range are processed recursively via AllRecSorted to ensure sorted traversal.
This function is intended for internal use by Subnets(), and it assumes the current node is positioned at the point in the trie corresponding to the parent prefix.
func (*BartNode[V]) EqualRec ¶
EqualRec performs recursive structural equality comparison between two nodes. Compares prefix and child bitsets, then recursively compares all stored values and child nodes. Returns true if the nodes and their entire subtrees are structurally and semantically identical, false otherwise.
The comparison handles different node types (internal nodes, leafNodes, fringeNodes) and uses the equal function for value comparisons to support custom equality logic.
func (*BartNode[V]) FprintRec ¶
FprintRec recursively prints a hierarchical CIDR tree representation starting from this node to the provided writer. The output shows the routing table structure in human-readable format for debugging and analysis.
func (*BartNode[V]) Get ¶
Get retrieves the value associated with the given network prefix. Returns the stored value and true if the prefix exists in this node, zero value and false if the prefix is not found.
Parameters:
- pfx: The network prefix to look up (must be in canonical form)
Returns:
- val: The value associated with the prefix (zero value if not found)
- exists: True if the prefix was found, false otherwise
func (*BartNode[V]) GetChild ¶
GetChild retrieves the child node at the specified address. Returns the child and true if found, or nil and false if not present.
func (*BartNode[V]) GetPrefix ¶
GetPrefix retrieves the value associated with the prefix at the given index. Returns the value and true if found, or zero value and false if not present.
func (*BartNode[V]) Insert ¶
Insert inserts a network prefix and its associated value into the trie starting at the specified byte depth.
The function traverses the prefix address from the given depth and inserts the value either directly into the node's prefix table or as a compressed leaf or fringe node. If a conflicting leaf or fringe exists, it creates a new intermediate node to accommodate both entries.
Parameters:
- pfx: The network prefix to insert (must be in canonical form)
- val: The value to associate with the prefix
- depth: The current depth in the trie (0-based byte index)
Returns true if a prefix already existed and was updated, false for new insertions.
func (*BartNode[V]) InsertChild ¶
InsertChild adds a child node at the specified address (0-255). The child can be a *BartNode[V], *LeafNode[V], or *FringeNode[V]. Returns true if a child already existed at that address.
func (*BartNode[V]) InsertPersist ¶
func (n *BartNode[V]) InsertPersist(cloneFn value.CloneFunc[V], pfx netip.Prefix, val V, depth int) (exists bool)
InsertPersist is similar to insert but the receiver isn't modified. Assumes the caller has pre-cloned the root (COW). It clones the internal nodes along the descent path before mutating them.
func (*BartNode[V]) InsertPrefix ¶
InsertPrefix adds or updates a routing entry at the specified index with the given value. It returns true if a prefix already existed at that index (indicating an update), false if this is a new insertion.
func (*BartNode[V]) IsEmpty ¶
IsEmpty returns true if the node contains no routing entries (prefixes) and no child nodes. Empty nodes are candidates for compression or removal during trie optimization.
func (*BartNode[V]) LookupIdx ¶
LookupIdx performs a longest-prefix match (LPM) lookup for the given index (idx) within the 8-bit stride-based prefix table at this trie depth.
The function returns the matched base index, associated value, and true if a matching prefix exists at this level; otherwise, ok is false.
Internally, the prefix table is organized as a complete binary tree (CBT) indexed via the baseIndex function. Unlike the original ART algorithm, this implementation does not use an allotment-based approach. Instead, it performs CBT backtracking using a bitset-based operation with a precomputed backtracking pattern specific to idx.
func (*BartNode[V]) Modify ¶
func (n *BartNode[V]) Modify(pfx netip.Prefix, cb func(val V, found bool) (_ V, del bool)) (delta int)
Modify performs an in-place modification of a prefix using the provided callback function. The callback receives the current value (if found) and existence flag, and returns a new value and deletion flag.
modify returns the size delta (-1, 0, +1). This method handles path traversal, node creation for new paths, and automatic purge/compress operations after deletions.
Parameters:
- pfx: The network prefix to modify (must be in canonical form)
- cb: Callback function that receives (currentValue, exists) and returns (newValue, deleteFlag)
Returns:
- delta: Size change (-1 for delete, 0 for update/noop, +1 for insert)
func (*BartNode[V]) MustGetChild ¶
MustGetChild retrieves the child at the specified address, panicking if not found. This method should only be used when the caller is certain the child exists.
func (*BartNode[V]) MustGetPrefix ¶
MustGetPrefix retrieves the value at the specified index, panicking if not found. This method should only be used when the caller is certain the index exists.
func (*BartNode[V]) Overlaps ¶
Overlaps recursively compares two trie nodes and returns true if any of their prefixes or descendants overlap.
The implementation checks for: 1. Direct overlapping prefixes on this node level 2. Prefixes in one node overlapping with children in the other 3. Matching child addresses in both nodes, which are recursively compared
All 12 possible type combinations for child entries (node, leaf, fringe) are supported.
The function is optimized for early exit on first match and uses heuristics to choose between set-based and loop-based matching for performance.
func (*BartNode[V]) OverlapsChildrenIn ¶
OverlapsChildrenIn checks whether the prefixes in node n overlap with any children (by address range) in node o.
Uses bitset intersection or manual iteration heuristically, depending on prefix and child count.
Bitset-based matching uses precomputed coverage tables to avoid per-address looping. This is critical for high fan-out nodes.
func (*BartNode[V]) OverlapsIdx ¶
OverlapsIdx returns true if the given prefix index overlaps with any entry in this node.
The overlap detection considers three categories:
- Whether any stored prefix in this node covers the requested prefix (LPM test)
- Whether the requested prefix covers any stored route in the node
- Whether the requested prefix overlaps with any fringe or child entry
Internally, it leverages precomputed bitsets from the allotment model, using fast bitwise set intersections instead of explicit range comparisons. This enables high-performance overlap checks on a single stride level without descending further into the trie.
func (*BartNode[V]) OverlapsPrefixAtDepth ¶
OverlapsPrefixAtDepth returns true if any route in the subtree rooted at this node overlaps with the given pfx, starting the comparison at the specified depth.
This function supports structural overlap detection even in compressed or sparse paths within the trie, including fringe and leaf nodes. Matching is directional: it returns true if a route fully covers pfx, or if pfx covers an existing route.
At each step, it checks for visible prefixes and children that may intersect the target prefix via stride-based longest-prefix test. The walk terminates early as soon as a structural overlap is found.
This function underlies the top-level OverlapsPrefix behavior and handles details of trie traversal across varying prefix lengths and compression levels.
func (*BartNode[V]) OverlapsRoutes ¶
OverlapsRoutes compares the prefix sets of two nodes (n and o).
It first checks for direct bitset intersection (identical indices), then walks both prefix sets using lpmTest to detect if any of the n-prefixes is contained in o, or vice versa.
func (*BartNode[V]) OverlapsSameChildren ¶
OverlapsSameChildren compares all matching child addresses (octets) between node n and node o recursively.
For each shared address, the corresponding child nodes (of any type) are compared using BartNodeOverlapsTwoChildren, which handles all node/leaf/fringe combinations.
func (*BartNode[V]) OverlapsTwoChildren ¶
OverlapsTwoChildren handles all 3x3 combinations of node kinds (node, leaf, fringe).
3x3 possible different combinations for n and o node, node --> overlaps rec descent node, leaf --> overlapsPrefixAtDepth node, fringe --> true leaf, node --> overlapsPrefixAtDepth leaf, leaf --> netip.Prefix.Overlaps leaf, fringe --> true fringe, node --> true fringe, leaf --> true fringe, fringe --> true
func (*BartNode[V]) PrefixCount ¶
PrefixCount returns the number of prefixes stored in this node.
func (*BartNode[V]) PurgeAndCompress ¶
PurgeAndCompress performs bottom-up compression of the trie.
The function unwinds the provided stack of parent nodes, checking each level for compression opportunities based on child and prefix count. It may convert:
- Nodes with a single prefix into leaf one level above.
- Nodes with a single leaf or fringe into leaf one level above.
Parameters:
- stack: Array of parent nodes to process during unwinding
- octets: The path of octets taken to reach the current position
- is4: True for IPv4 processing, false for IPv6
func (*BartNode[V]) Stats ¶
Stats returns immediate statistics for n: counts of prefixes and children, and a classification of each child into nodes, leaves, or fringes. It inspects only the direct children of n (not the whole subtree). Panics if a child has an unexpected concrete type.
func (*BartNode[V]) StatsRec ¶
StatsRec returns aggregated statistics for the subtree rooted at n.
It walks the node tree recursively and sums immediate counts (prefixes and child slots) plus the number of nodes, leaves, and fringe nodes in the subtree. If n is nil or empty, a zeroed stats is returned. The returned stats.nodes includes the current node. The function will panic if a child has an unexpected concrete type.
func (*BartNode[V]) Subnets ¶
Subnets yields all subnet prefixes covered by pfx that exist in the trie, in CIDR sort order.
It first locates the trie node corresponding to pfx, then recursively yields all prefixes and child entries contained within that subtree. The traversal uses sorted iteration to maintain canonical CIDR ordering.
The function handles various node types (internal nodes, leaves, and fringes) and uses EachSubnet and AllRecSorted for sorted traversal of covered prefixes.
Parameters:
- pfx: The parent prefix whose subnets should be yielded
- yield: Callback function invoked for each subnet prefix/value pair
The yield function receives prefix/value pairs and returns false to stop the iteration early. If pfx doesn't exist in the trie, no prefixes are yielded.
func (*BartNode[V]) Supernets ¶
Supernets yields all supernet prefixes of pfx that exist in the trie, in reverse order (most-specific first, least-specific last).
It traverses upward from the given prefix toward the root, collecting matching prefixes along the path. The traversal uses a stack to yield results in reverse order, so that more-specific supernets appear before less-specific ones.
The function handles all node types (internal nodes, leaves, and fringes) and stops early if the yield callback returns false.
Parameters:
- pfx: The prefix for which to find supernets
- yield: Callback function invoked for each supernet prefix/value pair
The yield function receives prefix/value pairs and returns false to stop the iteration early.
func (*BartNode[V]) UnionRec ¶
func (n *BartNode[V]) UnionRec(cloneFn value.CloneFunc[V], o *BartNode[V], depth int) (duplicates int)
UnionRec recursively merges another node o into the receiver node n.
All prefix and child entries from o are cloned and inserted into n. If a prefix already exists in n, its value is overwritten by the value from o, and the duplicate is counted in the return value. This count can later be used to update size-related metadata in the parent trie.
The union handles all possible combinations of child node types (node, leaf, fringe) between the two nodes. Structural conflicts are resolved by creating new intermediate *BartNode[V] objects and pushing both children further down the trie. Leaves and fringes are also recursively relocated as needed to preserve prefix semantics.
The merge operation is destructive on the receiver n, but leaves the source node o unchanged.
Returns the number of duplicate prefixes that were overwritten during merging.
type FastNode ¶
type FastNode[V any] struct { // Prefixes holding prefix -> value pointers, organized as a CBT // for fast LPM lookup within the node. Prefixes struct { bitset.BitSet256 Items [256]*V } // Children holding subtries or path-compressed leaves or fringes. Children struct { bitset.BitSet256 Items [256]*any // pointer to any, see explanation above } // PfxCount replaces expensive BitSet256.Size() calls. Automatically // maintained during InsertPrefix() and DeletePrefix() operations. PfxCount uint16 // CldCount replaces expensive BitSet.Size() calls. Automatically // maintained during InsertChild() and DeleteChild() operations. CldCount uint16 }
FastNode is a trie level node in the multibit routing table.
Each FastNode contains two sections (Prefixes and Children), each with a BitSet256 tracking occupied indices and a fixed-size Items array:
- Prefixes.BitSet256: tracks which prefix indices are occupied.
- Prefixes.Items: [256]*V storing routing entry values.
- Children.BitSet256: tracks which child indices are occupied.
- Children.Items: [256]*any holding subtries or path-compressed leaves/fringes (branching factor 256, 8 bits per stride).
- PfxCount: cached count of active prefixes (avoids BitSet.Size() calls).
- CldCount: cached count of child nodes (avoids BitSet.Size() calls).
Prefixes use a complete binary tree layout driven by the baseIndex() function from the ART algorithm for fast LPM lookup.
Entries in Children.Items (each *any containing a pointer) may be:
- **FastNode[V] -> internal child node for further traversal
- **LeafNode[V] -> path-comp. node (depth < maxDepth - 1)
- **FringeNode[V] -> path-comp. node (depth == maxDepth - 1, stride-aligned)
Note: Children.Items uses *any (pointer to any) instead of any to reduce memory by ~30%, since many slots are nil and *any takes 1 word vs 2 words for nil any.
func (*FastNode[V]) AllChildren ¶
AllChildren returns an iterator over all child nodes. Each iteration yields the child's address (uint8) and the child node (any).
func (*FastNode[V]) AllIndices ¶
AllIndices returns an iterator over all prefix entries. Each iteration yields the prefix index (uint8) and its associated value (V).
func (*FastNode[V]) AllRec ¶
func (n *FastNode[V]) AllRec(path StridePath, depth int, is4 bool, yield func(netip.Prefix, V) bool) bool
AllRec recursively traverses the trie starting at the current node, applying the provided yield function to every stored prefix and value.
For each route entry (prefix and value), yield is invoked. If yield returns false, the traversal stops immediately, and false is propagated upwards, enabling early termination.
The function handles all prefix entries in the current node, as well as any children - including sub-nodes, leaf nodes with full prefixes, and fringe nodes representing path-compressed prefixes. IP prefix reconstruction is performed on-the-fly from the current path and depth.
The traversal order is not defined. This implementation favors simplicity and runtime efficiency over consistency of iteration sequence.
func (*FastNode[V]) AllRecSorted ¶
func (n *FastNode[V]) AllRecSorted(path StridePath, depth int, is4 bool, yield func(netip.Prefix, V) bool) bool
AllRecSorted recursively traverses the trie in prefix-sorted order and applies the given yield function to each stored prefix and value.
Unlike AllRec, this implementation ensures that route entries are visited in canonical prefix sort order. To achieve this, both the prefixes and children of the current node are gathered, sorted, and then interleaved during traversal based on logical octet positioning.
The function first sorts relevant entries by their prefix index and address value, using a comparison function that ranks prefixes according to their mask length and position. Then it walks the trie, always yielding child entries that fall before the current prefix, followed by the prefix itself. Remaining children are processed once all prefixes have been visited.
Prefixes are reconstructed on-the-fly from the traversal path, and iteration includes all child types: inner nodes (recursive descent), leaf nodes, and fringe (compressed) prefixes.
The order is stable and predictable, making the function suitable for use cases like table exports, comparisons or serialization.
Parameters:
- path: the current traversal path through the trie
- depth: current depth in the trie (0-based)
- is4: true for IPv4 processing, false for IPv6
- yield: callback function invoked for each prefix/value pair
Returns false if yield function requests early termination.
func (*FastNode[V]) ChildCount ¶
ChildCount returns the number of slots used in this node.
func (*FastNode[V]) CloneFlat ¶
CloneFlat returns a shallow copy of the current FastNode[V], Its semantics are identical to [bartNode.CloneFlat] but the implementation is more complex.
func (*FastNode[V]) CloneRec ¶
CloneRec performs a recursive deep copy of the FastNode[V] and all its descendants. Its semantics are identical to [bartNode.cloneRec].
func (*FastNode[V]) Contains ¶
Contains returns true if the given index has any matching longest-prefix in the current node's prefix table.
This function performs a presence check using the ART algorithm's hierarchical prefix structure. It tests whether any ancestor prefix exists for the given index by probing the slot at idx (children inherit ancestor pointers via allot).
func (*FastNode[V]) Delete ¶
Delete deletes the prefix and returns true if the prefix existed, or false otherwise. The prefix must be in canonical form.
func (*FastNode[V]) DeleteChild ¶
DeleteChild removes the child node at the specified address. This operation is idempotent - removing a non-existent child is safe.
func (*FastNode[V]) DeletePersist ¶
DeletePersist is similar to delete but does not mutate the original trie. Assumes the caller has pre-cloned the root (COW). It clones the internal nodes along the descent path before mutating them.
func (*FastNode[V]) DeletePrefix ¶
DeletePrefix removes the route at the given index. Returns true if the prefix existed, otherwise false.
func (*FastNode[V]) DirectItemsRec ¶
func (n *FastNode[V]) DirectItemsRec(parentIdx uint8, path StridePath, depth int, is4 bool) (directItems []TrieItem[V])
DirectItemsRec, returns the direct covered items by parent. It's a complex recursive function, you have to know the data structure by heart to understand this function!
func (*FastNode[V]) DumpRec ¶
DumpRec recursively descends the trie rooted at n and writes a human-readable representation of each visited node to w.
It returns immediately if n is nil or empty. For each visited internal node it calls dump to write the node's representation, then iterates its child addresses and recurses into children that implement nodeDumper[V] (internal subnodes). The path slice and depth together represent the byte-wise path from the root to the current node; depth is incremented for each recursion. The is4 flag controls IPv4/IPv6 formatting used by dump.
func (*FastNode[V]) DumpString ¶
DumpString traverses the trie to the node at the specified depth along the given octet path and returns its string representation via Dump.
If the path is invalid or encounters an unexpected node type during traversal, it returns an error message string instead.
Parameters:
- octets: The path of octets to follow from the root
- depth: Target depth to reach before dumping (0-based byte index)
- is4: True for IPv4 formatting, false for IPv6
Returns a formatted string representation of the target node or an error message.
func (*FastNode[V]) EachLookupPrefix ¶
func (n *FastNode[V]) EachLookupPrefix(ip netip.Addr, depth int, pfxIdx uint8, yield func(netip.Prefix, V) bool) (ok bool)
EachLookupPrefix performs a hierarchical lookup of all matching prefixes in the current node’s 8-bit stride-based prefix table.
The function walks up the trie-internal complete binary tree (CBT), testing each possible prefix length mask (in decreasing order of specificity), and invokes the yield function for every matching entry.
The given idx refers to the position for this stride's prefix and is used to derive a backtracking path through the CBT by repeatedly halving the index. At each step, if a prefix exists in the table, its corresponding CIDR is reconstructed and yielded. If yield returns false, traversal stops early.
This function is intended for internal use during supernet traversal and does not descend the trie further.
func (*FastNode[V]) EachSubnet ¶
func (n *FastNode[V]) EachSubnet(octets []byte, depth int, is4 bool, pfxIdx uint8, yield func(netip.Prefix, V) bool) bool
EachSubnet yields all prefix entries and child nodes covered by a given parent prefix, sorted in natural CIDR order, within the current node.
The function iterates through all prefixes and children from the node’s stride tables. Only entries that fall within the address range defined by the parent prefix index (pfxIdx) are included. Matching entries are buffered, sorted, and passed through to the yield function.
Child entries (nodes, leaves, fringes) that fall under the covered address range are processed recursively via AllRecSorted to ensure sorted traversal.
This function is intended for internal use by Subnets(), and it assumes the current node is positioned at the point in the trie corresponding to the parent prefix.
func (*FastNode[V]) EqualRec ¶
EqualRec performs recursive structural equality comparison between two nodes. Compares prefix and child bitsets, then recursively compares all stored values and child nodes. Returns true if the nodes and their entire subtrees are structurally and semantically identical, false otherwise.
The comparison handles different node types (internal nodes, leafNodes, fringeNodes) and uses the equal function for value comparisons to support custom equality logic.
func (*FastNode[V]) FprintRec ¶
FprintRec recursively prints a hierarchical CIDR tree representation starting from this node to the provided writer. The output shows the routing table structure in human-readable format for debugging and analysis.
func (*FastNode[V]) Get ¶
Get retrieves the value associated with the given network prefix. Returns the stored value and true if the prefix exists in this node, zero value and false if the prefix is not found.
Parameters:
- pfx: The network prefix to look up (must be in canonical form)
Returns:
- val: The value associated with the prefix (zero value if not found)
- exists: True if the prefix was found, false otherwise
func (*FastNode[V]) GetChild ¶
GetChild returns the child node at the specified address and true if it exists. If no child exists at addr, returns nil and false.
func (*FastNode[V]) GetPrefix ¶
GetPrefix returns the value for the given prefix index and true if it exists. If no prefix exists at idx, returns the zero value and false.
func (*FastNode[V]) Insert ¶
Insert inserts a network prefix and its associated value into the trie starting at the specified byte depth.
The function traverses the prefix address from the given depth and inserts the value either directly into the node's prefix table or as a compressed leaf or fringe node. If a conflicting leaf or fringe exists, it creates a new intermediate node to accommodate both entries.
Parameters:
- pfx: The network prefix to insert (must be in canonical form)
- val: The value to associate with the prefix
- depth: The current depth in the trie (0-based byte index)
Returns true if a prefix already existed and was updated, false for new insertions.
func (*FastNode[V]) InsertChild ¶
InsertChild inserts a child node at the specified address. Returns true if a child already existed at addr (overwrite case), false if this is a new insertion.
func (*FastNode[V]) InsertPersist ¶
func (n *FastNode[V]) InsertPersist(cloneFn value.CloneFunc[V], pfx netip.Prefix, val V, depth int) (exists bool)
InsertPersist is similar to insert but the receiver isn't modified. Assumes the caller has pre-cloned the root (COW). It clones the internal nodes along the descent path before mutating them.
func (*FastNode[V]) InsertPrefix ¶
InsertPrefix adds or updates a routing entry at the specified index with the given value. It returns true if a prefix already existed at that index (indicating an update), false if this is a new insertion.
func (*FastNode[V]) Lookup ¶
Lookup performs a longest-prefix match (LPM) Lookup for the given index within the current node's prefix table in O(1).
The function returns the matched value and true if a matching prefix exists; otherwise, it returns the zero value and false. The Lookup uses the ART algorithm's hierarchical structure to find the most specific matching prefix.
func (*FastNode[V]) LookupIdx ¶
LookupIdx performs a longest-prefix match (LPM) lookup for the given index (idx) within the 8-bit stride-based prefix table at this trie depth.
The function returns the matched base index, associated value, and true if a matching prefix exists at this level; otherwise, ok is false.
Its semantics are identical to [node.LookupIdx].
func (*FastNode[V]) Modify ¶
func (n *FastNode[V]) Modify(pfx netip.Prefix, cb func(val V, found bool) (_ V, del bool)) (delta int)
Modify performs an in-place modification of a prefix using the provided callback function. The callback receives the current value (if found) and existence flag, and returns a new value and deletion flag.
modify returns the size delta (-1, 0, +1). This method handles path traversal, node creation for new paths, and automatic purge/compress operations after deletions.
Parameters:
- pfx: The network prefix to modify (must be in canonical form)
- cb: Callback function that receives (currentValue, exists) and returns (newValue, deleteFlag)
Returns:
- delta: Size change (-1 for delete, 0 for update/noop, +1 for insert)
func (*FastNode[V]) MustGetChild ¶
MustGetChild returns the child node at the specified address. Panics if no child exists at addr. This method should only be called when the caller has verified the child exists.
func (*FastNode[V]) MustGetPrefix ¶
MustGetPrefix returns the value for the given prefix index. Panics if no prefix exists at idx. This method should only be called when the caller has verified the prefix exists.
func (*FastNode[V]) Overlaps ¶
Overlaps recursively compares two trie nodes and returns true if any of their prefixes or descendants overlap.
The implementation checks for: 1. Direct overlapping prefixes on this node level 2. Prefixes in one node overlapping with children in the other 3. Matching child addresses in both nodes, which are recursively compared
All 12 possible type combinations for child entries (node, leaf, fringe) are supported.
The function is optimized for early exit on first match and uses heuristics to choose between set-based and loop-based matching for performance.
func (*FastNode[V]) OverlapsChildrenIn ¶
OverlapsChildrenIn checks whether the prefixes in node n overlap with any children (by address range) in node o.
Uses bitset intersection or manual iteration heuristically, depending on prefix and child count.
Bitset-based matching uses precomputed coverage tables to avoid per-address looping. This is critical for high fan-out nodes.
func (*FastNode[V]) OverlapsIdx ¶
OverlapsIdx returns true if the given prefix index overlaps with any entry in this node.
The overlap detection considers three categories:
- Whether any stored prefix in this node covers the requested prefix (LPM test)
- Whether the requested prefix covers any stored route in the node
- Whether the requested prefix overlaps with any fringe or child entry
Internally, it leverages precomputed bitsets from the allotment model, using fast bitwise set intersections instead of explicit range comparisons. This enables high-performance overlap checks on a single stride level without descending further into the trie.
func (*FastNode[V]) OverlapsPrefixAtDepth ¶
OverlapsPrefixAtDepth returns true if any route in the subtree rooted at this node overlaps with the given pfx, starting the comparison at the specified depth.
This function supports structural overlap detection even in compressed or sparse paths within the trie, including fringe and leaf nodes. Matching is directional: it returns true if a route fully covers pfx, or if pfx covers an existing route.
At each step, it checks for visible prefixes and children that may intersect the target prefix via stride-based longest-prefix test. The walk terminates early as soon as a structural overlap is found.
This function underlies the top-level OverlapsPrefix behavior and handles details of trie traversal across varying prefix lengths and compression levels.
func (*FastNode[V]) OverlapsRoutes ¶
OverlapsRoutes compares the prefix sets of two nodes (n and o).
It first checks for direct bitset intersection (identical indices), then walks both prefix sets using lpmTest to detect if any of the n-prefixes is contained in o, or vice versa.
func (*FastNode[V]) OverlapsSameChildren ¶
OverlapsSameChildren compares all matching child addresses (octets) between node n and node o recursively.
For each shared address, the corresponding child nodes (of any type) are compared using FastNodeOverlapsTwoChildren, which handles all node/leaf/fringe combinations.
func (*FastNode[V]) OverlapsTwoChildren ¶
OverlapsTwoChildren handles all 3x3 combinations of node kinds (node, leaf, fringe).
3x3 possible different combinations for n and o node, node --> overlaps rec descent node, leaf --> overlapsPrefixAtDepth node, fringe --> true leaf, node --> overlapsPrefixAtDepth leaf, leaf --> netip.Prefix.Overlaps leaf, fringe --> true fringe, node --> true fringe, leaf --> true fringe, fringe --> true
func (*FastNode[V]) PrefixCount ¶
PrefixCount returns the number of prefixes stored in this node.
func (*FastNode[V]) PurgeAndCompress ¶
PurgeAndCompress performs bottom-up compression of the trie.
The function unwinds the provided stack of parent nodes, checking each level for compression opportunities based on child and prefix count. It may convert:
- Nodes with a single prefix into leaf one level above.
- Nodes with a single leaf or fringe into leaf one level above.
Parameters:
- stack: Array of parent nodes to process during unwinding
- octets: The path of octets taken to reach the current position
- is4: True for IPv4 processing, false for IPv6
func (*FastNode[V]) Stats ¶
Stats returns immediate statistics for n: counts of prefixes and children, and a classification of each child into nodes, leaves, or fringes. It inspects only the direct children of n (not the whole subtree). Panics if a child has an unexpected concrete type.
func (*FastNode[V]) StatsRec ¶
StatsRec returns aggregated statistics for the subtree rooted at n.
It walks the node tree recursively and sums immediate counts (prefixes and child slots) plus the number of nodes, leaves, and fringe nodes in the subtree. If n is nil or empty, a zeroed stats is returned. The returned stats.nodes includes the current node. The function will panic if a child has an unexpected concrete type.
func (*FastNode[V]) Subnets ¶
Subnets yields all subnet prefixes covered by pfx that exist in the trie, in CIDR sort order.
It first locates the trie node corresponding to pfx, then recursively yields all prefixes and child entries contained within that subtree. The traversal uses sorted iteration to maintain canonical CIDR ordering.
The function handles various node types (internal nodes, leaves, and fringes) and uses EachSubnet and AllRecSorted for sorted traversal of covered prefixes.
Parameters:
- pfx: The parent prefix whose subnets should be yielded
- yield: Callback function invoked for each subnet prefix/value pair
The yield function receives prefix/value pairs and returns false to stop the iteration early. If pfx doesn't exist in the trie, no prefixes are yielded.
func (*FastNode[V]) Supernets ¶
Supernets yields all supernet prefixes of pfx that exist in the trie, in reverse order (most-specific first, least-specific last).
It traverses upward from the given prefix toward the root, collecting matching prefixes along the path. The traversal uses a stack to yield results in reverse order, so that more-specific supernets appear before less-specific ones.
The function handles all node types (internal nodes, leaves, and fringes) and stops early if the yield callback returns false.
Parameters:
- pfx: The prefix for which to find supernets
- yield: Callback function invoked for each supernet prefix/value pair
The yield function receives prefix/value pairs and returns false to stop the iteration early.
func (*FastNode[V]) UnionRec ¶
func (n *FastNode[V]) UnionRec(cloneFn value.CloneFunc[V], o *FastNode[V], depth int) (duplicates int)
UnionRec recursively merges another node o into the receiver node n.
All prefix and child entries from o are cloned and inserted into n. If a prefix already exists in n, its value is overwritten by the value from o, and the duplicate is counted in the return value. This count can later be used to update size-related metadata in the parent trie.
The union handles all possible combinations of child node types (node, leaf, fringe) between the two nodes. Structural conflicts are resolved by creating new intermediate *FastNode[V] objects and pushing both children further down the trie. Leaves and fringes are also recursively relocated as needed to preserve prefix semantics.
The merge operation is destructive on the receiver n, but leaves the source node o unchanged.
Returns the number of duplicate prefixes that were overwritten during merging.
type FringeNode ¶
type FringeNode[V any] struct { Value V }
FringeNode represents a path-compressed routing entry that stores only a value. The prefix is implicitly defined by the node's position in the trie. Fringe nodes are used for prefixes that align exactly with stride boundaries (/8, /16, /24, etc.) to save memory by not storing redundant prefix information.
func NewFringeNode ¶
func NewFringeNode[V any](val V) *FringeNode[V]
NewFringeNode creates a new fringe node with the specified value.
func (*FringeNode[V]) CloneFringe ¶
func (l *FringeNode[V]) CloneFringe(cloneFn value.CloneFunc[V]) *FringeNode[V]
cloneFringe creates and returns a copy of the fringeNode receiver. If cloneFn is nil, the value is copied directly without modification. Otherwise, cloneFn is applied to the value for deep cloning.
type LeafNode ¶
LeafNode represents a path-compressed routing entry that stores both prefix and value. Leaf nodes are used when a prefix doesn't align with trie stride boundaries and needs to be stored as a compressed path to save memory.
func NewLeafNode ¶
NewLeafNode creates a new leaf node with the specified prefix and value.
type LiteNode ¶
type LiteNode[V any] struct { Children sparse.Array256[any] Prefixes struct { // no values bitset.BitSet256 Count uint16 } }
LiteNode is a trie level node in the multibit routing table.
Each LiteNode contains two conceptually different bitset-based arrays:
- Prefixes: a BitSet256 tracking which prefix indices are occupied, with Count tracking the number of active entries.
- Children: holding subtries or path-compressed leaves/fringes with a branching factor of 256 (8 bits per stride).
Entries in Children may be:
- *LiteNode[V] -> internal child node for further traversal
- *LeafNode[V] -> path-comp. node (depth < maxDepth - 1)
- *FringeNode[V] -> path-comp. node (depth == maxDepth - 1, stride-aligned)
Note: The type parameter V is a phantom type used solely for common method generation; LiteNode stores no values.
func (*LiteNode[V]) AllChildren ¶
AllChildren returns an iterator over all child nodes. Each iteration yields the child's address (uint8) and the child node (any).
func (*LiteNode[V]) AllIndices ¶
AllIndices returns an iterator over all prefix entries. Each iteration yields the prefix index (uint8) and its associated value (V).
func (*LiteNode[V]) AllRec ¶
func (n *LiteNode[V]) AllRec(path StridePath, depth int, is4 bool, yield func(netip.Prefix, V) bool) bool
AllRec recursively traverses the trie starting at the current node, applying the provided yield function to every stored prefix and value.
For each route entry (prefix and value), yield is invoked. If yield returns false, the traversal stops immediately, and false is propagated upwards, enabling early termination.
The function handles all prefix entries in the current node, as well as any children - including sub-nodes, leaf nodes with full prefixes, and fringe nodes representing path-compressed prefixes. IP prefix reconstruction is performed on-the-fly from the current path and depth.
The traversal order is not defined. This implementation favors simplicity and runtime efficiency over consistency of iteration sequence.
func (*LiteNode[V]) AllRecSorted ¶
func (n *LiteNode[V]) AllRecSorted(path StridePath, depth int, is4 bool, yield func(netip.Prefix, V) bool) bool
AllRecSorted recursively traverses the trie in prefix-sorted order and applies the given yield function to each stored prefix and value.
Unlike AllRec, this implementation ensures that route entries are visited in canonical prefix sort order. To achieve this, both the prefixes and children of the current node are gathered, sorted, and then interleaved during traversal based on logical octet positioning.
The function first sorts relevant entries by their prefix index and address value, using a comparison function that ranks prefixes according to their mask length and position. Then it walks the trie, always yielding child entries that fall before the current prefix, followed by the prefix itself. Remaining children are processed once all prefixes have been visited.
Prefixes are reconstructed on-the-fly from the traversal path, and iteration includes all child types: inner nodes (recursive descent), leaf nodes, and fringe (compressed) prefixes.
The order is stable and predictable, making the function suitable for use cases like table exports, comparisons or serialization.
Parameters:
- path: the current traversal path through the trie
- depth: current depth in the trie (0-based)
- is4: true for IPv4 processing, false for IPv6
- yield: callback function invoked for each prefix/value pair
Returns false if yield function requests early termination.
func (*LiteNode[V]) ChildCount ¶
ChildCount returns the number of slots used in this node.
func (*LiteNode[V]) CloneFlat ¶
CloneFlat returns a shallow copy of the current node.
CloneFn is only used for interface satisfaction.
func (*LiteNode[V]) CloneRec ¶
CloneRec performs a recursive deep copy of the node and all its descendants.
cloneFn is only used for interface satisfaction.
It first creates a shallow clone of the current node using CloneFlat. Then it recursively clones all child nodes of type *LiteNode[V], performing a full deep clone down the subtree.
Child nodes of type *LeafNode and *FringeNode are already copied by CloneFlat.
Returns a new instance of LiteNode[V] which is a complete deep clone of the receiver node with all descendants.
func (*LiteNode[V]) Contains ¶
Contains returns true if an index (idx) has any matching longest-prefix in the current node’s prefix table.
This function performs a presence check.
The prefix table is structured as a complete binary tree (CBT), and LPM testing is done via a bitset operation that maps the traversal path from the given index toward its possible ancestors.
func (*LiteNode[V]) Delete ¶
Delete deletes the prefix and returns true if the prefix existed, or false otherwise. The prefix must be in canonical form.
func (*LiteNode[V]) DeleteChild ¶
DeleteChild removes the child node at the specified address. This operation is idempotent - removing a non-existent child is safe.
func (*LiteNode[V]) DeletePersist ¶
DeletePersist is similar to delete but does not mutate the original trie. Assumes the caller has pre-cloned the root (COW). It clones the internal nodes along the descent path before mutating them.
func (*LiteNode[V]) DeletePrefix ¶
DeletePrefix removes the prefix at the specified index. Returns true if the prefix existed, and false otherwise.
func (*LiteNode[V]) DirectItemsRec ¶
func (n *LiteNode[V]) DirectItemsRec(parentIdx uint8, path StridePath, depth int, is4 bool) (directItems []TrieItem[V])
DirectItemsRec, returns the direct covered items by parent. It's a complex recursive function, you have to know the data structure by heart to understand this function!
func (*LiteNode[V]) DumpRec ¶
DumpRec recursively descends the trie rooted at n and writes a human-readable representation of each visited node to w.
It returns immediately if n is nil or empty. For each visited internal node it calls dump to write the node's representation, then iterates its child addresses and recurses into children that implement nodeDumper[V] (internal subnodes). The path slice and depth together represent the byte-wise path from the root to the current node; depth is incremented for each recursion. The is4 flag controls IPv4/IPv6 formatting used by dump.
func (*LiteNode[V]) DumpString ¶
DumpString traverses the trie to the node at the specified depth along the given octet path and returns its string representation via Dump.
If the path is invalid or encounters an unexpected node type during traversal, it returns an error message string instead.
Parameters:
- octets: The path of octets to follow from the root
- depth: Target depth to reach before dumping (0-based byte index)
- is4: True for IPv4 formatting, false for IPv6
Returns a formatted string representation of the target node or an error message.
func (*LiteNode[V]) EachLookupPrefix ¶
func (n *LiteNode[V]) EachLookupPrefix(ip netip.Addr, depth int, pfxIdx uint8, yield func(netip.Prefix, V) bool) (ok bool)
EachLookupPrefix performs a hierarchical lookup of all matching prefixes in the current node’s 8-bit stride-based prefix table.
The function walks up the trie-internal complete binary tree (CBT), testing each possible prefix length mask (in decreasing order of specificity), and invokes the yield function for every matching entry.
The given idx refers to the position for this stride's prefix and is used to derive a backtracking path through the CBT by repeatedly halving the index. At each step, if a prefix exists in the table, its corresponding CIDR is reconstructed and yielded. If yield returns false, traversal stops early.
This function is intended for internal use during supernet traversal and does not descend the trie further.
func (*LiteNode[V]) EachSubnet ¶
func (n *LiteNode[V]) EachSubnet(octets []byte, depth int, is4 bool, pfxIdx uint8, yield func(netip.Prefix, V) bool) bool
EachSubnet yields all prefix entries and child nodes covered by a given parent prefix, sorted in natural CIDR order, within the current node.
The function iterates through all prefixes and children from the node’s stride tables. Only entries that fall within the address range defined by the parent prefix index (pfxIdx) are included. Matching entries are buffered, sorted, and passed through to the yield function.
Child entries (nodes, leaves, fringes) that fall under the covered address range are processed recursively via AllRecSorted to ensure sorted traversal.
This function is intended for internal use by Subnets(), and it assumes the current node is positioned at the point in the trie corresponding to the parent prefix.
func (*LiteNode[V]) EqualRec ¶
EqualRec performs recursive structural equality comparison between two nodes. Compares prefix and child bitsets, then recursively compares all stored values and child nodes. Returns true if the nodes and their entire subtrees are structurally and semantically identical, false otherwise.
The comparison handles different node types (internal nodes, leafNodes, fringeNodes) and uses the equal function for value comparisons to support custom equality logic.
func (*LiteNode[V]) FprintRec ¶
FprintRec recursively prints a hierarchical CIDR tree representation starting from this node to the provided writer. The output shows the routing table structure in human-readable format for debugging and analysis.
func (*LiteNode[V]) Get ¶
Get retrieves the value associated with the given network prefix. Returns the stored value and true if the prefix exists in this node, zero value and false if the prefix is not found.
Parameters:
- pfx: The network prefix to look up (must be in canonical form)
Returns:
- val: The value associated with the prefix (zero value if not found)
- exists: True if the prefix was found, false otherwise
func (*LiteNode[V]) GetChild ¶
GetChild retrieves the child node at the specified address. Returns the child and true if found, or nil and false if not present.
func (*LiteNode[V]) Insert ¶
Insert inserts a network prefix and its associated value into the trie starting at the specified byte depth.
The function traverses the prefix address from the given depth and inserts the value either directly into the node's prefix table or as a compressed leaf or fringe node. If a conflicting leaf or fringe exists, it creates a new intermediate node to accommodate both entries.
Parameters:
- pfx: The network prefix to insert (must be in canonical form)
- val: The value to associate with the prefix
- depth: The current depth in the trie (0-based byte index)
Returns true if a prefix already existed and was updated, false for new insertions.
func (*LiteNode[V]) InsertChild ¶
InsertChild adds a child node at the specified address (0-255). The child can be a *LiteNode[V], *LeafNode, or *FringeNode. Returns true if a child already existed at that address.
func (*LiteNode[V]) InsertPersist ¶
func (n *LiteNode[V]) InsertPersist(cloneFn value.CloneFunc[V], pfx netip.Prefix, val V, depth int) (exists bool)
InsertPersist is similar to insert but the receiver isn't modified. Assumes the caller has pre-cloned the root (COW). It clones the internal nodes along the descent path before mutating them.
func (*LiteNode[V]) InsertPrefix ¶
InsertPrefix adds a routing entry at the specified index. It returns true if a prefix already existed at that index false if this is a new insertion.
func (*LiteNode[V]) IsEmpty ¶
IsEmpty returns true if the node contains no routing entries (prefixes) and no child nodes. Empty nodes are candidates for compression or removal during trie optimization.
func (*LiteNode[V]) LookupIdx ¶
LookupIdx performs a longest-prefix match (LPM) lookup for the given index (idx) within the 8-bit stride-based prefix table at this trie depth.
The function returns the matched index and whether a matching prefix exists at this level. The value type parameter exists only to satisfy interfaces.
Internally, the prefix table is organized as a complete binary tree (CBT) indexed via the baseIndex function. Unlike the original ART algorithm, this implementation does not use an allotment-based approach. Instead, it performs CBT backtracking using a bitset-based operation with a precomputed backtracking pattern specific to idx.
func (*LiteNode[V]) Modify ¶
func (n *LiteNode[V]) Modify(pfx netip.Prefix, cb func(val V, found bool) (_ V, del bool)) (delta int)
Modify performs an in-place modification of a prefix using the provided callback function. The callback receives the current value (if found) and existence flag, and returns a new value and deletion flag.
modify returns the size delta (-1, 0, +1). This method handles path traversal, node creation for new paths, and automatic purge/compress operations after deletions.
Parameters:
- pfx: The network prefix to modify (must be in canonical form)
- cb: Callback function that receives (currentValue, exists) and returns (newValue, deleteFlag)
Returns:
- delta: Size change (-1 for delete, 0 for update/noop, +1 for insert)
func (*LiteNode[V]) MustGetChild ¶
MustGetChild retrieves the child at the specified address, panicking if not found. This method should only be used when the caller is certain the child exists.
func (*LiteNode[V]) MustGetPrefix ¶
func (*LiteNode[V]) Overlaps ¶
Overlaps recursively compares two trie nodes and returns true if any of their prefixes or descendants overlap.
The implementation checks for: 1. Direct overlapping prefixes on this node level 2. Prefixes in one node overlapping with children in the other 3. Matching child addresses in both nodes, which are recursively compared
All 12 possible type combinations for child entries (node, leaf, fringe) are supported.
The function is optimized for early exit on first match and uses heuristics to choose between set-based and loop-based matching for performance.
func (*LiteNode[V]) OverlapsChildrenIn ¶
OverlapsChildrenIn checks whether the prefixes in node n overlap with any children (by address range) in node o.
Uses bitset intersection or manual iteration heuristically, depending on prefix and child count.
Bitset-based matching uses precomputed coverage tables to avoid per-address looping. This is critical for high fan-out nodes.
func (*LiteNode[V]) OverlapsIdx ¶
OverlapsIdx returns true if the given prefix index overlaps with any entry in this node.
The overlap detection considers three categories:
- Whether any stored prefix in this node covers the requested prefix (LPM test)
- Whether the requested prefix covers any stored route in the node
- Whether the requested prefix overlaps with any fringe or child entry
Internally, it leverages precomputed bitsets from the allotment model, using fast bitwise set intersections instead of explicit range comparisons. This enables high-performance overlap checks on a single stride level without descending further into the trie.
func (*LiteNode[V]) OverlapsPrefixAtDepth ¶
OverlapsPrefixAtDepth returns true if any route in the subtree rooted at this node overlaps with the given pfx, starting the comparison at the specified depth.
This function supports structural overlap detection even in compressed or sparse paths within the trie, including fringe and leaf nodes. Matching is directional: it returns true if a route fully covers pfx, or if pfx covers an existing route.
At each step, it checks for visible prefixes and children that may intersect the target prefix via stride-based longest-prefix test. The walk terminates early as soon as a structural overlap is found.
This function underlies the top-level OverlapsPrefix behavior and handles details of trie traversal across varying prefix lengths and compression levels.
func (*LiteNode[V]) OverlapsRoutes ¶
OverlapsRoutes compares the prefix sets of two nodes (n and o).
It first checks for direct bitset intersection (identical indices), then walks both prefix sets using lpmTest to detect if any of the n-prefixes is contained in o, or vice versa.
func (*LiteNode[V]) OverlapsSameChildren ¶
OverlapsSameChildren compares all matching child addresses (octets) between node n and node o recursively.
For each shared address, the corresponding child nodes (of any type) are compared using LiteNodeOverlapsTwoChildren, which handles all node/leaf/fringe combinations.
func (*LiteNode[V]) OverlapsTwoChildren ¶
OverlapsTwoChildren handles all 3x3 combinations of node kinds (node, leaf, fringe).
3x3 possible different combinations for n and o node, node --> overlaps rec descent node, leaf --> overlapsPrefixAtDepth node, fringe --> true leaf, node --> overlapsPrefixAtDepth leaf, leaf --> netip.Prefix.Overlaps leaf, fringe --> true fringe, node --> true fringe, leaf --> true fringe, fringe --> true
func (*LiteNode[V]) PrefixCount ¶
PrefixCount returns the number of prefixes stored in this node.
func (*LiteNode[V]) PurgeAndCompress ¶
PurgeAndCompress performs bottom-up compression of the trie.
The function unwinds the provided stack of parent nodes, checking each level for compression opportunities based on child and prefix count. It may convert:
- Nodes with a single prefix into leaf one level above.
- Nodes with a single leaf or fringe into leaf one level above.
Parameters:
- stack: Array of parent nodes to process during unwinding
- octets: The path of octets taken to reach the current position
- is4: True for IPv4 processing, false for IPv6
func (*LiteNode[V]) Stats ¶
Stats returns immediate statistics for n: counts of prefixes and children, and a classification of each child into nodes, leaves, or fringes. It inspects only the direct children of n (not the whole subtree). Panics if a child has an unexpected concrete type.
func (*LiteNode[V]) StatsRec ¶
StatsRec returns aggregated statistics for the subtree rooted at n.
It walks the node tree recursively and sums immediate counts (prefixes and child slots) plus the number of nodes, leaves, and fringe nodes in the subtree. If n is nil or empty, a zeroed stats is returned. The returned stats.nodes includes the current node. The function will panic if a child has an unexpected concrete type.
func (*LiteNode[V]) Subnets ¶
Subnets yields all subnet prefixes covered by pfx that exist in the trie, in CIDR sort order.
It first locates the trie node corresponding to pfx, then recursively yields all prefixes and child entries contained within that subtree. The traversal uses sorted iteration to maintain canonical CIDR ordering.
The function handles various node types (internal nodes, leaves, and fringes) and uses EachSubnet and AllRecSorted for sorted traversal of covered prefixes.
Parameters:
- pfx: The parent prefix whose subnets should be yielded
- yield: Callback function invoked for each subnet prefix/value pair
The yield function receives prefix/value pairs and returns false to stop the iteration early. If pfx doesn't exist in the trie, no prefixes are yielded.
func (*LiteNode[V]) Supernets ¶
Supernets yields all supernet prefixes of pfx that exist in the trie, in reverse order (most-specific first, least-specific last).
It traverses upward from the given prefix toward the root, collecting matching prefixes along the path. The traversal uses a stack to yield results in reverse order, so that more-specific supernets appear before less-specific ones.
The function handles all node types (internal nodes, leaves, and fringes) and stops early if the yield callback returns false.
Parameters:
- pfx: The prefix for which to find supernets
- yield: Callback function invoked for each supernet prefix/value pair
The yield function receives prefix/value pairs and returns false to stop the iteration early.
func (*LiteNode[V]) UnionRec ¶
func (n *LiteNode[V]) UnionRec(cloneFn value.CloneFunc[V], o *LiteNode[V], depth int) (duplicates int)
UnionRec recursively merges another node o into the receiver node n.
All prefix and child entries from o are cloned and inserted into n. If a prefix already exists in n, its value is overwritten by the value from o, and the duplicate is counted in the return value. This count can later be used to update size-related metadata in the parent trie.
The union handles all possible combinations of child node types (node, leaf, fringe) between the two nodes. Structural conflicts are resolved by creating new intermediate *LiteNode[V] objects and pushing both children further down the trie. Leaves and fringes are also recursively relocated as needed to preserve prefix semantics.
The merge operation is destructive on the receiver n, but leaves the source node o unchanged.
Returns the number of duplicate prefixes that were overwritten during merging.
type StridePath ¶
type StridePath [MaxTreeDepth]uint8
StridePath represents a path through the trie, with a maximum depth of 16 octets for IPv6.
type TrieItem ¶
type TrieItem[V any] struct { // for traversing, Path/Depth/Idx is needed to get the CIDR back from the trie. Node any // BartNode, FastNode, LiteNode Is4 bool Path StridePath Depth int Idx uint8 // for printing Cidr netip.Prefix Val V }
TrieItem, a node has no path information about its predecessors, we collect this during the recursive descent.