This repository has been archived by the owner on Jul 24, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
val_string.go
115 lines (104 loc) · 2.91 KB
/
val_string.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
package jsonschema
import (
"encoding/json"
"fmt"
"net"
"net/url"
"regexp"
"strings"
"unicode/utf8"
)
type maxLength int
func (m maxLength) Validate(keypath []string, v interface{}) []ValidationError {
l, ok := v.(string)
if !ok {
return nil
}
if utf8.RuneCountInString(l) > int(m) {
lenErr := ValidationError{keypath, fmt.Sprintf("String length must be shorter than %d characters.", m)}
return []ValidationError{lenErr}
}
return nil
}
type minLength int
func (m minLength) Validate(keypath []string, v interface{}) []ValidationError {
l, ok := v.(string)
if !ok {
return nil
}
if utf8.RuneCountInString(l) < int(m) {
lenErr := ValidationError{keypath, fmt.Sprintf("String length must be shorter than %d characters.", m)}
return []ValidationError{lenErr}
}
return nil
}
type pattern struct {
regexp.Regexp
}
func (p *pattern) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
r, err := regexp.Compile(s)
if err != nil {
return err
}
p.Regexp = *r
return nil
}
func (p pattern) Validate(keypath []string, v interface{}) []ValidationError {
s, ok := v.(string)
if !ok {
return nil
}
if !p.MatchString(s) {
patErr := ValidationError{keypath, fmt.Sprintf("String must match the pattern: \"%s\".", p.String())}
return []ValidationError{patErr}
}
return nil
}
type format string
var dateTimeRegexp = regexp.MustCompile(`^([0-9]{4})-([0-9]{2})-([0-9]{2})([Tt]([0-9]{2}):([0-9]{2}):([0-9]{2})(\.[0-9]+)?)?([Tt]([0-9]{2}):([0-9]{2}):([0-9]{2})(\\.[0-9]+)?)?(([Zz]|([+-])([0-9]{2}):([0-9]{2})))?`)
var mailRegexp = regexp.MustCompile(".+@.+")
var hostnameRegexp = regexp.MustCompile(`^[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?(\.[a-zA-Z](([-0-9a-zA-Z]+)?[0-9a-zA-Z])?)*$`)
func (f format) Validate(keypath []string, v interface{}) []ValidationError {
s, ok := v.(string)
if !ok {
return nil
}
switch f {
case "date-time":
if !dateTimeRegexp.MatchString(s) {
return []ValidationError{{keypath, "Value must conform to RFC3339."}}
}
case "uri":
if _, err := url.ParseRequestURI(s); err != nil {
return []ValidationError{{keypath, "Value must be a valid URI, according to RFC3986."}}
}
case "email":
if !mailRegexp.MatchString(s) {
return []ValidationError{{keypath, "Value must be a valid email address, according to RFC5322."}}
}
case "ipv4":
if net.ParseIP(s).To4() == nil {
return []ValidationError{{keypath, "Value must be a valid IPv4 address."}}
}
case "ipv6":
if net.ParseIP(s).To16() == nil {
return []ValidationError{{keypath, "Value must be a valid IPv6 address."}}
}
case "hostname":
formatErr := []ValidationError{{keypath, "Value must be a valid hostname."}}
if !hostnameRegexp.MatchString(s) || utf8.RuneCountInString(s) > 255 {
return formatErr
}
labels := strings.Split(s, ".")
for _, label := range labels {
if utf8.RuneCountInString(label) > 63 {
return formatErr
}
}
}
return nil
}