-
Notifications
You must be signed in to change notification settings - Fork 0
/
parsers.go
137 lines (118 loc) · 3.17 KB
/
parsers.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
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package asn
import (
"encoding/binary"
"strconv"
"strings"
)
// MustDecimal parses an ASN in decimal/asplain format and panics if the input is invalid.
func MustDecimal(d string) ASN {
a, err := FromDecimal(d)
if err != nil {
panic(err)
}
return a
}
// MustASDot parses an ASN in asdot format and panics if the input is invalid.
func MustASDot(d string) ASN {
a, err := FromASDot(d)
if err != nil {
panic(err)
}
return a
}
// MustParse parses an ASN in any valid format and panics if the input is invalid.
func MustParse(d string) ASN {
a, err := Parse(d)
if err != nil {
panic(err)
}
return a
}
// FromDecimal parses an ASN in decimal/asplain format and returns an error if the input is invalid.
func FromDecimal(i string) (ASN, error) {
matches := asDecimalPattern.FindStringSubmatch(i)
if len(matches) == 0 {
return nil, ErrInvalidInput
}
i = matches[len(matches)-1]
n64, err := strconv.ParseUint(i, 10, 32)
if err != nil {
return nil, ErrOutOf4ByteRange
}
n := uint32(n64)
a := make(ASN, BYTE_SIZE)
binary.BigEndian.PutUint32(a, n)
return a, nil
}
// FromASDot parses an ASN in asdot format and returns an error if the input is invalid.
func FromASDot(i string) (ASN, error) {
matches := asdotPattern.FindStringSubmatch(i)
if len(matches) == 0 {
return nil, ErrInvalidInput
}
i = matches[len(matches)-1]
parts := strings.Split(strings.TrimSpace(i), ".")
asn := make(ASN, 4)
high, err := strconv.Atoi(parts[0])
if err != nil {
return nil, ErrInvalidInput
}
low, err := strconv.Atoi(parts[1])
if err != nil {
return nil, ErrInvalidInput
}
if high < 0 || high > 65535 || low < 0 || low > 65535 {
return nil, ErrOutOf2ByteRange
}
asn[0] = byte(high >> 8)
asn[1] = byte(high)
asn[2] = byte(low >> 8)
asn[3] = byte(low)
return asn, nil
}
// FromUint32 parses an ASN from an unsigned 32-bit integer.
func FromUint32(n uint32) ASN {
a := make(ASN, BYTE_SIZE)
binary.BigEndian.PutUint32(a, n)
return a
}
// FromUint64 parses an ASN from an unsigned 64-bit integer and returns an error if the value is
// greater than 32 bits.
func FromUint64(n uint64) (ASN, error) {
if n > uint64(MAX_32) {
return nil, ErrOutOf4ByteRange
}
a := make(ASN, BYTE_SIZE)
binary.BigEndian.PutUint32(a, uint32(n))
return a, nil
}
// From4Bytes creates an ASN object from 4 bytes.
func From4Bytes(one, two, three, four byte) ASN {
return ASN{one, two, three, four}
}
// From2Bytes creates an ASN object from 2 bytes.
func From2Bytes(one, two byte) ASN {
return ASN{0, 0, one, two}
}
// FromBytes creates an ASN object from either 2 or 4 bytes. An error is returned if the number of
// bytes provided is not 2 or 4.
func FromBytes(bytes ...byte) (ASN, error) {
if len(bytes) != 2 && len(bytes) != 4 {
return nil, ErrOutOf4ByteRange
}
if len(bytes) == 2 {
return From2Bytes(bytes[0], bytes[1]), nil
}
return From4Bytes(bytes[0], bytes[1], bytes[2], bytes[3]), nil
}
// Parse parses and validates an ASN from an input string. An error is returned if the input is
// invalid.
func Parse(in string) (ASN, error) {
if asdotPattern.MatchString(in) {
return FromASDot(in)
}
if asDecimalPattern.MatchString(in) {
return FromDecimal(in)
}
return nil, ErrInvalidInput
}