Documentation
¶
Overview ¶
IP addresses as generic, immutable positive integers. Use for arithmetic and bitwise operations.
IP Address Types ¶
Addr4 and Addr6 are IP address representations for IPv4 and IPv6 respectively. Family types act as factories for the Int structs Addr4 and Addr6. Use V4 or V6 to obtain a Family.
Use Family.FromBytes or FromBytes to obtain Int from byte slice. Use Parse or ParseUnknown to obtain Int from string.
Index ¶
- Constants
- func Eq(address0, address1 Address) (areEqual bool)
- func Exclusive[A Int[A]](start, excludedEnd A) (exclusiveRange iter.Seq[A])
- func FromBigInt[A Int[A]](family Family[A], i *big.Int) (address A, err error)
- func Inclusive[A Int[A]](first, last A) (inclusiveRange iter.Seq[A])
- func MaxAddress[A Int[A]](fam Family[A]) (lastInFamily A)
- func MinAddress[A Int[A]](fam Family[A]) (firstInFamily A)
- func MustParse[A Int[A]](family Family[A], candidate string) (address A)
- func Next[A Int[A]](address A) (incremented A)
- func Parse[A Int[A]](family Family[A], candidate string) (address A, err error)
- func Prev[A Int[A]](address A) (decremented A)
- func ToBigInt[A Int[A]](address A) (i *big.Int)
- type Addr4
- func (a Addr4) Add(addend Addr4) Addr4
- func (a Addr4) And(operand Addr4) Addr4
- func (a Addr4) Bytes() []byte
- func (a Addr4) Compare(other Addr4) int
- func (a Addr4) Divide(denominator Addr4) Addr4
- func (a Addr4) Family() Family[Addr4]
- func (a Addr4) Float64() float64
- func (a Addr4) LeadingZeros() int
- func (a Addr4) Mod(denominator Addr4) Addr4
- func (a Addr4) Multiply(multiplicand Addr4) Addr4
- func (a Addr4) Not() Addr4
- func (a Addr4) Or(operand Addr4) Addr4
- func (a Addr4) Shift(bits int) Addr4
- func (a Addr4) String() string
- func (a Addr4) Subtract(subtrahend Addr4) Addr4
- func (a Addr4) TrailingZeros() int
- func (a Addr4) Version() Version
- func (a Addr4) Width() int
- func (a Addr4) Xor(operand Addr4) Addr4
- type Addr6
- func (a Addr6) Add(addend Addr6) Addr6
- func (a Addr6) And(operand Addr6) Addr6
- func (a Addr6) Bytes() []byte
- func (a Addr6) Compare(other Addr6) int
- func (a Addr6) Divide(denominator Addr6) Addr6
- func (a Addr6) Family() Family[Addr6]
- func (a Addr6) Float64() float64
- func (a Addr6) LeadingZeros() int
- func (a Addr6) Mod(denominator Addr6) Addr6
- func (a Addr6) Multiply(multiplicand Addr6) Addr6
- func (a Addr6) Not() Addr6
- func (a Addr6) Or(operand Addr6) Addr6
- func (a Addr6) Shift(bits int) Addr6
- func (a Addr6) String() string
- func (a Addr6) Subtract(subtrahend Addr6) Addr6
- func (a Addr6) TrailingZeros() int
- func (a Addr6) Version() Version
- func (a Addr6) Width() int
- func (a Addr6) Xor(operand Addr6) Addr6
- type Address
- type Family
- type Int
- type Spec
- type Version
Examples ¶
Constants ¶
const ( // Number of bits in IPv4 address (32) Width4 int = 32 // Number of bits in IPv6 address (128) Width6 int = 128 )
Variables ¶
This section is empty.
Functions ¶
func Exclusive ¶
The exclusive version of Inclusive. If start and end are equal the sequence is empty.
Example ¶
package main
import (
"fmt"
"github.com/ipfreely-uk/go/ip"
)
func printOrder(order string, start, end fmt.Stringer) {
msg := fmt.Sprintf("%s: %s to %s", order, start.String(), end.String())
println(msg)
}
func main() {
v6 := ip.V6()
docs := ip.MustParse(v6, "2001:DB8::")
lowest := docs.Add(v6.FromInt(0xD))
highest := lowest.Add(v6.FromInt(5))
printOrder("Ascending", lowest, highest)
for addr := range ip.Exclusive(lowest, highest) {
println(addr.String())
}
printOrder("Descending", highest, lowest)
for addr := range ip.Exclusive(highest, lowest) {
println(addr.String())
}
}
func FromBigInt ¶
Converts big integer to Int. Returns error if value out of range for address family.
func Inclusive ¶
Address iteration for range loops. Iteration uses Next or Prev depending on relative values of first and last. The returned sequence is reusable.
Example ¶
package main
import (
"fmt"
"github.com/ipfreely-uk/go/ip"
)
func main() {
v4 := ip.V4()
lowest := v4.MustFromBytes(192, 0, 2, 0)
highest := lowest.Add(v4.FromInt(5))
printOrder("Ascending", lowest, highest)
for addr := range ip.Inclusive(lowest, highest) {
println(addr.String())
}
printOrder("Descending", highest, lowest)
for addr := range ip.Inclusive(highest, lowest) {
println(addr.String())
}
}
func printOrder(order string, start, end fmt.Stringer) {
msg := fmt.Sprintf("%s: %s to %s", order, start.String(), end.String())
println(msg)
}
func MaxAddress ¶
Maximum address for family
func MinAddress ¶
Zero address for family.
func Next ¶
func Next[A Int[A]](address A) (incremented A)
Increments argument by one with overflow
Example ¶
package main
import (
"github.com/ipfreely-uk/go/ip"
)
func main() {
v4 := ip.V4()
lowest := v4.MustFromBytes(192, 0, 2, 0)
highest := lowest.Add(v4.FromInt(10))
Ascend(lowest, highest)
}
func Ascend[A ip.Int[A]](lowest, highest A) {
current := lowest
for {
println(current.String())
if ip.Eq(current, highest) {
break
}
current = ip.Next(current)
}
}
func Prev ¶
func Prev[A Int[A]](address A) (decremented A)
Decrements argument by one with underflow
Example ¶
package main
import (
"github.com/ipfreely-uk/go/ip"
)
func main() {
v6 := ip.V6()
highest := ip.MustParse(v6, "2001:db8::fffe")
lowest := highest.Subtract(v6.FromInt(10))
Descend(highest, lowest)
}
func Descend[A ip.Int[A]](highest, lowest A) {
current := highest
for {
println(current.String())
if ip.Eq(current, lowest) {
break
}
current = ip.Prev(current)
}
}
func ToBigInt ¶
Converts any Int to big integer
Example ¶
package main
import (
"fmt"
"math/big"
"github.com/ipfreely-uk/go/ip"
"github.com/ipfreely-uk/go/txt"
)
func main() {
printNumberOfAddresses(ip.MinAddress(ip.V4()), ip.MaxAddress(ip.V4()))
printNumberOfAddresses(ip.MinAddress(ip.V6()), ip.MaxAddress(ip.V6()))
}
func printNumberOfAddresses[A ip.Int[A]](first, last A) {
diff := last.Subtract(first)
n := ip.ToBigInt(diff)
rangeSize := n.Add(n, big.NewInt(1))
fmt.Printf("%v to %v = %s addresses\n", first, last, txt.CommaDelim(rangeSize))
}
Types ¶
type Addr4 ¶
type Addr4 struct {
// contains filtered or unexported fields
}
Immutable 32bit unsigned integer IP Int representation. Use V4 to create values.
type Addr6 ¶
type Addr6 struct {
// contains filtered or unexported fields
}
Immutable 128bit unsigned integer IP Int representation. Use V6 to create values.
type Address ¶
type Address interface {
Spec
// Address as byte slice
Bytes() (slice []byte)
// Normalized string form
String() (address string)
// Equivalent to math/bits.LeadingZeros
LeadingZeros() (count int)
// Equivalent to math/bits.TrailingZeros
TrailingZeros() (count int)
// Approximation to float64
Float64() (approximation float64)
}
The parts of Int without generic typing. Addr4 and Addr6 are the only types that can conform to this interface.
Example ¶
package main
import (
"github.com/ipfreely-uk/go/ip"
)
func main() {
examples := []string{
"2001:db8::",
"192.0.2.0",
}
for _, e := range examples {
address := ip.MustParseUnknown(e)
switch a := address.(type) {
case ip.Addr4:
printNthAfter(a, 255)
case ip.Addr6:
printNthAfter(a, 0xFFFFFFFF)
}
}
}
func printNthAfter[A ip.Int[A]](address A, n uint32) {
operand := address.Family().FromInt(n)
result := address.Add(operand)
println(result.String())
}
func FromBytes ¶
Parse IP address bytes from unknown family. Slice length must be 4 (IPv4) or 16 (IPv6).
Example ¶
package main
import (
"github.com/ipfreely-uk/go/ip"
)
func main() {
address, err := ip.FromBytes(192, 0, 2, 1)
if err != nil {
println("Not address:", err.Error())
}
switch a := address.(type) {
case ip.Addr4:
println("IPv4 address:", a.String())
case ip.Addr6:
println("IPv6 address", a.String())
}
}
func MustFromBytes ¶
As FromBytes but panics on error
Example ¶
package main
import (
"net/netip"
"github.com/ipfreely-uk/go/ip"
)
func main() {
// Convert to/from netip.Addr
examples := []string{
"2001:db8::",
"192.0.2.1",
}
for _, e := range examples {
original := netip.MustParseAddr(e)
addr := fromNetip(original)
var result netip.Addr
switch a := addr.(type) {
case ip.Addr4:
result = toNetip(a)
case ip.Addr6:
result = toNetip(a)
}
println(original.String(), "->", result.String())
}
}
func toNetip(address ip.Address) netip.Addr {
i, _ := netip.AddrFromSlice(address.Bytes())
return i
}
func fromNetip(a netip.Addr) ip.Address {
return ip.MustFromBytes(a.AsSlice()...)
}
func MustParseUnknown ¶
As ParseUnknown but panics on error
func ParseUnknown ¶
Parse IP address string from unknown family
Example ¶
package main
import (
"github.com/ipfreely-uk/go/ip"
)
func main() {
examples := []string{"2001:db8::1", "192.0.2.1", "foobar"}
for _, s := range examples {
address, err := ip.ParseUnknown(s)
if err != nil {
println("Not address:", err.Error())
} else {
println("Address:", address.String())
}
}
}
type Family ¶
type Family[A Address] interface { Spec // Create address from bytes. // Returns error if slice is not [Width]/8 bytes. FromBytes(...byte) (address A, err error) // As FromBytes but panics on error MustFromBytes(...byte) (address A) // Create address from unsigned integer. // All values are valid. // For V4 operand 1 returns "0.0.0.1". // For V6 operand 1 return "::1". FromInt(i uint32) (address A) }
IP address family. Obtain via V4 or V6 functions.
func V4 ¶
IPv4 family of addresses
Example ¶
package main
import (
"github.com/ipfreely-uk/go/ip"
)
func main() {
address := ip.V4().MustFromBytes(203, 0, 113, 1)
println(address.String())
}
func V6 ¶
IPv6 family of addresses
Example ¶
package main
import (
"github.com/ipfreely-uk/go/ip"
)
func main() {
family := ip.V6()
bytes := make([]byte, family.Width()/8)
bytes[0] = 0x20
bytes[1] = 0x01
bytes[2] = 0xDB
bytes[3] = 0x80
bytes[15] = 1
address := family.MustFromBytes(bytes...)
println(address.String())
}
type Int ¶
type Int[A Address] interface { Address // IP address family - [V4] or [V6] Family() Family[A] // Addition with overflow Add(addend A) (sum A) // Subtraction with overflow Subtract(subtrahend A) (difference A) // Multiplication with overflow Multiply(factor A) (product A) // Division Divide(denominator A) (quotient A) // Modulus Mod(denominator A) (remainder A) // Bitwise NOT Not() (complement A) // Bitwise AND And(operand A) (address A) // Bitwise OR Or(operand A) (address A) // Bitwise XOR Xor(operand A) (address A) // Bit shift. Use negative int for left shift; use positive int for right shift. Shift(bits int) (address A) // Returns 1 if operand is less than this. // Returns -1 if operand is more than this. // Returns 0 if operand is equal. Compare(address A) int }
IP address as generic unsigned integer type. Addr4 and Addr6 are the only types that can conform to this interface.
Example ¶
package main
import (
"github.com/ipfreely-uk/go/ip"
)
func main() {
printN(ip.V4().MustFromBytes(192, 0, 2, 0), 3)
printN(ip.MustParse(ip.V6(), "2001:db8::"), 3)
}
func printN[A ip.Int[A]](address A, n int) {
a := address
one := a.Family().FromInt(1)
for range n {
println(a.String())
a = a.Add(one)
}
}