Skip to content

Commit 9c0c863

Browse files
committed
refactor: allow internal validators infrastructure to throw
1 parent 5ddc382 commit 9c0c863

19 files changed

+62
-56
lines changed

Sources/Applicators/additionalItems.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
func additionalItems(context: Context, additionalItems: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
1+
func additionalItems(context: Context, additionalItems: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
22
guard let instance = instance as? [Any], let items = schema["items"] as? [Any], instance.count > items.count else {
33
return AnySequence(EmptyCollection())
44
}
55

66
if let additionalItems = additionalItems as? [String: Any] {
7-
return AnySequence(Array(instance.enumerated())[items.count...].map { (index, subinstance) -> AnySequence<ValidationError> in
7+
return try AnySequence(Array(instance.enumerated())[items.count...].map { (index, subinstance) throws -> AnySequence<ValidationError> in
88
context.instanceLocation.push(index.description)
99
defer { context.instanceLocation.pop() }
10-
return context.descend(instance: subinstance, subschema: additionalItems)
10+
return try context.descend(instance: subinstance, subschema: additionalItems)
1111
}.joined())
1212
}
1313

Sources/Applicators/additionalProperties.swift

+4-2
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,17 @@ func findAdditionalProperties(instance: [String: Any], schema: [String: Any]) ->
2525
}
2626

2727

28-
func additionalProperties(context: Context, additionalProperties: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
28+
func additionalProperties(context: Context, additionalProperties: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
2929
guard let instance = instance as? [String: Any] else {
3030
return AnySequence(EmptyCollection())
3131
}
3232

3333
let extras = findAdditionalProperties(instance: instance, schema: schema)
3434

3535
if let additionalProperties = additionalProperties as? [String: Any] {
36-
return AnySequence(extras.map { context.descend(instance: instance[$0]!, subschema: additionalProperties) }.joined())
36+
return try AnySequence(extras.map {
37+
try context.descend(instance: instance[$0]!, subschema: additionalProperties)
38+
}.joined())
3739
}
3840

3941
if let additionalProperties = additionalProperties as? Bool, !additionalProperties && !extras.isEmpty {

Sources/Applicators/allOf.swift

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
func allOf(context: Context, allOf: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
1+
func allOf(context: Context, allOf: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
22
guard let allOf = allOf as? [Any] else {
33
return AnySequence(EmptyCollection())
44
}
55

6-
return AnySequence(allOf.map({ context.descend(instance: instance, subschema: $0) }).joined())
6+
return try AnySequence(allOf.map({
7+
try context.descend(instance: instance, subschema: $0)
8+
}).joined())
79
}

Sources/Applicators/anyOf.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
func anyOf(context: Context, anyOf: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
1+
func anyOf(context: Context, anyOf: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
22
guard let anyOf = anyOf as? [Any] else {
33
return AnySequence(EmptyCollection())
44
}
55

6-
if !anyOf.contains(where: { context.descend(instance: instance, subschema: $0).isValid }) {
6+
if try !anyOf.contains(where: { try context.descend(instance: instance, subschema: $0).isValid }) {
77
return AnySequence([
88
ValidationError(
99
"\(instance) does not meet anyOf validation rules.",

Sources/Applicators/contains.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
func contains(context: Context, contains: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
1+
func contains(context: Context, contains: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
22
guard let instance = instance as? [Any] else {
33
return AnySequence(EmptyCollection())
44
}
@@ -22,10 +22,10 @@ func contains(context: Context, contains: Any, instance: Any, schema: [String: A
2222
return AnySequence(EmptyCollection())
2323
}
2424

25-
let containsCount = Array(instance.enumerated()).filter({ (index, subinstance) -> Bool in
25+
let containsCount = try Array(instance.enumerated()).filter({ (index, subinstance) throws -> Bool in
2626
context.instanceLocation.push(index.description)
2727
defer { context.instanceLocation.pop() }
28-
return context.descend(instance: subinstance, subschema: contains).isValid
28+
return try context.descend(instance: subinstance, subschema: contains).isValid
2929
}).count
3030
if let max = max, containsCount > max {
3131
return AnySequence([

Sources/Applicators/dependencies.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
func dependencies(context: Context, dependencies: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
1+
func dependencies(context: Context, dependencies: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
22
guard let dependencies = dependencies as? [String: Any] else {
33
return AnySequence(EmptyCollection())
44
}
@@ -22,7 +22,7 @@ func dependencies(context: Context, dependencies: Any, instance: Any, schema: [S
2222
}
2323
}
2424
} else {
25-
results.append(context.descend(instance: instance, subschema: dependency))
25+
results.append(try context.descend(instance: instance, subschema: dependency))
2626
}
2727
}
2828

Sources/Applicators/dependentSchemas.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
func dependentSchemas(context: Context, dependentRequired: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
1+
func dependentSchemas(context: Context, dependentRequired: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
22
guard let instance = instance as? [String: Any] else {
33
return AnySequence(EmptyCollection())
44
}
@@ -7,9 +7,9 @@ func dependentSchemas(context: Context, dependentRequired: Any, instance: Any, s
77
return AnySequence(EmptyCollection())
88
}
99

10-
return AnySequence(dependentRequired.compactMap({ (key, subschema) -> AnySequence<ValidationError> in
10+
return try AnySequence(dependentRequired.compactMap({ (key, subschema) throws -> AnySequence<ValidationError> in
1111
if instance.keys.contains(key) {
12-
return context.descend(instance: instance, subschema: subschema)
12+
return try context.descend(instance: instance, subschema: subschema)
1313
}
1414

1515
return AnySequence(EmptyCollection())

Sources/Applicators/if.swift

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
func `if`(context: Context, `if`: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
2-
if context.validate(instance: instance, schema: `if`).isValid {
1+
func `if`(context: Context, `if`: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
2+
if try context.validate(instance: instance, schema: `if`).isValid {
33
if let then = schema["then"] {
4-
return context.descend(instance: instance, subschema: then)
4+
return try context.descend(instance: instance, subschema: then)
55
}
66
} else if let `else` = schema["else"] {
7-
return context.descend(instance: instance, subschema: `else`)
7+
return try context.descend(instance: instance, subschema: `else`)
88
}
99

1010
return AnySequence(EmptyCollection())

Sources/Applicators/items.swift

+7-7
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
1-
func items(context: Context, items: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
1+
func items(context: Context, items: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
22
guard let instance = instance as? [Any] else {
33
return AnySequence(EmptyCollection())
44
}
55

66
if let items = items as? [String: Any] {
7-
return AnySequence(Array(instance.enumerated()).map { (index, instance) -> AnySequence<ValidationError> in
7+
return try AnySequence(Array(instance.enumerated()).map { (index, instance) throws -> AnySequence<ValidationError> in
88
context.instanceLocation.push(index.description)
99
defer { context.instanceLocation.pop() }
10-
return context.descend(instance: instance, subschema: items)
10+
return try context.descend(instance: instance, subschema: items)
1111
}.joined())
1212
}
1313

1414
if let items = items as? Bool {
15-
return AnySequence(Array(instance.enumerated()).map { (index, instance) -> AnySequence<ValidationError> in
15+
return try AnySequence(Array(instance.enumerated()).map { (index, instance) throws -> AnySequence<ValidationError> in
1616
context.instanceLocation.push(index.description)
1717
defer { context.instanceLocation.pop() }
18-
return context.descend(instance: instance, subschema: items)
18+
return try context.descend(instance: instance, subschema: items)
1919
}.joined())
2020
}
2121

@@ -24,8 +24,8 @@ func items(context: Context, items: Any, instance: Any, schema: [String: Any]) -
2424

2525
for (index, item) in instance.enumerated() where index < items.count {
2626
context.instanceLocation.push(index.description)
27-
results.append(context.descend(instance: item, subschema: items[index]))
28-
context.instanceLocation.pop()
27+
defer { context.instanceLocation.pop() }
28+
results.append(try context.descend(instance: item, subschema: items[index]))
2929
}
3030

3131
return AnySequence(results.joined())

Sources/Applicators/not.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
func not(context: Context, not: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
2-
guard context.descend(instance: instance, subschema: not).isValid else {
1+
func not(context: Context, not: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
2+
guard try context.descend(instance: instance, subschema: not).isValid else {
33
return AnySequence(EmptyCollection())
44
}
55

Sources/Applicators/oneOf.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
func oneOf(context: Context, oneOf: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
1+
func oneOf(context: Context, oneOf: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
22
guard let oneOf = oneOf as? [Any] else {
33
return AnySequence(EmptyCollection())
44
}
55

6-
if oneOf.filter({ context.descend(instance: instance, subschema: $0).isValid }).count != 1 {
6+
if try oneOf.filter({ try context.descend(instance: instance, subschema: $0).isValid }).count != 1 {
77
return AnySequence([
88
ValidationError(
99
"Only one value from `oneOf` should be met",

Sources/Applicators/patternProperties.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Foundation
22

33

4-
func patternProperties(context: Context, patternProperties: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
4+
func patternProperties(context: Context, patternProperties: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
55
guard let instance = instance as? [String: Any] else {
66
return AnySequence(EmptyCollection())
77
}
@@ -21,8 +21,8 @@ func patternProperties(context: Context, patternProperties: Any, instance: Any,
2121

2222
for key in keys {
2323
context.instanceLocation.push(key)
24-
results.append(context.descend(instance: instance[key]!, subschema: schema))
25-
context.instanceLocation.pop()
24+
defer { context.instanceLocation.pop() }
25+
results.append(try context.descend(instance: instance[key]!, subschema: schema))
2626
}
2727
} catch {
2828
return AnySequence([

Sources/Applicators/properties.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
func properties(context: Context, properties: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
1+
func properties(context: Context, properties: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
22
guard let instance = instance as? [String: Any] else {
33
return AnySequence(EmptyCollection())
44
}
@@ -7,11 +7,11 @@ func properties(context: Context, properties: Any, instance: Any, schema: [Strin
77
return AnySequence(EmptyCollection())
88
}
99

10-
return AnySequence(instance.map { (key, value) -> AnySequence<ValidationError> in
10+
return try AnySequence(instance.map { (key, value) throws -> AnySequence<ValidationError> in
1111
if let schema = properties[key] {
1212
context.instanceLocation.push(key)
1313
defer { context.instanceLocation.pop() }
14-
return context.descend(instance: value, subschema: schema)
14+
return try context.descend(instance: value, subschema: schema)
1515
}
1616

1717
return AnySequence(EmptyCollection())
+4-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
func propertyNames(context: Context, propertyNames: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
1+
func propertyNames(context: Context, propertyNames: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
22
guard let instance = instance as? [String: Any] else {
33
return AnySequence(EmptyCollection())
44
}
55

6-
return AnySequence(instance.keys.map { context.descend(instance: $0, subschema: propertyNames) }.joined())
6+
return try AnySequence(instance.keys.map {
7+
try context.descend(instance: $0, subschema: propertyNames)
8+
}.joined())
79
}

Sources/Core/ref.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
func ref(context: Context, reference: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
1+
func ref(context: Context, reference: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
22
guard let reference = reference as? String else {
33
return AnySequence(EmptyCollection())
44
}
@@ -28,5 +28,5 @@ func ref(context: Context, reference: Any, instance: Any, schema: [String: Any])
2828
}
2929
}
3030

31-
return context.descend(instance: instance, subschema: document)
31+
return try context.descend(instance: instance, subschema: document)
3232
}

Sources/Validation/dependentRequired.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
func dependentRequired(context: Context, dependentRequired: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
1+
func dependentRequired(context: Context, dependentRequired: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
22
guard let instance = instance as? [String: Any] else {
33
return AnySequence(EmptyCollection())
44
}
@@ -7,9 +7,9 @@ func dependentRequired(context: Context, dependentRequired: Any, instance: Any,
77
return AnySequence(EmptyCollection())
88
}
99

10-
return AnySequence(dependentRequired.compactMap({ (key, required) -> AnySequence<ValidationError> in
10+
return try AnySequence(dependentRequired.compactMap({ (key, required) -> AnySequence<ValidationError> in
1111
if instance.keys.contains(key) {
12-
return JSONSchema.required(context: context, required: required, instance: instance, schema: schema)
12+
return try JSONSchema.required(context: context, required: required, instance: instance, schema: schema)
1313
}
1414

1515
return AnySequence(EmptyCollection())

Sources/Validation/required.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
func required(context: Context, required: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
1+
func required(context: Context, required: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
22
guard let instance = instance as? [String: Any] else {
33
return AnySequence(EmptyCollection())
44
}

Sources/Validator.swift

+9-9
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class Context {
1111
self.validator = validator
1212
}
1313

14-
func validate(instance: Any, schema: Any) -> AnySequence<ValidationError> {
14+
func validate(instance: Any, schema: Any) throws -> AnySequence<ValidationError> {
1515
if let schema = schema as? Bool {
1616
if schema == true {
1717
return AnySequence(EmptyCollection())
@@ -30,13 +30,13 @@ class Context {
3030
// Older versions of JSON Schema, $ref ignores any alongside keywords
3131
if let ref = schema["$ref"] as? String {
3232
let validation = validator.validations["$ref"]!
33-
return validation(self, ref, instance, schema)
33+
return try validation(self, ref, instance, schema)
3434
}
3535
}
3636

37-
return AnySequence(validator.validations.compactMap { (key, validation) -> AnySequence<ValidationError> in
37+
return try AnySequence(validator.validations.compactMap { (key, validation) -> AnySequence<ValidationError> in
3838
if let value = schema[key] {
39-
return validation(self, value, instance, schema)
39+
return try validation(self, value, instance, schema)
4040
}
4141

4242
return AnySequence(EmptyCollection())
@@ -47,13 +47,13 @@ class Context {
4747
return resolver.resolve(reference: ref)
4848
}
4949

50-
func descend(instance: Any, subschema: Any) -> AnySequence<ValidationError> {
51-
return validate(instance: instance, schema: subschema)
50+
func descend(instance: Any, subschema: Any) throws -> AnySequence<ValidationError> {
51+
return try validate(instance: instance, schema: subschema)
5252
}
5353
}
5454

5555
protocol Validator {
56-
typealias Validation = (Context, Any, Any, [String: Any]) -> AnySequence<ValidationError>
56+
typealias Validation = (Context, Any, Any, [String: Any]) throws -> AnySequence<ValidationError>
5757

5858
var resolver: RefResolver { get }
5959

@@ -66,11 +66,11 @@ protocol Validator {
6666
extension Validator {
6767
public func validate(instance: Any) throws -> ValidationResult {
6868
let context = Context(resolver: resolver, validator: self)
69-
return context.validate(instance: instance, schema: schema).validationResult()
69+
return try context.validate(instance: instance, schema: schema).validationResult()
7070
}
7171

7272
public func validate(instance: Any) throws -> AnySequence<ValidationError> {
7373
let context = Context(resolver: resolver, validator: self)
74-
return context.validate(instance: instance, schema: schema)
74+
return try context.validate(instance: instance, schema: schema)
7575
}
7676
}

Sources/format.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Foundation
22

33

4-
func format(context: Context, format: Any, instance: Any, schema: [String: Any]) -> AnySequence<ValidationError> {
4+
func format(context: Context, format: Any, instance: Any, schema: [String: Any]) throws -> AnySequence<ValidationError> {
55
guard let format = format as? String else {
66
return AnySequence(EmptyCollection())
77
}

0 commit comments

Comments
 (0)