github.com/cilium/cilium@v1.16.2/pkg/container/bitlpm/unsigned.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package bitlpm 5 6 import ( 7 "fmt" 8 "math/bits" 9 "unsafe" 10 ) 11 12 // Unsigned represents all types that have an underlying 13 // unsigned integer type, excluding uintptr and uint. 14 type Unsigned interface { 15 ~uint8 | ~uint16 | ~uint32 | ~uint64 16 } 17 18 // UintTrie uses all unsigned integer types 19 // except for uintptr and uint. 20 type UintTrie[K Unsigned, V any] struct { 21 trie Trie[Key[K], V] 22 keySize uint 23 } 24 25 // NewUintTrie represents a Trie with a key of any 26 // uint type. 27 func NewUintTrie[K Unsigned, T any]() *UintTrie[K, T] { 28 var k K 29 size := uint(unsafe.Sizeof(k)) 30 return &UintTrie[K, T]{ 31 trie: NewTrie[K, T](size * 8), 32 keySize: size, 33 } 34 } 35 36 func (tu *UintTrie[K, T]) getKey(k K) Key[K] { 37 switch tu.keySize { 38 case 1: 39 return unsignedKey8[K](k) 40 case 2: 41 return unsignedKey16[K](k) 42 case 4: 43 return unsignedKey32[K](k) 44 case 8: 45 return unsignedKey64[K](k) 46 } 47 panic(fmt.Sprintf("unexpected key size of %d", unsafe.Sizeof(k))) 48 } 49 50 func (ut *UintTrie[K, T]) Upsert(prefix uint, k K, value T) { 51 ut.trie.Upsert(prefix, ut.getKey(k), value) 52 } 53 54 func (ut *UintTrie[K, T]) Delete(prefix uint, k K) bool { 55 return ut.trie.Delete(prefix, ut.getKey(k)) 56 } 57 58 func (ut *UintTrie[K, T]) ExactLookup(prefix uint, k K) (T, bool) { 59 return ut.trie.ExactLookup(prefix, ut.getKey(k)) 60 } 61 62 func (ut *UintTrie[K, T]) LongestPrefixMatch(k K) (T, bool) { 63 return ut.trie.LongestPrefixMatch(ut.getKey(k)) 64 } 65 66 func (ut *UintTrie[K, T]) Ancestors(prefix uint, k K, fn func(prefix uint, key K, value T) bool) { 67 ut.trie.Ancestors(prefix, ut.getKey(k), func(prefix uint, k Key[K], v T) bool { 68 return fn(prefix, k.Value(), v) 69 }) 70 } 71 72 func (ut *UintTrie[K, T]) Descendants(prefix uint, k K, fn func(prefix uint, key K, value T) bool) { 73 ut.trie.Descendants(prefix, ut.getKey(k), func(prefix uint, k Key[K], v T) bool { 74 return fn(prefix, k.Value(), v) 75 }) 76 } 77 78 func (ut *UintTrie[K, T]) Len() uint { 79 return ut.trie.Len() 80 } 81 82 func (ut *UintTrie[K, T]) ForEach(fn func(prefix uint, key K, value T) bool) { 83 ut.trie.ForEach(func(prefix uint, k Key[K], v T) bool { 84 return fn(prefix, k.Value(), v) 85 }) 86 } 87 88 type unsignedKey8[U Unsigned] uint8 89 90 func (u unsignedKey8[U]) CommonPrefix(v U) uint { 91 return uint(bits.LeadingZeros8(uint8(U(u) ^ v))) 92 } 93 94 func (u unsignedKey8[U]) BitValueAt(i uint) uint8 { 95 if u&(1<<(7-i)) == 0 { 96 return 0 97 } 98 return 1 99 } 100 101 func (u unsignedKey8[U]) Value() U { 102 return U(u) 103 } 104 105 type unsignedKey16[U Unsigned] uint16 106 107 func (u unsignedKey16[U]) CommonPrefix(v U) uint { 108 return uint(bits.LeadingZeros16(uint16(u) ^ uint16(v))) 109 } 110 111 func (u unsignedKey16[U]) BitValueAt(i uint) uint8 { 112 if u&(1<<(15-i)) == 0 { 113 return 0 114 } 115 return 1 116 } 117 118 func (u unsignedKey16[U]) Value() U { 119 return U(u) 120 } 121 122 type unsignedKey32[U Unsigned] uint32 123 124 func (u unsignedKey32[U]) CommonPrefix(v U) uint { 125 return uint(bits.LeadingZeros32(uint32(u) ^ uint32(v))) 126 } 127 128 func (u unsignedKey32[U]) BitValueAt(i uint) uint8 { 129 if u&(1<<(31-i)) == 0 { 130 return 0 131 } 132 return 1 133 } 134 135 func (u unsignedKey32[U]) Value() U { 136 return U(u) 137 } 138 139 type unsignedKey64[U Unsigned] uint64 140 141 func (u unsignedKey64[U]) CommonPrefix(v U) uint { 142 return uint(bits.LeadingZeros64(uint64(u) ^ uint64(v))) 143 } 144 145 func (u unsignedKey64[U]) BitValueAt(i uint) uint8 { 146 if u&(1<<(63-i)) == 0 { 147 return 0 148 } 149 return 1 150 } 151 152 func (u unsignedKey64[U]) Value() U { 153 return U(u) 154 }