Compare commits
	
		
			5 Commits
		
	
	
		
			v0.1.0
			...
			cf39b623ae
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| cf39b623ae | |||
| 023b399a32 | |||
| 0d49fc86d7 | |||
| f35554437d | |||
| 6e26d24a42 | 
@@ -1,9 +1,7 @@
 | 
			
		||||
name: CI
 | 
			
		||||
name: Docs
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
    branches: [ "master" ]
 | 
			
		||||
  pull_request:
 | 
			
		||||
    branches: [ "master" ]
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
@@ -19,9 +17,6 @@ jobs:
 | 
			
		||||
          unzip -q /tmp/v.zip -d /tmp
 | 
			
		||||
          echo /tmp/v >> "$GITHUB_PATH"
 | 
			
		||||
 | 
			
		||||
      - name: Run tests
 | 
			
		||||
        run: v -stats test .
 | 
			
		||||
 | 
			
		||||
      - name: Build docs
 | 
			
		||||
        run: |
 | 
			
		||||
          v doc -f html -m .
 | 
			
		||||
							
								
								
									
										24
									
								
								.github/workflows/test.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								.github/workflows/test.yaml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
name: Tests
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
    branches: [ "master" ]
 | 
			
		||||
  pull_request:
 | 
			
		||||
    branches: [ "master" ]
 | 
			
		||||
  workflow_dispatch:
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  test:
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    steps:
 | 
			
		||||
      - name: Checkout code
 | 
			
		||||
        uses: actions/checkout@v4
 | 
			
		||||
 | 
			
		||||
      - name: Setup V
 | 
			
		||||
        run: |
 | 
			
		||||
          wget -qO /tmp/v.zip https://github.com/vlang/v/releases/latest/download/v_linux.zip
 | 
			
		||||
          unzip -q /tmp/v.zip -d /tmp
 | 
			
		||||
          echo /tmp/v >> "$GITHUB_PATH"
 | 
			
		||||
 | 
			
		||||
      - name: Run tests
 | 
			
		||||
        run: |
 | 
			
		||||
          v -stats test .
 | 
			
		||||
@@ -14,14 +14,15 @@
 | 
			
		||||
// along with netaddr. If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	This file contains functions for operating with big endian ordered byte arrays.
 | 
			
		||||
	Using big.Integer is significantly slower than doing math strictly on 128-bit
 | 
			
		||||
	numbers. At a minimum, you have to do expensive instantiation of big.Integer.
 | 
			
		||||
	The functions below do not require copying arrays and allocate less memory.
 | 
			
		||||
	This file contains functions for operating with 128-bit unsigned integer
 | 
			
		||||
	numbers represented as big endian ordered byte fixed size arrays.
 | 
			
		||||
	Note that arrays always be 16 byte length and may contain leading zeros.
 | 
			
		||||
 | 
			
		||||
	Functions missing:
 | 
			
		||||
		fn add_128(a [16]u8, b [16]u8) [16]u8
 | 
			
		||||
		fn diff_128(a [16]u8, b [16]u8) [16]u8
 | 
			
		||||
	Using V math.big is significantly slower than doing math strictly on
 | 
			
		||||
	128-bit numbers. At a minimum, you have to do expensive instantiation of
 | 
			
		||||
	big.Integer.
 | 
			
		||||
 | 
			
		||||
	The functions below do not requires copying and allocates less memory.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
module netaddr
 | 
			
		||||
@@ -29,6 +30,39 @@ module netaddr
 | 
			
		||||
import math.bits
 | 
			
		||||
 | 
			
		||||
const max_128 = [16]u8{init: 0xff}
 | 
			
		||||
const one_128 = [u8(0), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]!
 | 
			
		||||
 | 
			
		||||
@[direct_array_access; inline]
 | 
			
		||||
