Update dependencies
This commit is contained in:
176
vendor/github.com/gaissmai/bart/stringify.go
generated
vendored
176
vendor/github.com/gaissmai/bart/stringify.go
generated
vendored
@@ -5,6 +5,7 @@ package bart
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"cmp"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/netip"
|
||||
@@ -18,7 +19,8 @@ import (
|
||||
type kid[V any] struct {
|
||||
// for traversing
|
||||
n *node[V]
|
||||
path [16]byte
|
||||
is4 bool
|
||||
path stridePath
|
||||
depth int
|
||||
idx uint
|
||||
|
||||
@@ -27,14 +29,14 @@ type kid[V any] struct {
|
||||
val V
|
||||
}
|
||||
|
||||
// MarshalText implements the encoding.TextMarshaler interface,
|
||||
// MarshalText implements the [encoding.TextMarshaler] interface,
|
||||
// just a wrapper for [Table.Fprint].
|
||||
func (t *Table[V]) MarshalText() ([]byte, error) {
|
||||
t.init()
|
||||
w := new(bytes.Buffer)
|
||||
if err := t.Fprint(w); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return w.Bytes(), nil
|
||||
}
|
||||
|
||||
@@ -42,46 +44,47 @@ func (t *Table[V]) MarshalText() ([]byte, error) {
|
||||
// as string, just a wrapper for [Table.Fprint].
|
||||
// If Fprint returns an error, String panics.
|
||||
func (t *Table[V]) String() string {
|
||||
t.init()
|
||||
w := new(strings.Builder)
|
||||
if err := t.Fprint(w); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return w.String()
|
||||
}
|
||||
|
||||
// Fprint writes a hierarchical tree diagram of the ordered CIDRs to w.
|
||||
// If w is nil, Fprint panics.
|
||||
// Fprint writes a hierarchical tree diagram of the ordered CIDRs
|
||||
// with default formatted payload V to w. If w is nil, Fprint panics.
|
||||
//
|
||||
// The order from top to bottom is in ascending order of the prefix address
|
||||
// and the subtree structure is determined by the CIDRs coverage.
|
||||
//
|
||||
// ▼
|
||||
// ├─ 10.0.0.0/8 (9.9.9.9)
|
||||
// │ ├─ 10.0.0.0/24 (8.8.8.8)
|
||||
// │ └─ 10.0.1.0/24 (10.0.0.0)
|
||||
// ├─ 127.0.0.0/8 (127.0.0.1)
|
||||
// │ └─ 127.0.0.1/32 (127.0.0.1)
|
||||
// ├─ 169.254.0.0/16 (10.0.0.0)
|
||||
// ├─ 172.16.0.0/12 (8.8.8.8)
|
||||
// └─ 192.168.0.0/16 (9.9.9.9)
|
||||
// └─ 192.168.1.0/24 (127.0.0.1)
|
||||
// ├─ 10.0.0.0/8 (V)
|
||||
// │ ├─ 10.0.0.0/24 (V)
|
||||
// │ └─ 10.0.1.0/24 (V)
|
||||
// ├─ 127.0.0.0/8 (V)
|
||||
// │ └─ 127.0.0.1/32 (V)
|
||||
// ├─ 169.254.0.0/16 (V)
|
||||
// ├─ 172.16.0.0/12 (V)
|
||||
// └─ 192.168.0.0/16 (V)
|
||||
// └─ 192.168.1.0/24 (V)
|
||||
// ▼
|
||||
// └─ ::/0 (2001:db8::1)
|
||||
// ├─ ::1/128 (::1%lo)
|
||||
// ├─ 2000::/3 (2001:db8::1)
|
||||
// │ └─ 2001:db8::/32 (2001:db8::1)
|
||||
// └─ fe80::/10 (::1%eth0)
|
||||
// └─ ::/0 (V)
|
||||
// ├─ ::1/128 (V)
|
||||
// ├─ 2000::/3 (V)
|
||||
// │ └─ 2001:db8::/32 (V)
|
||||
// └─ fe80::/10 (V)
|
||||
func (t *Table[V]) Fprint(w io.Writer) error {
|
||||
t.init()
|
||||
|
||||
// v4
|
||||
if err := t.fprint(w, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// v6
|
||||
if err := t.fprint(w, false); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -95,16 +98,30 @@ func (t *Table[V]) fprint(w io.Writer, is4 bool) error {
|
||||
if _, err := fmt.Fprint(w, "▼\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := n.fprintRec(w, 0, zeroPath, 0, is4, ""); err != nil {
|
||||
|
||||
startKid := kid[V]{
|
||||
n: nil,
|
||||
idx: 0,
|
||||
path: stridePath{},
|
||||
is4: is4,
|
||||
}
|
||||
|
||||
if err := n.fprintRec(w, startKid, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// fprintRec, the output is a hierarchical CIDR tree starting with parentIdx and byte path.
|
||||
func (n *node[V]) fprintRec(w io.Writer, parentIdx uint, path [16]byte, depth int, is4 bool, pad string) error {
|
||||
// get direct childs for this parentIdx ...
|
||||
directKids := n.getKidsRec(parentIdx, path, depth, is4)
|
||||
// fprintRec, the output is a hierarchical CIDR tree starting with this kid.
|
||||
func (n *node[V]) fprintRec(w io.Writer, parent kid[V], pad string) error {
|
||||
// recursion stop condition
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// get direct childs for this kid ...
|
||||
directKids := n.getKidsRec(parent.idx, parent.path, parent.depth, parent.is4)
|
||||
|
||||
// sort them by netip.Prefix, not by baseIndex
|
||||
slices.SortFunc(directKids, cmpKidByPrefix[V])
|
||||
@@ -129,7 +146,7 @@ func (n *node[V]) fprintRec(w io.Writer, parentIdx uint, path [16]byte, depth in
|
||||
// rec-descent with this prefix as parentIdx.
|
||||
// hierarchical nested tree view, two rec-descent functions
|
||||
// work together to spoil the reader.
|
||||
if err := kid.n.fprintRec(w, kid.idx, kid.path, kid.depth, is4, pad+spacer); err != nil {
|
||||
if err := kid.n.fprintRec(w, kid, pad+spacer); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -143,71 +160,104 @@ func (n *node[V]) fprintRec(w io.Writer, parentIdx uint, path [16]byte, depth in
|
||||
//
|
||||
// See the artlookup.pdf paper in the doc folder,
|
||||
// the baseIndex function is the key.
|
||||
func (n *node[V]) getKidsRec(parentIdx uint, path [16]byte, depth int, is4 bool) []kid[V] {
|
||||
directKids := []kid[V]{}
|
||||
func (n *node[V]) getKidsRec(parentIdx uint, path stridePath, depth int, is4 bool) []kid[V] {
|
||||
// recursion stop condition
|
||||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// make backing arrays, no heap allocs
|
||||
idxBackingArray := [maxNodePrefixes]uint{}
|
||||
for _, idx := range n.allStrideIndexes(idxBackingArray[:]) {
|
||||
var directKids []kid[V]
|
||||
|
||||
for _, idx := range n.prefixes.All() {
|
||||
// parent or self, handled alreday in an upper stack frame.
|
||||
if idx <= parentIdx {
|
||||
continue
|
||||
}
|
||||
|
||||
// check if lpmIdx for this idx' parent is equal to parentIdx
|
||||
lpmIdx, _, _ := n.lpm(idx >> 1)
|
||||
if lpmIdx == parentIdx {
|
||||
// idx is directKid
|
||||
val, _ := n.getValue(idx)
|
||||
cidr, _ := cidrFromPath(path, depth, is4, idx)
|
||||
lpmIdx, _, _ := n.lpmGet(idx >> 1)
|
||||
|
||||
directKids = append(directKids, kid[V]{n, path, depth, idx, cidr, val})
|
||||
// if idx is directKid?
|
||||
if lpmIdx == parentIdx {
|
||||
cidr := cidrFromPath(path, depth, is4, idx)
|
||||
|
||||
kid := kid[V]{
|
||||
n: n,
|
||||
is4: is4,
|
||||
path: path,
|
||||
depth: depth,
|
||||
idx: idx,
|
||||
cidr: cidr,
|
||||
val: n.prefixes.MustGet(idx),
|
||||
}
|
||||
|
||||
directKids = append(directKids, kid)
|
||||
}
|
||||
}
|
||||
|
||||
// the node may have childs, the rec-descent monster starts
|
||||
addrBackingArray := [maxNodeChildren]uint{}
|
||||
for i, addr := range n.allChildAddrs(addrBackingArray[:]) {
|
||||
octet := byte(addr)
|
||||
// the node may have childs and leaves, the rec-descent monster starts
|
||||
for i, addr := range n.children.All() {
|
||||
// do a longest-prefix-match
|
||||
lpmIdx, _, _ := n.lpm(octetToBaseIndex(octet))
|
||||
lpmIdx, _, _ := n.lpmGet(hostIndex(addr))
|
||||
if lpmIdx == parentIdx {
|
||||
c := n.children[i]
|
||||
path[depth] = octet
|
||||
switch k := n.children.Items[i].(type) {
|
||||
case *node[V]:
|
||||
path[depth] = byte(addr)
|
||||
|
||||
// traverse, rec-descent call with next child node
|
||||
directKids = append(directKids, c.getKidsRec(0, path, depth+1, is4)...)
|
||||
// traverse, rec-descent call with next child node
|
||||
directKids = append(directKids, k.getKidsRec(0, path, depth+1, is4)...)
|
||||
case *leaf[V]:
|
||||
kid := kid[V]{
|
||||
n: nil, // path compressed item, stop recursion
|
||||
is4: is4,
|
||||
cidr: k.prefix,
|
||||
val: k.value,
|
||||
}
|
||||
|
||||
directKids = append(directKids, kid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return directKids
|
||||
}
|
||||
|
||||
// cidrFromPath, get prefix back from byte path, depth, octet and pfxLen.
|
||||
func cidrFromPath(path [16]byte, depth int, is4 bool, idx uint) (netip.Prefix, error) {
|
||||
octet, pfxLen := baseIndexToPrefix(idx)
|
||||
// cmpKidByPrefix, all prefixes are already normalized (Masked).
|
||||
func cmpKidByPrefix[V any](a, b kid[V]) int {
|
||||
return cmpPrefix(a.cidr, b.cidr)
|
||||
}
|
||||
|
||||
// set (partially) masked byte in path at depth
|
||||
// cmpPrefix, compare func for prefix sort,
|
||||
// all cidrs are already normalized
|
||||
func cmpPrefix(a, b netip.Prefix) int {
|
||||
if cmp := a.Addr().Compare(b.Addr()); cmp != 0 {
|
||||
return cmp
|
||||
}
|
||||
|
||||
return cmp.Compare(a.Bits(), b.Bits())
|
||||
}
|
||||
|
||||
// cidrFromPath, get prefix back from byte path, depth, octet and pfxLen.
|
||||
func cidrFromPath(path stridePath, depth int, is4 bool, idx uint) netip.Prefix {
|
||||
octet, pfxLen := idxToPfx(idx)
|
||||
|
||||
// set masked byte in path at depth
|
||||
path[depth] = octet
|
||||
|
||||
// zero/mask the bytes after prefix bits
|
||||
clear(path[depth+1:])
|
||||
|
||||
// make ip addr from octets
|
||||
var ip netip.Addr
|
||||
if is4 {
|
||||
b4 := [4]byte{}
|
||||
copy(b4[:], path[:4])
|
||||
ip = netip.AddrFrom4(b4)
|
||||
ip = netip.AddrFrom4([4]byte(path[:4]))
|
||||
} else {
|
||||
ip = netip.AddrFrom16(path)
|
||||
}
|
||||
|
||||
// calc bits with pathLen and pfxLen
|
||||
bits := depth*strideLen + pfxLen
|
||||
bits := depth<<3 + pfxLen
|
||||
|
||||
// make a normalized prefix from ip/bits
|
||||
return ip.Prefix(bits)
|
||||
}
|
||||
|
||||
// cmpKidByPrefix, all prefixes are already normalized (Masked).
|
||||
func cmpKidByPrefix[V any](a, b kid[V]) int {
|
||||
return cmpPrefix(a.cidr, b.cidr)
|
||||
// return a normalized prefix from ip/bits
|
||||
return netip.PrefixFrom(ip, bits)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user