-
Notifications
You must be signed in to change notification settings - Fork 16
/
prefixset.go
66 lines (54 loc) · 1.29 KB
/
prefixset.go
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
package prefixset
import (
"fmt"
"net/netip"
"github.com/database64128/shadowsocks-go/bytestrings"
"github.com/database64128/shadowsocks-go/mmap"
"go4.org/netipx"
)
// Config is the configuration for a prefix set.
type Config struct {
Name string `json:"name"`
Path string `json:"path"`
}
// IPSet creates a prefix set from the configuration.
func (psc Config) IPSet() (*netipx.IPSet, error) {
data, err := mmap.ReadFile[string](psc.Path)
if err != nil {
return nil, fmt.Errorf("failed to load prefix set %s: %w", psc.Name, err)
}
defer mmap.Unmap(data)
return IPSetFromText(data)
}
// IPSetFromText parses prefixes from the text and builds a prefix set.
func IPSetFromText(text string) (*netipx.IPSet, error) {
var (
line string
sb netipx.IPSetBuilder
)
for {
line, text = bytestrings.NextNonEmptyLine(text)
if len(line) == 0 {
break
}
if line[0] == '#' {
continue
}
prefix, err := netip.ParsePrefix(line)
if err != nil {
return nil, err
}
sb.AddPrefix(prefix)
}
return sb.IPSet()
}
// IPSetToText returns the text representation of the prefix set.
func IPSetToText(s *netipx.IPSet) []byte {
prefixes := s.Prefixes()
b := make([]byte, 0, 20*len(prefixes))
for _, prefix := range prefixes {
b = prefix.AppendTo(b)
b = append(b, '\n')
}
return b
}