forked from mattpolzin/JSONAPI
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathResourceObjectCheck.swift
More file actions
95 lines (74 loc) · 3.18 KB
/
ResourceObjectCheck.swift
File metadata and controls
95 lines (74 loc) · 3.18 KB
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
//
// ResourceObjectCheck.swift
// JSONAPITesting
//
// Created by Mathew Polzin on 11/27/18.
//
import JSONAPI
public enum ResourceObjectCheckError: Swift.Error {
/// The attributes should live in a struct, not
/// another type class.
case attributesNotStruct
/// The relationships should live in a struct, not
/// another type class.
case relationshipsNotStruct
/// All stored properties on an Attributes struct should
/// be one of the supplied Attribute types.
case nonAttribute(named: String)
/// All stored properties on a Relationships struct should
/// be one of the supplied Relationship types.
case nonRelationship(named: String)
/// It is explicitly stated by the JSON spec
/// a "none" value for arrays is an empty array, not `nil`.
case nullArray(named: String)
}
public struct ResourceObjectCheckErrors: Swift.Error {
let problems: [ResourceObjectCheckError]
}
private protocol OptionalAttributeType {}
extension Optional: OptionalAttributeType where Wrapped: AttributeType {}
private protocol OptionalArray {}
extension Optional: OptionalArray where Wrapped: ArrayType {}
private protocol AttributeTypeWithOptionalArray {}
extension TransformedAttribute: AttributeTypeWithOptionalArray where RawValue: OptionalArray {}
extension Attribute: AttributeTypeWithOptionalArray where RawValue: OptionalArray {}
private protocol OptionalRelationshipType {}
extension Optional: OptionalRelationshipType where Wrapped: RelationshipType {}
private protocol _RelationshipType {}
extension MetaRelationship: _RelationshipType {}
extension ToOneRelationship: _RelationshipType {}
extension ToManyRelationship: _RelationshipType {}
private protocol _AttributeType {}
extension TransformedAttribute: _AttributeType {}
extension Attribute: _AttributeType {}
public extension ResourceObject {
static func check(_ entity: ResourceObject) throws {
var problems = [ResourceObjectCheckError]()
let attributesMirror = Mirror(reflecting: entity.attributes)
if attributesMirror.displayStyle != .`struct` {
problems.append(.attributesNotStruct)
}
for attribute in attributesMirror.children {
if attribute.value as? _AttributeType == nil,
attribute.value as? OptionalAttributeType == nil {
problems.append(.nonAttribute(named: attribute.label ?? "unnamed"))
}
if attribute.value as? AttributeTypeWithOptionalArray != nil {
problems.append(.nullArray(named: attribute.label ?? "unnamed"))
}
}
let relationshipsMirror = Mirror(reflecting: entity.relationships)
if relationshipsMirror.displayStyle != .`struct` {
problems.append(.relationshipsNotStruct)
}
for relationship in relationshipsMirror.children {
if relationship.value as? _RelationshipType == nil,
relationship.value as? OptionalRelationshipType == nil {
problems.append(.nonRelationship(named: relationship.label ?? "unnamed"))
}
}
guard problems.count == 0 else {
throw ResourceObjectCheckErrors(problems: problems)
}
}
}