forked from dspinhirne/netaddr-go
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathIPv6NetList.go
More file actions
123 lines (108 loc) · 3.07 KB
/
IPv6NetList.go
File metadata and controls
123 lines (108 loc) · 3.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package netaddr
import (
"fmt"
"sort"
)
// NewIPv6NetList parses a slice of IP networks into a IPv6NetList.
func NewIPv6NetList(networks []string) (IPv6NetList, error) {
list := make(IPv6NetList, len(networks), len(networks))
for i, e := range networks {
net, err := ParseIPv6Net(e)
if err != nil {
return nil, fmt.Errorf("Error parsing item index %d. %s", i, err.Error())
}
list[i] = net
}
return list, nil
}
// IPv6NetList is a slice of IPv6 types
type IPv6NetList []*IPv6Net
// Len is used to implement the sort interface
func (list IPv6NetList) Len() int { return len(list) }
// Less is used to implement the sort interface
func (list IPv6NetList) Less(i, j int) bool {
cmp, _ := list[i].Cmp(list[j])
return cmp == -1
}
// Sort sorts the list using sort.Sort(). Returns itself.
func (list IPv6NetList) Sort() IPv6NetList {
sort.Sort(list)
return list
}
// Summ returns a copy of the list with the contained IPv6Net entries
// sorted and summarized as much as possible.
func (list IPv6NetList) Summ() IPv6NetList {
var summd IPv6NetList
if len(list) > 1 {
summd = list.discardSubnets()
} else if len(list) == 1 {
summd = append(summd, list...)
}
if len(summd) > 1 {
summd = summd.summPeers()
}
return summd
}
// Swap is used to implement the sort interface
func (list IPv6NetList) Swap(i, j int) { list[i], list[j] = list[j], list[i] }
// NON EXPORTED
// discardSubnets returns a sorted copy of the IPv6NetList with
// any entries which are subnets of other entries removed.
func (list IPv6NetList) discardSubnets() IPv6NetList {
var cleaned IPv6NetList
// group into 2 categories: supernets of, and unrelated to
// discard duplicates and subnets of
unrelated := IPv6NetList{}
supernets := IPv6NetList{}
last := list[len(list)-1]
for _, e := range list {
isRel, rel := last.Rel(e)
if !isRel { // last is unrelated to e
unrelated = append(unrelated, e)
} else if isRel && rel == -1 { // last is subnet of e
supernets = append(supernets, e)
}
}
if len(supernets) > 0 {
cleaned = supernets.discardSubnets()
} else {
cleaned = IPv6NetList{last}
}
if len(unrelated) > 0 {
cleaned = append(cleaned, unrelated.discardSubnets()...)
}
return cleaned
}
// summPeers returns a copy of the IPv6NetList with any
// merge-able subnets Summ'd together.
func (list IPv6NetList) summPeers() IPv6NetList {
summd := list.Sort()
for {
listLen := len(summd)
last := listLen - 1
var tmpList IPv6NetList
for i := 0; i < listLen; i += 1 {
net := summd[i]
next := i + 1
if i != last {
// if we can summarize 2 consecutive entries then store the new
// summary net and discard the 2 original networks
newNet := net.Summ(summd[next])
if newNet != nil { // can summarize. keep summary net
tmpList = append(tmpList, newNet)
i += 1 // skip over the next entry
} else { // cant summarize. keep existing
tmpList = append(tmpList, net)
}
} else {
tmpList = append(tmpList, net) // keep last
}
}
// stop if summd is not getting shorter
if len(tmpList) == listLen {
break
}
summd = tmpList
}
return summd
}