3c59ef247f
The netip types can be used as map keys, unlike net.IP and friends, which is a very useful property to have for this application. Signed-off-by: Cory Snider <csnider@mirantis.com>
41 lines
1.1 KiB
Go
41 lines
1.1 KiB
Go
// Package ipbits contains utilities for manipulating [netip.Addr] values as
|
|
// numbers or bitfields.
|
|
package ipbits
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"net/netip"
|
|
)
|
|
|
|
// Add returns ip + (x << shift).
|
|
func Add(ip netip.Addr, x uint64, shift uint) netip.Addr {
|
|
if ip.Is4() {
|
|
a := ip.As4()
|
|
addr := binary.BigEndian.Uint32(a[:])
|
|
addr += uint32(x) << shift
|
|
binary.BigEndian.PutUint32(a[:], addr)
|
|
return netip.AddrFrom4(a)
|
|
} else {
|
|
a := ip.As16()
|
|
addr := uint128From16(a)
|
|
addr = addr.add(uint128From(x).lsh(shift))
|
|
addr.fill16(&a)
|
|
return netip.AddrFrom16(a)
|
|
}
|
|
}
|
|
|
|
// Field returns the value of the bitfield [u, v] in ip as an integer,
|
|
// where bit 0 is the most-significant bit of ip.
|
|
//
|
|
// The result is undefined if u > v, if v-u > 64, or if u or v is larger than
|
|
// ip.BitLen().
|
|
func Field(ip netip.Addr, u, v uint) uint64 {
|
|
if ip.Is4() {
|
|
mask := ^uint32(0) >> u
|
|
a := ip.As4()
|
|
return uint64((binary.BigEndian.Uint32(a[:]) & mask) >> (32 - v))
|
|
} else {
|
|
mask := uint128From(0).not().rsh(u)
|
|
return uint128From16(ip.As16()).and(mask).rsh(128 - v).uint64()
|
|
}
|
|
}
|