9 // The packed format is an 8 byte integer of the number of ranges. Then 20
10 // bytes per range, consisting of 4 byte packed IP being the lower bound IP of
11 // the range, then 4 bytes of the upper, inclusive bound, 8 bytes for the
12 // offset of the description from the end of the packed ranges, and 4 bytes
13 // for the length of the description. After these packed ranges, are the
14 // concatenated descriptions.
17 packedRangesOffset = 8
21 func (me *IPList) WritePacked(w io.Writer) (err error) {
22 descOffsets := make(map[string]int64, len(me.ranges))
23 descs := make([]string, 0, len(me.ranges))
25 // This is a little monadic, no?
26 write := func(b []byte, expectedLen int) {
40 binary.LittleEndian.PutUint64(b[:], uint64(len(me.ranges)))
42 for _, r := range me.ranges {
43 write(r.First.To4(), 4)
44 write(r.Last.To4(), 4)
45 descOff, ok := descOffsets[r.Description]
48 descOffsets[r.Description] = descOff
49 descs = append(descs, r.Description)
50 nextOffset += int64(len(r.Description))
52 binary.LittleEndian.PutUint64(b[:], uint64(descOff))
54 binary.LittleEndian.PutUint32(b[:], uint32(len(r.Description)))
57 for _, d := range descs {
58 write([]byte(d), len(d))
63 func NewFromPacked(b []byte) PackedIPList {
64 return PackedIPList(b)
67 type PackedIPList []byte
69 var _ Ranger = PackedIPList{}
71 func (me PackedIPList) len() int {
72 return int(binary.LittleEndian.Uint64(me[:8]))
75 func (me PackedIPList) NumRanges() int {
79 func (me PackedIPList) getRange(i int) (ret Range) {
80 rOff := packedRangesOffset + packedRangeLen*i
81 first := me[rOff : rOff+4]
82 last := me[rOff+4 : rOff+8]
83 descOff := int(binary.LittleEndian.Uint64(me[rOff+8:]))
84 descLen := int(binary.LittleEndian.Uint32(me[rOff+16:]))
85 descOff += packedRangesOffset + packedRangeLen*me.len()
86 ret = Range{net.IP(first), net.IP(last), string(me[descOff : descOff+descLen])}
90 func (me PackedIPList) Lookup(ip net.IP) (r *Range) {
93 // If the IP list was built successfully, then it only contained IPv4
94 // ranges. Therefore no IPv6 ranges are blocked.
97 Description: "bad IP",
102 return lookup(me.getRange, me.len(), ip4)