ip

package
v1.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 18, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

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

Examples

Constants

View Source
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 Eq

func Eq(address0, address1 Address) (areEqual bool)

Tests equality

func Exclusive

func Exclusive[A Int[A]](start, excludedEnd A) (exclusiveRange iter.Seq[A])

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

func FromBigInt[A Int[A]](family Family[A], i *big.Int) (address A, err error)

Converts big integer to Int. Returns error if value out of range for address family.

func Inclusive

func Inclusive[A Int[A]](first, last A) (inclusiveRange iter.Seq[A])

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

func MaxAddress[A Int[A]](fam Family[A]) (lastInFamily A)

Maximum address for family

func MinAddress

func MinAddress[A Int[A]](fam Family[A]) (firstInFamily A)

Zero address for family.

func MustParse

func MustParse[A Int[A]](family Family[A], candidate string) (address A)

As Parse but panics on error

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 Parse

func Parse[A Int[A]](family Family[A], candidate string) (address A, err error)

Parses address string

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

func ToBigInt[A Int[A]](address A) (i *big.Int)

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.

func (Addr4) Add

func (a Addr4) Add(addend Addr4) Addr4

See Int

func (Addr4) And

func (a Addr4) And(operand Addr4) Addr4

See Int

func (Addr4) Bytes

func (a Addr4) Bytes() []byte

Returns 4 byte slice

func (Addr4) Compare

func (a Addr4) Compare(other Addr4) int

See Int

func (Addr4) Divide

func (a Addr4) Divide(denominator Addr4) Addr4

See Int

func (Addr4) Family

func (a Addr4) Family() Family[Addr4]

Returns V4

func (Addr4) Float64

func (a Addr4) Float64() float64

See Int

func (Addr4) LeadingZeros

func (a Addr4) LeadingZeros() int

See Int

func (Addr4) Mod

func (a Addr4) Mod(denominator Addr4) Addr4

See Int

func (Addr4) Multiply

func (a Addr4) Multiply(multiplicand Addr4) Addr4

See Int

func (Addr4) Not

func (a Addr4) Not() Addr4

See Int

func (Addr4) Or

func (a Addr4) Or(operand Addr4) Addr4

See Int

func (Addr4) Shift

func (a Addr4) Shift(bits int) Addr4

See Int

func (Addr4) String

func (a Addr4) String() string

Returns compact decimal dotted quad notation

func (Addr4) Subtract

func (a Addr4) Subtract(subtrahend Addr4) Addr4

See Int

func (Addr4) TrailingZeros

func (a Addr4) TrailingZeros() int

See Int

func (Addr4) Version

func (a Addr4) Version() Version

Returns Version4

func (Addr4) Width

func (a Addr4) Width() int

Returns Width4

func (Addr4) Xor

func (a Addr4) Xor(operand Addr4) Addr4

See Int

type Addr6

type Addr6 struct {
	// contains filtered or unexported fields
}

Immutable 128bit unsigned integer IP Int representation. Use V6 to create values.

func (Addr6) Add

func (a Addr6) Add(addend Addr6) Addr6

See Int

func (Addr6) And

func (a Addr6) And(operand Addr6) Addr6

See Int

func (Addr6) Bytes

func (a Addr6) Bytes() []byte

Returns 16 byte slice

func (Addr6) Compare

func (a Addr6) Compare(other Addr6) int

See Int

func (Addr6) Divide

func (a Addr6) Divide(denominator Addr6) Addr6

See Int

func (Addr6) Family

func (a Addr6) Family() Family[Addr6]

Returns V6

func (Addr6) Float64

func (a Addr6) Float64() float64

See Int

func (Addr6) LeadingZeros

func (a Addr6) LeadingZeros() int

See Int

func (Addr6) Mod

func (a Addr6) Mod(denominator Addr6) Addr6

See Int

func (Addr6) Multiply

func (a Addr6) Multiply(multiplicand Addr6) Addr6

See Int

func (Addr6) Not

func (a Addr6) Not() Addr6

See Int

func (Addr6) Or

func (a Addr6) Or(operand Addr6) Addr6

See Int

func (Addr6) Shift

func (a Addr6) Shift(bits int) Addr6

See Int

func (Addr6) String

func (a Addr6) String() string

Returns RFC 5952 notation.

https://datatracker.ietf.org/doc/html/rfc5952

func (Addr6) Subtract

func (a Addr6) Subtract(subtrahend Addr6) Addr6

See Int

func (Addr6) TrailingZeros

func (a Addr6) TrailingZeros() int

See Int

func (Addr6) Version

func (a Addr6) Version() Version

Returns Version6

func (Addr6) Width

func (a Addr6) Width() int

Returns Width6

func (Addr6) Xor

func (a Addr6) Xor(operand Addr6) Addr6

See Int

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

func FromBytes(address ...byte) (Address, error)

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

func MustFromBytes(address ...byte) Address

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

func MustParseUnknown(candidate string) Address

As ParseUnknown but panics on error

func ParseUnknown

func ParseUnknown(candidate string) (Address, error)

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

func V4() Family[Addr4]

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

func V6() Family[Addr6]

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)
	}
}

type Spec

type Spec interface {

	// IP address version
	Version() (constant Version)
	// Address width in bits - 32 or 128
	Width() (bits int)
	// Informational
	String() string
	// contains filtered or unexported methods
}

Basic specification information.

type Version

type Version uint8

Internet protocol version

const (
	// Internet protocol version 4
	Version4 Version = 4
	// Internet protocol version 6
	Version6 Version = 6
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL