Add the range.CIDRs functions

This commit is contained in:
Martynas Pumputis authored and Bryan Boreham committed 2016-06-08 16:44:54 +01:00
1 parent 6062627582
commit 2266868648
2 files changed
+56

No files matched your search

+34
View File
@@ -73,6 +73,40 @@ type CIDR struct {
PrefixLen int
}
// CIDRs returns a list of CIDR-aligned ranges which cover this range.
func (r Range) CIDRs() []CIDR {
const (
fullMask = ^Address(0)
cidrMaxPrefixLen = 32
)
var cidrs []CIDR
for start, end := r.Start, r.End-1; end >= start; {
mask, prefixLen := fullMask, cidrMaxPrefixLen
// Find the smallest mask which would cover some part of [start;end].
// Once we found such, apply it by OR'ing
for mask > 0 {
tmpMask := mask << 1
// Check whether mask neither too short nor too long
if (start&tmpMask) != start || (start|^tmpMask) > end {
break
}
mask = tmpMask
prefixLen--
}
cidrs = append(cidrs, CIDR{start, prefixLen})
// Apply mask
start |= ^mask
// Check for overflow
if start+1 < start {
break
}
start++
}
return cidrs
}
func ParseIP(s string) (Address, error) {
if ip := net.ParseIP(s); ip != nil {
return FromIP4(ip), nil
+22
View File
@@ -39,3 +39,25 @@ func TestBiggestPow2AlignedRange(t *testing.T) {
}
require.NoError(t, quick.Check(prop, &quick.Config{MaxCount: 1000000}))
}
func ip(s string) Address {
addr, _ := ParseIP(s)
return addr
}
func cidr(s string) CIDR {
c, err := ParseCIDR(s)
if err != nil {
panic(err)
}
return c
}
func TestCIDRs(t *testing.T) {
start := ip("10.0.0.1")
end := ip("10.0.0.9")
r := NewRange(start, Subtract(end, start))
require.Equal(t,
[]CIDR{cidr("10.0.0.1/32"), cidr("10.0.0.2/31"), cidr("10.0.0.4/30"), cidr("10.0.0.8/32")},
r.CIDRs())
}