...
1
2
3
4
5 package netipx
6
7 import (
8 "encoding/binary"
9 "math/bits"
10 "net/netip"
11 )
12
13
14
15
16
17 type uint128 struct {
18 hi uint64
19 lo uint64
20 }
21
22 func u128From16(a [16]byte) uint128 {
23 return uint128{
24 binary.BigEndian.Uint64(a[:8]),
25 binary.BigEndian.Uint64(a[8:]),
26 }
27 }
28
29 func (u uint128) IP6() netip.Addr {
30 var a [16]byte
31 binary.BigEndian.PutUint64(a[:8], u.hi)
32 binary.BigEndian.PutUint64(a[8:], u.lo)
33 return netip.AddrFrom16(a)
34 }
35
36 func (u uint128) IP4() netip.Addr {
37 var a [8]byte
38 binary.BigEndian.PutUint64(a[:], u.lo)
39 return netip.AddrFrom4([4]byte{a[4], a[5], a[6], a[7]})
40 }
41
42
43
44
45
46
47 func (u uint128) isZero() bool { return u.hi|u.lo == 0 }
48
49
50 func (u uint128) and(m uint128) uint128 {
51 return uint128{u.hi & m.hi, u.lo & m.lo}
52 }
53
54
55 func (u uint128) xor(m uint128) uint128 {
56 return uint128{u.hi ^ m.hi, u.lo ^ m.lo}
57 }
58
59
60 func (u uint128) or(m uint128) uint128 {
61 return uint128{u.hi | m.hi, u.lo | m.lo}
62 }
63
64
65 func (u uint128) not() uint128 {
66 return uint128{^u.hi, ^u.lo}
67 }
68
69
70 func (u uint128) subOne() uint128 {
71 lo, borrow := bits.Sub64(u.lo, 1, 0)
72 return uint128{u.hi - borrow, lo}
73 }
74
75
76 func (u uint128) addOne() uint128 {
77 lo, carry := bits.Add64(u.lo, 1, 0)
78 return uint128{u.hi + carry, lo}
79 }
80
81 func u64CommonPrefixLen(a, b uint64) uint8 {
82 return uint8(bits.LeadingZeros64(a ^ b))
83 }
84
85 func (u uint128) commonPrefixLen(v uint128) (n uint8) {
86 if n = u64CommonPrefixLen(u.hi, v.hi); n == 64 {
87 n += u64CommonPrefixLen(u.lo, v.lo)
88 }
89 return
90 }
91
92
93
94
95
96
97
98 func (u uint128) bitsSetFrom(bit uint8) uint128 {
99 return u.or(mask6[bit].not())
100 }
101
102
103
104 func (u uint128) bitsClearedFrom(bit uint8) uint128 {
105 return u.and(mask6[bit])
106 }
107
View as plain text