Add Poly7 and Include7 because why not

This commit is contained in:
Mathew Polzin
2018-12-06 18:38:20 -08:00
parent d8d030286d
commit 53f7f55e07
6 changed files with 365 additions and 0 deletions
+7
View File
@@ -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
+155
View File
@@ -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)!
+94
View File
@@ -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)!