1234567891011121314151617181920212223242526272829303132333435363738394041 |
- // 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()
- }
- }
|