github.com/Prakhar-Agarwal-byte/moby@v0.0.0-20231027092010-a14e3e8ab87e/libnetwork/ipbits/ipbits.go (about) 1 // Package ipbits contains utilities for manipulating [netip.Addr] values as 2 // numbers or bitfields. 3 package ipbits 4 5 import ( 6 "encoding/binary" 7 "net/netip" 8 ) 9 10 // Add returns ip + (x << shift). 11 func Add(ip netip.Addr, x uint64, shift uint) netip.Addr { 12 if ip.Is4() { 13 a := ip.As4() 14 addr := binary.BigEndian.Uint32(a[:]) 15 addr += uint32(x) << shift 16 binary.BigEndian.PutUint32(a[:], addr) 17 return netip.AddrFrom4(a) 18 } else { 19 a := ip.As16() 20 addr := uint128From16(a) 21 addr = addr.add(uint128From(x).lsh(shift)) 22 addr.fill16(&a) 23 return netip.AddrFrom16(a) 24 } 25 } 26 27 // Field returns the value of the bitfield [u, v] in ip as an integer, 28 // where bit 0 is the most-significant bit of ip. 29 // 30 // The result is undefined if u > v, if v-u > 64, or if u or v is larger than 31 // ip.BitLen(). 32 func Field(ip netip.Addr, u, v uint) uint64 { 33 if ip.Is4() { 34 mask := ^uint32(0) >> u 35 a := ip.As4() 36 return uint64((binary.BigEndian.Uint32(a[:]) & mask) >> (32 - v)) 37 } else { 38 mask := uint128From(0).not().rsh(u) 39 return uint128From16(ip.As16()).and(mask).rsh(128 - v).uint64() 40 } 41 }