mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-03-30 11:18:38 -07:00
Add Poly7 and Include7 because why not
This commit is contained in:
@@ -115,4 +115,11 @@ extension Includes where I: _Poly6 {
|
||||
}
|
||||
|
||||
// MARK: - 7 includes
|
||||
public typealias Include7 = Poly7
|
||||
extension Includes where I: _Poly7 {
|
||||
public subscript(_ lookup: I.G.Type) -> [I.G] {
|
||||
return values.compactMap { $0.g }
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 8 includes
|
||||
|
||||
@@ -644,3 +644,158 @@ extension Poly6: CustomStringConvertible {
|
||||
return "Poly(\(str))"
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 7 types
|
||||
public protocol _Poly7: _Poly6 {
|
||||
associatedtype G: EntityType
|
||||
var g: G? { get }
|
||||
|
||||
init(_ g: G)
|
||||
}
|
||||
|
||||
public extension _Poly7 {
|
||||
subscript(_ lookup: G.Type) -> G? {
|
||||
return g
|
||||
}
|
||||
}
|
||||
|
||||
public enum Poly7<A: EntityType, B: EntityType, C: EntityType, D: EntityType, E: EntityType, F: EntityType, G: EntityType>: _Poly7 {
|
||||
case a(A)
|
||||
case b(B)
|
||||
case c(C)
|
||||
case d(D)
|
||||
case e(E)
|
||||
case f(F)
|
||||
case g(G)
|
||||
|
||||
public var a: A? {
|
||||
guard case let .a(ret) = self else { return nil }
|
||||
return ret
|
||||
}
|
||||
|
||||
public init(_ a: A) {
|
||||
self = .a(a)
|
||||
}
|
||||
|
||||
public var b: B? {
|
||||
guard case let .b(ret) = self else { return nil }
|
||||
return ret
|
||||
}
|
||||
|
||||
public init(_ b: B) {
|
||||
self = .b(b)
|
||||
}
|
||||
|
||||
public var c: C? {
|
||||
guard case let .c(ret) = self else { return nil }
|
||||
return ret
|
||||
}
|
||||
|
||||
public init(_ c: C) {
|
||||
self = .c(c)
|
||||
}
|
||||
|
||||
public var d: D? {
|
||||
guard case let .d(ret) = self else { return nil }
|
||||
return ret
|
||||
}
|
||||
|
||||
public init(_ d: D) {
|
||||
self = .d(d)
|
||||
}
|
||||
|
||||
public var e: E? {
|
||||
guard case let .e(ret) = self else { return nil }
|
||||
return ret
|
||||
}
|
||||
|
||||
public init(_ e: E) {
|
||||
self = .e(e)
|
||||
}
|
||||
|
||||
public var f: F? {
|
||||
guard case let .f(ret) = self else { return nil }
|
||||
return ret
|
||||
}
|
||||
|
||||
public init(_ f: F) {
|
||||
self = .f(f)
|
||||
}
|
||||
|
||||
public var g: G? {
|
||||
guard case let .g(ret) = self else { return nil }
|
||||
return ret
|
||||
}
|
||||
|
||||
public init(_ g: G) {
|
||||
self = .g(g)
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
|
||||
let attempts = [
|
||||
try decode(A.self, from: container).map { Poly7.a($0) },
|
||||
try decode(B.self, from: container).map { Poly7.b($0) },
|
||||
try decode(C.self, from: container).map { Poly7.c($0) },
|
||||
try decode(D.self, from: container).map { Poly7.d($0) },
|
||||
try decode(E.self, from: container).map { Poly7.e($0) },
|
||||
try decode(F.self, from: container).map { Poly7.f($0) },
|
||||
try decode(G.self, from: container).map { Poly7.g($0) }]
|
||||
|
||||
let maybeVal: Poly7<A, B, C, D, E, F, G>? = attempts
|
||||
.compactMap { $0.value }
|
||||
.first
|
||||
|
||||
guard let val = maybeVal else {
|
||||
throw EncodingError.invalidValue(Poly7<A, B, C, D, E, F, G>.self, .init(codingPath: decoder.codingPath, debugDescription: "Failed to find an include of the expected type. Attempts: \(attempts.map { $0.error }.compactMap { $0 })"))
|
||||
}
|
||||
|
||||
self = val
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
|
||||
switch self {
|
||||
case .a(let a):
|
||||
try container.encode(a)
|
||||
case .b(let b):
|
||||
try container.encode(b)
|
||||
case .c(let c):
|
||||
try container.encode(c)
|
||||
case .d(let d):
|
||||
try container.encode(d)
|
||||
case .e(let e):
|
||||
try container.encode(e)
|
||||
case .f(let f):
|
||||
try container.encode(f)
|
||||
case .g(let g):
|
||||
try container.encode(g)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Poly7: CustomStringConvertible {
|
||||
public var description: String {
|
||||
let str: String
|
||||
switch self {
|
||||
case .a(let a):
|
||||
str = String(describing: a)
|
||||
case .b(let b):
|
||||
str = String(describing: b)
|
||||
case .c(let c):
|
||||
str = String(describing: c)
|
||||
case .d(let d):
|
||||
str = String(describing: d)
|
||||
case .e(let e):
|
||||
str = String(describing: e)
|
||||
case .f(let f):
|
||||
str = String(describing: f)
|
||||
case .g(let g):
|
||||
str = String(describing: g)
|
||||
}
|
||||
|
||||
return "Poly(\(str))"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,24 @@ class IncludedTests: XCTestCase {
|
||||
test_DecodeEncodeEquality(type: Includes<Include6<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity5, TestEntity6>>.self,
|
||||
data: six_different_type_includes)
|
||||
}
|
||||
|
||||
func test_SevenDifferentIncludes() {
|
||||
let includes = decoded(type: Includes<Include7<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity5, TestEntity6, TestEntity7>>.self,
|
||||
data: seven_different_type_includes)
|
||||
|
||||
XCTAssertEqual(includes[TestEntity.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity2.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity3.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity4.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity5.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity6.self].count, 1)
|
||||
XCTAssertEqual(includes[TestEntity7.self].count, 1)
|
||||
}
|
||||
|
||||
func test_SevenDifferentIncludes_encode() {
|
||||
test_DecodeEncodeEquality(type: Includes<Include7<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity5, TestEntity6, TestEntity7>>.self,
|
||||
data: seven_different_type_includes)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Test types
|
||||
@@ -203,4 +221,15 @@ extension IncludedTests {
|
||||
}
|
||||
|
||||
typealias TestEntity6 = BasicEntity<TestEntityType6>
|
||||
|
||||
enum TestEntityType7: EntityDescription {
|
||||
|
||||
typealias Attributes = NoAttributes
|
||||
|
||||
public static var type: String { return "test_entity7" }
|
||||
|
||||
typealias Relationships = NoRelationships
|
||||
}
|
||||
|
||||
typealias TestEntity7 = BasicEntity<TestEntityType7>
|
||||
}
|
||||
|
||||
@@ -281,3 +281,76 @@ let six_different_type_includes = """
|
||||
}
|
||||
]
|
||||
""".data(using: .utf8)!
|
||||
|
||||
let seven_different_type_includes = """
|
||||
[
|
||||
{
|
||||
"type": "test_entity1",
|
||||
"id": "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF",
|
||||
"attributes": {
|
||||
"foo": "Hello",
|
||||
"bar": 123
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "test_entity2",
|
||||
"id": "90F03B69-4DF1-467F-B52E-B0C9E44FC333",
|
||||
"attributes": {
|
||||
"foo": "World",
|
||||
"bar": 456
|
||||
},
|
||||
"relationships": {
|
||||
"entity1": {
|
||||
"data": {
|
||||
"type": "test_entity1",
|
||||
"id": "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "test_entity3",
|
||||
"id": "11223B69-4DF1-467F-B52E-B0C9E44FC443",
|
||||
"relationships": {
|
||||
"entity1": {
|
||||
"data": {
|
||||
"type": "test_entity1",
|
||||
"id": "2DF03B69-4B0A-467F-B52E-B0C9E44FCECF"
|
||||
}
|
||||
},
|
||||
"entity2": {
|
||||
"data": [
|
||||
{
|
||||
"type": "test_entity2",
|
||||
"id": "90F03B69-4DF1-467F-B52E-B0C9E44FC333"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "test_entity6",
|
||||
"id": "11113B69-4DF1-467F-B52E-B0C9E44FC444",
|
||||
"relationships": {
|
||||
"entity4": {
|
||||
"data": {
|
||||
"type": "test_entity4",
|
||||
"id": "364B3B69-4DF1-467F-B52E-B0C9E44F666E"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "test_entity5",
|
||||
"id": "A24B3B69-4DF1-467F-B52E-B0C9E44F436A"
|
||||
},
|
||||
{
|
||||
"type": "test_entity4",
|
||||
"id": "364B3B69-4DF1-467F-B52E-B0C9E44F666E"
|
||||
},
|
||||
{
|
||||
"type": "test_entity7",
|
||||
"id": "364B3B69-4DF1-222F-B52E-B0C9E44F666E"
|
||||
}
|
||||
]
|
||||
""".data(using: .utf8)!
|
||||
|
||||
@@ -164,6 +164,72 @@ class PolyTests: XCTestCase {
|
||||
XCTAssertNil(poly6.d)
|
||||
XCTAssertNil(poly6.e)
|
||||
}
|
||||
|
||||
func test_init_Poly7() {
|
||||
let entity = TestEntity5()
|
||||
let poly = Poly7<TestEntity5, TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity6, TestEntity7>(entity)
|
||||
XCTAssertEqual(poly.a, entity)
|
||||
XCTAssertNil(poly.b)
|
||||
XCTAssertNil(poly.c)
|
||||
XCTAssertNil(poly.d)
|
||||
XCTAssertNil(poly.e)
|
||||
XCTAssertNil(poly.f)
|
||||
XCTAssertNil(poly.g)
|
||||
|
||||
let poly2 = Poly7<TestEntity, TestEntity5, TestEntity2, TestEntity3, TestEntity4, TestEntity6, TestEntity7>(entity)
|
||||
XCTAssertEqual(poly2.b, entity)
|
||||
XCTAssertNil(poly2.a)
|
||||
XCTAssertNil(poly2.c)
|
||||
XCTAssertNil(poly2.d)
|
||||
XCTAssertNil(poly2.e)
|
||||
XCTAssertNil(poly2.f)
|
||||
XCTAssertNil(poly2.g)
|
||||
|
||||
let poly3 = Poly7<TestEntity, TestEntity2, TestEntity5, TestEntity3, TestEntity4, TestEntity6, TestEntity7>(entity)
|
||||
XCTAssertEqual(poly3.c, entity)
|
||||
XCTAssertNil(poly3.a)
|
||||
XCTAssertNil(poly3.b)
|
||||
XCTAssertNil(poly3.d)
|
||||
XCTAssertNil(poly3.e)
|
||||
XCTAssertNil(poly3.f)
|
||||
XCTAssertNil(poly3.g)
|
||||
|
||||
let poly4 = Poly7<TestEntity, TestEntity2, TestEntity3, TestEntity5, TestEntity4, TestEntity6, TestEntity7>(entity)
|
||||
XCTAssertEqual(poly4.d, entity)
|
||||
XCTAssertNil(poly4.a)
|
||||
XCTAssertNil(poly4.b)
|
||||
XCTAssertNil(poly4.c)
|
||||
XCTAssertNil(poly4.e)
|
||||
XCTAssertNil(poly4.f)
|
||||
XCTAssertNil(poly4.g)
|
||||
|
||||
let poly5 = Poly7<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity5, TestEntity6, TestEntity7>(entity)
|
||||
XCTAssertEqual(poly5.e, entity)
|
||||
XCTAssertNil(poly5.a)
|
||||
XCTAssertNil(poly5.b)
|
||||
XCTAssertNil(poly5.c)
|
||||
XCTAssertNil(poly5.d)
|
||||
XCTAssertNil(poly5.f)
|
||||
XCTAssertNil(poly5.g)
|
||||
|
||||
let poly6 = Poly7<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity6, TestEntity5, TestEntity7>(entity)
|
||||
XCTAssertEqual(poly6.f, entity)
|
||||
XCTAssertNil(poly6.a)
|
||||
XCTAssertNil(poly6.b)
|
||||
XCTAssertNil(poly6.c)
|
||||
XCTAssertNil(poly6.d)
|
||||
XCTAssertNil(poly6.e)
|
||||
XCTAssertNil(poly6.g)
|
||||
|
||||
let poly7 = Poly7<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity6, TestEntity7, TestEntity5>(entity)
|
||||
XCTAssertEqual(poly7.g, entity)
|
||||
XCTAssertNil(poly7.a)
|
||||
XCTAssertNil(poly7.b)
|
||||
XCTAssertNil(poly7.c)
|
||||
XCTAssertNil(poly7.d)
|
||||
XCTAssertNil(poly7.e)
|
||||
XCTAssertNil(poly7.f)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - subscript lookup
|
||||
@@ -224,6 +290,19 @@ extension PolyTests {
|
||||
XCTAssertNil(poly[TestEntity5.self])
|
||||
XCTAssertEqual(entity, poly[TestEntity6.self])
|
||||
}
|
||||
|
||||
func test_Poly7_lookup() {
|
||||
let entity = decoded(type: TestEntity7.self, data: poly_entity7)
|
||||
let poly = decoded(type: Poly7<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity5, TestEntity6, TestEntity7>.self, data: poly_entity7)
|
||||
|
||||
XCTAssertNil(poly[TestEntity.self])
|
||||
XCTAssertNil(poly[TestEntity2.self])
|
||||
XCTAssertNil(poly[TestEntity3.self])
|
||||
XCTAssertNil(poly[TestEntity4.self])
|
||||
XCTAssertNil(poly[TestEntity5.self])
|
||||
XCTAssertNil(poly[TestEntity6.self])
|
||||
XCTAssertEqual(entity, poly[TestEntity7.self])
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - failures
|
||||
@@ -259,6 +338,10 @@ extension PolyTests {
|
||||
func test_Poly6_decode_throws_typeNotFound() {
|
||||
XCTAssertThrowsError(try JSONDecoder().decode(Poly6<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity5, TestEntity6>.self, from: poly_entity7))
|
||||
}
|
||||
|
||||
func test_Poly7_decode_throws_typeNotFound() {
|
||||
XCTAssertThrowsError(try JSONDecoder().decode(Poly7<TestEntity, TestEntity2, TestEntity3, TestEntity4, TestEntity5, TestEntity6, TestEntity7>.self, from: poly_entity8))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Test types
|
||||
@@ -341,4 +424,15 @@ extension PolyTests {
|
||||
}
|
||||
|
||||
typealias TestEntity6 = BasicEntity<TestEntityType6>
|
||||
|
||||
enum TestEntityType7: EntityDescription {
|
||||
|
||||
typealias Attributes = NoAttributes
|
||||
|
||||
public static var type: String { return "test_entity7" }
|
||||
|
||||
typealias Relationships = NoRelationships
|
||||
}
|
||||
|
||||
typealias TestEntity7 = BasicEntity<TestEntityType7>
|
||||
}
|
||||
|
||||
@@ -93,3 +93,10 @@ let poly_entity7 = """
|
||||
"id": "A24B3444-4DF1-467F-B52E-B0C9E44F436A"
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
|
||||
let poly_entity8 = """
|
||||
{
|
||||
"type": "test_entity8",
|
||||
"id": "A24B3444-4DF1-467F-B52E-B0C9E44F436A"
|
||||
}
|
||||
""".data(using: .utf8)!
|
||||
|
||||
Reference in New Issue
Block a user