-
-
Notifications
You must be signed in to change notification settings - Fork 23
/
std_anystr2ip.go
147 lines (132 loc) · 4.78 KB
/
std_anystr2ip.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
138
139
140
141
142
143
144
145
146
147
// Code generated by __generator__/interpreter.go at once
package builtin
import (
"fmt"
"net"
"strconv"
"strings"
"github.com/ysugimoto/falco/interpreter/context"
"github.com/ysugimoto/falco/interpreter/function/errors"
"github.com/ysugimoto/falco/interpreter/value"
)
const Std_anystr2ip_Name = "std.anystr2ip"
var Std_anystr2ip_ArgumentTypes = []value.Type{value.StringType, value.StringType}
func Std_anystr2ip_Validate(args []value.Value) error {
if len(args) != 2 {
return errors.ArgumentNotEnough(Std_anystr2ip_Name, 2, args)
}
for i := range args {
if args[i].Type() != Std_anystr2ip_ArgumentTypes[i] {
return errors.TypeMismatch(Std_anystr2ip_Name, i+1, Std_anystr2ip_ArgumentTypes[i], args[i].Type())
}
}
return nil
}
func Std_anystr2ip_ParseString(v string) (int64, error) {
// "0" always indicates zero
if v == "0" {
return 0, nil
}
switch {
case strings.HasPrefix(v, "0x"): // hex
return strconv.ParseInt(strings.TrimPrefix(v, "0x"), 16, 64)
case strings.HasPrefix(v, "0"): // octet
return strconv.ParseInt(strings.TrimPrefix(v, "0"), 8, 64)
default: // decimal
return strconv.ParseInt(v, 10, 64)
}
}
func Std_anystr2ip_ParseIpv4(addr string) (*value.IP, error) {
var ip int64
segments := strings.SplitN(addr, ".", 4)
switch len(segments) {
case 1:
// first segment represetns all bits of IP (xxx.xxx.xxx.xxx)
v, err := Std_anystr2ip_ParseString(segments[0])
if err != nil {
return nil, errors.New(Std_anystr2ip_Name, "Failed to parse IPv4 string: %s", err.Error())
}
ip = v
case 2:
// first segment represetns first bits of IP (xxx.---.---.---)
v1, err := Std_anystr2ip_ParseString(segments[0])
if err != nil {
return nil, errors.New(Std_anystr2ip_Name, "Failed to parse IPv4 string: %s", err.Error())
}
// second segment represetns remainings of IPs (---.xxx.xxx.xxx)
v2, err := Std_anystr2ip_ParseString(segments[1])
if err != nil {
return nil, errors.New(Std_anystr2ip_Name, "Failed to parse IPv4 string: %s", err.Error())
}
ip = (v1 << 24) | v2
case 3:
// first segment represetns first bits of IP (xxx.---.---.---)
v1, err := Std_anystr2ip_ParseString(segments[0])
if err != nil {
return nil, errors.New(Std_anystr2ip_Name, "Failed to parse IPv4 string: %s", err.Error())
}
// second segment represetns second bits of IP (---.xxx.---.---)
v2, err := Std_anystr2ip_ParseString(segments[1])
if err != nil {
return nil, errors.New(Std_anystr2ip_Name, "Failed to parse IPv4 string: %s", err.Error())
}
// thrid segment represetns remainings of IPs (---.---.xxx.xxx)
v3, err := Std_anystr2ip_ParseString(segments[2])
if err != nil {
return nil, errors.New(Std_anystr2ip_Name, "Failed to parse IPv4 string: %s", err.Error())
}
ip = (v1 << 24) | (v2 << 16) | v3
case 4:
// first segment represetns first bits of IP (xxx.---.---.---)
v1, err := Std_anystr2ip_ParseString(segments[0])
if err != nil {
return nil, errors.New(Std_anystr2ip_Name, "Failed to parse IPv4 string: %s", err.Error())
}
// second segment represetns second bits of IP (---.xxx.---.---)
v2, err := Std_anystr2ip_ParseString(segments[1])
if err != nil {
return nil, errors.New(Std_anystr2ip_Name, "Failed to parse IPv4 string: %s", err.Error())
}
// thrid segment represetns third bits of IP (---.---.xxx.---)
v3, err := Std_anystr2ip_ParseString(segments[2])
if err != nil {
return nil, errors.New(Std_anystr2ip_Name, "Failed to parse IPv4 string: %s", err.Error())
}
// last segment represetns fourth bits of IP (---.---.---.xxx)
v4, err := Std_anystr2ip_ParseString(segments[3])
if err != nil {
return nil, errors.New(Std_anystr2ip_Name, "Failed to parse IPv4 string: %s", err.Error())
}
ip = (v1 << 24) | (v2 << 16) | (v3 << 8) | v4
default:
return nil, errors.New(Std_anystr2ip_Name, "Invalid IPv4 string: %s", addr)
}
return &value.IP{
Value: net.ParseIP(
fmt.Sprintf("%d.%d.%d.%d", ((ip >> 24) & 0xFF), ((ip >> 16) & 0xFF), ((ip >> 8) & 0xFF), (ip & 0xFF)),
),
}, nil
}
// Fastly built-in function implementation of std.anystr2ip
// Arguments may be:
// - STRING, STRING
// Reference: https://developer.fastly.com/reference/vcl/functions/strings/std-anystr2ip/
func Std_anystr2ip(ctx *context.Context, args ...value.Value) (value.Value, error) {
// Argument validations
if err := Std_anystr2ip_Validate(args); err != nil {
return value.Null, err
}
addr := value.Unwrap[*value.String](args[0])
fallback := value.Unwrap[*value.String](args[1])
fallbackIP := &value.IP{Value: net.ParseIP(fallback.Value)}
// TODO: support IPv6 string to parse
if strings.Contains(addr.Value, ":") {
return value.Null, errors.New(Std_anystr2ip_Name, "Does not support IPv6 format string")
}
// IPv4 parseing
if v, err := Std_anystr2ip_ParseIpv4(addr.Value); err != nil {
return fallbackIP, nil
} else {
return v, nil
}
}