-
Notifications
You must be signed in to change notification settings - Fork 76
/
Copy pathformat.swift
148 lines (122 loc) · 4.56 KB
/
format.swift
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
148
import Foundation
func format(context: Context, format: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
guard let format = format as? String else {
return AnySequence(EmptyCollection())
}
guard let instance = instance as? String else {
return AnySequence(EmptyCollection())
}
guard let validator = context.validator.formats[format] else {
return AnySequence([
ValidationError(
"'format' validation of '\(format)' is not yet supported.",
instanceLocation: context.instanceLocation,
keywordLocation: context.keywordLocation
)
])
}
return validator(context, instance)
}
func validateIPv4(_ context: Context, _ value: String) -> AnySequence<ValidationError> {
if let expression = try? NSRegularExpression(pattern: "^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$", options: NSRegularExpression.Options(rawValue: 0)) {
if expression.matches(in: value, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, value.utf16.count)).count == 1 {
return AnySequence(EmptyCollection())
}
}
return AnySequence([
ValidationError(
"'\(value)' is not a IPv4 address.",
instanceLocation: context.instanceLocation,
keywordLocation: context.keywordLocation
)
])
}
func validateIPv6(_ context: Context, _ value: String) -> AnySequence<ValidationError> {
if !value.contains("%") {
var buf = UnsafeMutablePointer<Int8>.allocate(capacity: Int(INET6_ADDRSTRLEN))
if inet_pton(AF_INET6, value, &buf) == 1 {
return AnySequence(EmptyCollection())
}
}
return AnySequence([
ValidationError(
"'\(value)' is not a value address.",
instanceLocation: context.instanceLocation,
keywordLocation: context.keywordLocation
)
])
}
func validateURI(_ context: Context, _ value: String) -> AnySequence<ValidationError> {
// Using the regex from http://blog.dieweltistgarnichtso.net/constructing-a-regular-expression-that-matches-uris
if let expression = try? NSRegularExpression(pattern: "((?<=\\()[A-Za-z][A-Za-z0-9\\+\\.\\-]*:([A-Za-z0-9\\.\\-_~:/\\?#\\[\\]@!\\$&'\\(\\)\\*\\+,;=]|%[A-Fa-f0-9]{2})+(?=\\)))|([A-Za-z][A-Za-z0-9\\+\\.\\-]*:([A-Za-z0-9\\.\\-_~:/\\?#\\[\\]@!\\$&'\\(\\)\\*\\+,;=]|%[A-Fa-f0-9]{2})+)", options: NSRegularExpression.Options(rawValue: 0)) {
let result = expression.matches(in: value, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, value.utf16.count))
if result.count == 1 {
let foundRange = result[0].range
if foundRange.location == 0 && foundRange.length == value.utf16.count {
return AnySequence(EmptyCollection())
}
}
}
return AnySequence([
ValidationError(
"'\(value)' is not a valid uri.",
instanceLocation: context.instanceLocation,
keywordLocation: context.keywordLocation
)
])
}
func validateUUID(_ context: Context, _ value: String) -> AnySequence<ValidationError> {
if UUID(uuidString: value) == nil {
return AnySequence([
ValidationError(
"'\(value)' is not a valid uuid.",
instanceLocation: context.instanceLocation,
keywordLocation: context.keywordLocation
)
])
}
return AnySequence(EmptyCollection())
}
func validateRegex(_ context: Context, _ value: String) -> AnySequence<ValidationError> {
do {
_ = try NSRegularExpression(pattern: value)
} catch {
return AnySequence([
ValidationError(
"'\(value)' is not a valid regex.",
instanceLocation: context.instanceLocation,
keywordLocation: context.keywordLocation
)
])
}
return AnySequence(EmptyCollection())
}
func validateJSONPointer(_ context: Context, _ value: String) -> AnySequence<ValidationError> {
guard !value.isEmpty else {
return AnySequence(EmptyCollection())
}
if !value.hasPrefix("/") {
return AnySequence([
ValidationError(
"'\(value)' is not a valid json-pointer.",
instanceLocation: context.instanceLocation,
keywordLocation: context.keywordLocation
)
])
}
if value
.replacingOccurrences(of: "~0", with: "")
.replacingOccurrences(of: "~1", with: "")
.contains("~")
{
// unescaped ~
return AnySequence([
ValidationError(
"'\(value)' is not a valid json-pointer.",
instanceLocation: context.instanceLocation,
keywordLocation: context.keywordLocation
)
])
}
return AnySequence(EmptyCollection())
}