fn add_128(a [16]u8, b [16]u8) [16]u8 {
 | 
			
		||||
	mut res := [16]u8{}
 | 
			
		||||
	mut num := u16(0)
 | 
			
		||||
	for i := 15; i >= 0; i-- {
 | 
			
		||||
		num += u16(a[i])
 | 
			
		||||
		num += u16(b[i])
 | 
			
		||||
		res[i] += u8(num % 256)
 | 
			
		||||
		num /= 256
 | 
			
		||||
	}
 | 
			
		||||
	if num > 0 {
 | 
			
		||||
		panic('128 bit overflow detected')
 | 
			
		||||
	}
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@[direct_array_access; inline]
 | 
			
		||||
fn sub_128(a [16]u8, b [16]u8) [16]u8 {
 | 
			
		||||
	mut res := [16]u8{}
 | 
			
		||||
	mut borrowed := u8(0)
 | 
			
		||||
	for i := 15; i >= 0; i-- {
 | 
			
		||||
		if a[i] < b[i] {
 | 
			
		||||
			res[i] = (a[i] + 256) - borrowed - b[i]
 | 
			
		||||
			borrowed = 1
 | 
			
		||||
		} else {
 | 
			
		||||
			res[i] = a[i] - borrowed - b[i]
 | 
			
		||||
			borrowed = 0
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return res
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@[direct_array_access; inline]
 | 
			
		||||
fn bit_len_128(a [16]u8) int {
 | 
			
		||||
@@ -46,7 +46,7 @@ fn main() {
 | 
			
		||||
	if ip is netaddr.Ipv4Net || ip is netaddr.Ipv6Net {
 | 
			
		||||
		panic('${ip} seems to be network, not a single host addresses')
 | 
			
		||||
	}
 | 
			
		||||
	println(addr)
 | 
			
		||||
	println(ip)
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@@ -265,3 +265,9 @@ println(ip) // 2001:db8::8429:6bff:fedc:ef8b
 | 
			
		||||
 | 
			
		||||
Note that using EUI in IPv6 address may cause security issues. See
 | 
			
		||||
[RFC 4941](https://datatracker.ietf.org/doc/html/rfc4941) for details.
 | 
			
		||||
 | 
			
		||||
# License
 | 
			
		||||
 | 
			
		||||
`netaddr` is released under LGPL 3.0 or later license.
 | 
			
		||||
 | 
			
		||||
SPDX Lincese ID: `LGPL-3.0-or-later`.
 | 
			
		||||
 
 | 
			
		||||
@@ -514,7 +514,7 @@ pub:
 | 
			
		||||
	host_address      ?Ipv6Addr
 | 
			
		||||
	prefix_len        int
 | 
			
		||||
mut:
 | 
			
		||||
	current big.Integer
 | 
			
		||||
	current [16]u8
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Ipv6Net.new creates new IPv6 network from given Ipv6Addr and prefix.
 | 
			
		||||
@@ -548,7 +548,7 @@ pub fn Ipv6Net.new(addr Ipv6Addr, prefix int) !Ipv6Net {
 | 
			
		||||
		broadcast_address: broadcast
 | 
			
		||||
		host_address:      host_addr
 | 
			
		||||
		prefix_len:        prefix
 | 
			
		||||
		current:           net_addr.bigint()
 | 
			
		||||
		current:           net_addr.u8_array_fixed()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -617,7 +617,7 @@ pub fn Ipv6Net.from_string(cidr string) !Ipv6Net {
 | 
			
		||||
		broadcast_address: broadcast
 | 
			
		||||
		host_address:      host_addr
 | 
			
		||||
		prefix_len:        prefix_len
 | 
			
		||||
		current:           net_addr.bigint()
 | 
			
		||||
		current:           net_addr.u8_array_fixed()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -639,14 +639,15 @@ pub fn Ipv6Net.from_bigint(addr big.Integer, prefix int) !Ipv6Net {
 | 
			
		||||
	}
 | 
			
		||||
	host_mask := net_mask.bitwise_xor(max_u128)
 | 
			
		||||
	broadcast := net_addr.bitwise_or(host_mask)
 | 
			
		||||
	net_addr6 := Ipv6Addr.from_bigint(net_addr)!
 | 
			
		||||
	return Ipv6Net{
 | 
			
		||||
		network_address:   Ipv6Addr.from_bigint(net_addr)!
 | 
			
		||||
		network_address:   net_addr6
 | 
			
		||||
		network_mask:      Ipv6Addr.from_bigint(net_mask)!
 | 
			
		||||
		host_mask:         Ipv6Addr.from_bigint(host_mask)!
 | 
			
		||||
		broadcast_address: Ipv6Addr.from_bigint(broadcast)!
 | 
			
		||||
		host_address:      host_addr
 | 
			
		||||
		prefix_len:        prefix
 | 
			
		||||
		current:           net_addr
 | 
			
		||||
		current:           net_addr6.u8_array_fixed()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -689,13 +690,15 @@ pub fn (n Ipv6Net) capacity() big.Integer {
 | 
			
		||||
// }
 | 
			
		||||
// ```
 | 
			
		||||
pub fn (mut n Ipv6Net) next() ?Ipv6Addr {
 | 
			
		||||
	if n.current >= n.broadcast_address.bigint() + big.one_int {
 | 
			
		||||
	// Possible optimization: do not calculate `limit` on each fn call (use LRU cache?)
 | 
			
		||||
	limit := add_128(n.broadcast_address.addr, one_128)
 | 
			
		||||
	if compare_128(n.current, limit) in [0, 1] {
 | 
			
		||||
		return none
 | 
			
		||||
	}
 | 
			
		||||
	defer {
 | 
			
		||||
		n.current = n.current + big.one_int
 | 
			
		||||
		n.current = add_128(n.current, one_128)
 | 
			
		||||
	}
 | 
			
		||||
	return Ipv6Addr.from_bigint(n.current)!
 | 
			
		||||
	return Ipv6Addr.from_octets(n.current)!
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// first returns the first usable host address in network.
 | 
			
		||||
@@ -703,7 +706,7 @@ pub fn (n Ipv6Net) first() Ipv6Addr {
 | 
			
		||||
	if n.prefix_len in [127, 128] {
 | 
			
		||||
		return n.network_address
 | 
			
		||||
	}
 | 
			
		||||
	return Ipv6Addr.from_bigint(n.network_address.bigint() + big.one_int) or { panic(err) }
 | 
			
		||||
	return Ipv6Addr.from_octets(add_128(n.network_address.addr, one_128)) or { panic(err) }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// last returns the last usable host address in network.
 | 
			
		||||
@@ -711,7 +714,7 @@ pub fn (n Ipv6Net) last() Ipv6Addr {
 | 
			
		||||
	if n.prefix_len in [127, 128] {
 | 
			
		||||
		return n.broadcast_address
 | 
			
		||||
	}
 | 
			
		||||
	return Ipv6Addr.from_bigint(n.broadcast_address.bigint() - big.one_int) or { panic(err) }
 | 
			
		||||
	return Ipv6Addr.from_octets(sub_128(n.broadcast_address.addr, one_128)) or { panic(err) }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// nth returns the Nth address in network. Supports negative indexes.
 | 
			
		||||
@@ -185,6 +185,12 @@ fn test_ipv6_net_format() {
 | 
			
		||||
	assert net.format(.verbose | .with_host_mask) == 'fe80:ffff:0000:0000:0000:0000:0000:0000/0000:0000:0000:0000:ffff:ffff:ffff:ffff'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_ipv6_net_first_last() {
 | 
			
		||||
	net := netaddr.Ipv6Net.from_string('fe80:ffff::/64')!
 | 
			
		||||
	assert net.first().str() == 'fe80:ffff::1'
 | 
			
		||||
	assert net.last().str() == 'fe80:ffff::ffff:ffff:ffff:fffe'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn test_ipv6_net_next() {
 | 
			
		||||
	net := netaddr.Ipv6Net.from_string('fe80::/64')!
 | 
			
		||||
	mut addrs := []netaddr.Ipv6Addr{}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user