From b37436723411cce229e9c8f65dc2bbb8effd4323 Mon Sep 17 00:00:00 2001 From: Mathew Polzin Date: Sat, 12 Jan 2019 21:30:20 -0800 Subject: [PATCH] Move Poly into its own library. --- Package.resolved | 10 +- Package.swift | 3 +- Sources/JSONAPI/Document/Document.swift | 2 + Sources/JSONAPI/Document/Includes.swift | 2 + .../Resource/Poly+PrimaryResource.swift | 55 + Sources/JSONAPI/Resource/Poly.swift | 1220 ----------------- .../JSONAPITests/Document/DocumentTests.swift | 1 + Tests/JSONAPITests/Poly/PolyProxyTests.swift | 1 + Tests/JSONAPITests/Poly/PolyTests.swift | 1 + 9 files changed, 73 insertions(+), 1222 deletions(-) create mode 100644 Sources/JSONAPI/Resource/Poly+PrimaryResource.swift delete mode 100644 Sources/JSONAPI/Resource/Poly.swift diff --git a/Package.resolved b/Package.resolved index 5cefbe8..81285d1 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,7 +1,15 @@ { "object": { "pins": [ - + { + "package": "Poly", + "repositoryURL": "https://github.com/mattpolzin/Poly.git", + "state": { + "branch": "master", + "revision": "92d889c2cdc027bb94814187e84d34783ae159ae", + "version": null + } + } ] }, "version": 1 diff --git a/Package.swift b/Package.swift index 7adbb9b..c51c7eb 100644 --- a/Package.swift +++ b/Package.swift @@ -14,11 +14,12 @@ let package = Package( targets: ["JSONAPITestLib"]) ], dependencies: [ + .package(url: "https://github.com/mattpolzin/Poly.git", .branch("master")) ], targets: [ .target( name: "JSONAPI", - dependencies: []), + dependencies: ["Poly"]), .target( name: "JSONAPITestLib", dependencies: ["JSONAPI"]), diff --git a/Sources/JSONAPI/Document/Document.swift b/Sources/JSONAPI/Document/Document.swift index 09f04f7..1a0fd5f 100644 --- a/Sources/JSONAPI/Document/Document.swift +++ b/Sources/JSONAPI/Document/Document.swift @@ -5,6 +5,8 @@ // Created by Mathew Polzin on 11/5/18. // +import Poly + public protocol JSONAPIDocument: Codable, Equatable { associatedtype PrimaryResourceBody: JSONAPI.ResourceBody associatedtype MetaType: JSONAPI.Meta diff --git a/Sources/JSONAPI/Document/Includes.swift b/Sources/JSONAPI/Document/Includes.swift index 2afb111..8682ee9 100644 --- a/Sources/JSONAPI/Document/Includes.swift +++ b/Sources/JSONAPI/Document/Includes.swift @@ -5,6 +5,8 @@ // Created by Mathew Polzin on 11/10/18. // +import Poly + public typealias Include = JSONPoly public struct Includes: Codable, Equatable { diff --git a/Sources/JSONAPI/Resource/Poly+PrimaryResource.swift b/Sources/JSONAPI/Resource/Poly+PrimaryResource.swift new file mode 100644 index 0000000..2e39a78 --- /dev/null +++ b/Sources/JSONAPI/Resource/Poly+PrimaryResource.swift @@ -0,0 +1,55 @@ +// +// Poly+PrimaryResource.swift +// JSONAPI +// +// Created by Mathew Polzin on 11/22/18. +// + +import Poly + +/// Poly is a protocol to which types that +/// are polymorphic belong to. Specifically, +/// Poly1, Poly2, Poly3, etc. types conform +/// to the Poly protocol. These types allow +/// typesafe grouping of a number of +/// disparate types under one roof for +/// the purposes of JSON API compliant +/// encoding or decoding. +public typealias JSONPoly = Poly & PrimaryResource + +extension Poly0: PrimaryResource { + public init(from decoder: Decoder) throws { + throw JSONAPIEncodingError.illegalDecoding("Attempted to decode Poly0, which should represent a thing that is not expected to be found in a document.") + } + + public func encode(to encoder: Encoder) throws { + throw JSONAPIEncodingError.illegalEncoding("Attempted to encode Poly0, which should represent a thing that is not expected to be found in a document.") + } +} + +// MARK: - 1 type +extension Poly1: PrimaryResource, MaybePrimaryResource where A: Codable & Equatable {} + +// MARK: - 2 types +extension Poly2: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped {} + +// MARK: - 3 types +extension Poly3: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped {} + +// MARK: - 4 types +extension Poly4: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped {} + +// MARK: - 5 types +extension Poly5: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped {} + +// MARK: - 6 types +extension Poly6: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped {} + +// MARK: - 7 types +extension Poly7: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped {} + +// MARK: - 8 types +extension Poly8: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped {} + +// MARK: - 9 types +extension Poly9: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped, I: PolyWrapped {} diff --git a/Sources/JSONAPI/Resource/Poly.swift b/Sources/JSONAPI/Resource/Poly.swift deleted file mode 100644 index e2a905a..0000000 --- a/Sources/JSONAPI/Resource/Poly.swift +++ /dev/null @@ -1,1220 +0,0 @@ -// -// Poly.swift -// JSONAPI -// -// Created by Mathew Polzin on 11/22/18. -// - -public protocol Poly {} - -/// Poly is a protocol to which types that -/// are polymorphic belong to. Specifically, -/// Poly1, Poly2, Poly3, etc. types conform -/// to the Poly protocol. These types allow -/// typesafe grouping of a number of -/// disparate types under one roof for -/// the purposes of JSON API compliant -/// encoding or decoding. -public typealias JSONPoly = Poly & PrimaryResource - -// MARK: - Generic Decoding - -private func decode(_ type: Thing.Type, from container: SingleValueDecodingContainer) throws -> Result { - let ret: Result - do { - ret = try .success(container.decode(Thing.self)) - } catch (let err as DecodingError) { - ret = .failure(err) - } catch (let err) { - ret = .failure(DecodingError.typeMismatch(Thing.self, - .init(codingPath: container.codingPath, - debugDescription: String(describing: err), - underlyingError: err))) - } - return ret -} - -public typealias PolyWrapped = Codable & Equatable - -// MARK: - 0 types -public protocol _Poly0: Poly { } -public struct Poly0: _Poly0 { - - public init() {} -} - -extension Poly0: PrimaryResource { - public init(from decoder: Decoder) throws { - throw JSONAPIEncodingError.illegalDecoding("Attempted to decode Poly0, which should represent a thing that is not expected to be found in a document.") - } - - public func encode(to encoder: Encoder) throws { - throw JSONAPIEncodingError.illegalEncoding("Attempted to encode Poly0, which should represent a thing that is not expected to be found in a document.") - } -} - -// MARK: - 1 type -public protocol _Poly1: _Poly0 { - associatedtype A - var a: A? { get } - - init(_ a: A) -} - -public extension _Poly1 { - subscript(_ lookup: A.Type) -> A? { - return a - } -} - -public enum Poly1: _Poly1 { - case a(A) - - public var a: A? { - guard case let .a(ret) = self else { return nil } - return ret - } - - public init(_ a: A) { - self = .a(a) - } -} - -extension Poly1: Equatable where A: Equatable {} - -extension Poly1: Codable where A: Codable { - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - - self = .a(try container.decode(A.self)) - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - - switch self { - case .a(let a): - try container.encode(a) - } - } -} - -extension Poly1: CustomStringConvertible { - public var description: String { - let str: String - switch self { - case .a(let a): - str = String(describing: a) - } - return "Poly(\(str))" - } -} - -extension Poly1: PrimaryResource, MaybePrimaryResource where A: Codable & Equatable {} - -// MARK: - 2 types -public protocol _Poly2: _Poly1 { - associatedtype B - var b: B? { get } - - init(_ b: B) -} - -public extension _Poly2 { - subscript(_ lookup: B.Type) -> B? { - return b - } -} - -public typealias Either = Poly2 - -public enum Poly2: _Poly2 { - case a(A) - case b(B) - - 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) - } -} - -extension Poly2: Equatable where A: Equatable, B: Equatable {} - -extension Poly2: Codable where A: Codable, B: Codable { - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - - let attempts = [ - try decode(A.self, from: container).map { Poly2.a($0) }, - try decode(B.self, from: container).map { Poly2.b($0) } ] - - let maybeVal: Poly2? = attempts - .compactMap { $0.value } - .first - - guard let val = maybeVal else { - throw EncodingError.invalidValue(Poly2.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) - } - } -} - -extension Poly2: 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) - } - return "Poly(\(str))" - } -} - -extension Poly2: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped {} - -// MARK: - 3 types -public protocol _Poly3: _Poly2 { - associatedtype C - var c: C? { get } - - init(_ c: C) -} - -public extension _Poly3 { - subscript(_ lookup: C.Type) -> C? { - return c - } -} - -public enum Poly3: _Poly3 { - case a(A) - case b(B) - case c(C) - - 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) - } -} - -extension Poly3: Equatable where A: Equatable, B: Equatable, C:Equatable {} - -extension Poly3: Codable where A: Codable, B: Codable, C: Codable { - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - - let attempts = [ - try decode(A.self, from: container).map { Poly3.a($0) }, - try decode(B.self, from: container).map { Poly3.b($0) }, - try decode(C.self, from: container).map { Poly3.c($0) }] - - let maybeVal: Poly3? = attempts - .compactMap { $0.value } - .first - - guard let val = maybeVal else { - throw EncodingError.invalidValue(Poly3.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) - } - } -} - -extension Poly3: 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) - } - return "Poly(\(str))" - } -} - -extension Poly3: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped {} - -// MARK: - 4 types -public protocol _Poly4: _Poly3 { - associatedtype D - var d: D? { get } - - init(_ d: D) -} - -public extension _Poly4 { - subscript(_ lookup: D.Type) -> D? { - return d - } -} - -public enum Poly4: _Poly4 { - case a(A) - case b(B) - case c(C) - case d(D) - - 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) - } -} - -extension Poly4: Equatable where A: Equatable, B: Equatable, C: Equatable, D: Equatable {} - -extension Poly4: Codable where A: Codable, B: Codable, C: Codable, D: Codable { - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - - let attempts = [ - try decode(A.self, from: container).map { Poly4.a($0) }, - try decode(B.self, from: container).map { Poly4.b($0) }, - try decode(C.self, from: container).map { Poly4.c($0) }, - try decode(D.self, from: container).map { Poly4.d($0) }] - - let maybeVal: Poly4? = attempts - .compactMap { $0.value } - .first - - guard let val = maybeVal else { - throw EncodingError.invalidValue(Poly4.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) - } - } -} - -extension Poly4: 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) - } - return "Poly(\(str))" - } -} - -extension Poly4: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped {} - -// MARK: - 5 types -public protocol _Poly5: _Poly4 { - associatedtype E - var e: E? { get } - - init(_ e: E) -} - -public extension _Poly5 { - subscript(_ lookup: E.Type) -> E? { - return e - } -} - -public enum Poly5: _Poly5 { - case a(A) - case b(B) - case c(C) - case d(D) - case e(E) - - 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) - } -} - -extension Poly5: Equatable where A: Equatable, B: Equatable, C: Equatable, D: Equatable, E: Equatable {} - -extension Poly5: Codable where A: Codable, B: Codable, C: Codable, D: Codable, E: Codable { - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - - let attempts = [ - try decode(A.self, from: container).map { Poly5.a($0) }, - try decode(B.self, from: container).map { Poly5.b($0) }, - try decode(C.self, from: container).map { Poly5.c($0) }, - try decode(D.self, from: container).map { Poly5.d($0) }, - try decode(E.self, from: container).map { Poly5.e($0) }] - - let maybeVal: Poly5? = attempts - .compactMap { $0.value } - .first - - guard let val = maybeVal else { - throw EncodingError.invalidValue(Poly5.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) - } - } -} - -extension Poly5: 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) - } - return "Poly(\(str))" - } -} - -extension Poly5: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped {} - -// MARK: - 6 types -public protocol _Poly6: _Poly5 { - associatedtype F - var f: F? { get } - - init(_ f: F) -} - -public extension _Poly6 { - subscript(_ lookup: F.Type) -> F? { - return f - } -} - -public enum Poly6: _Poly6 { - case a(A) - case b(B) - case c(C) - case d(D) - case e(E) - case f(F) - - 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) - } -} - -extension Poly6: Equatable where A: Equatable, B: Equatable, C: Equatable, D: Equatable, E: Equatable, F: Equatable {} - -extension Poly6: Codable where A: Codable, B: Codable, C: Codable, D: Codable, E: Codable, F: Codable { - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - - let attempts = [ - try decode(A.self, from: container).map { Poly6.a($0) }, - try decode(B.self, from: container).map { Poly6.b($0) }, - try decode(C.self, from: container).map { Poly6.c($0) }, - try decode(D.self, from: container).map { Poly6.d($0) }, - try decode(E.self, from: container).map { Poly6.e($0) }, - try decode(F.self, from: container).map { Poly6.f($0) }] - - let maybeVal: Poly6? = attempts - .compactMap { $0.value } - .first - - guard let val = maybeVal else { - throw EncodingError.invalidValue(Poly6.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) - } - } -} - -extension Poly6: 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) - } - return "Poly(\(str))" - } -} - -extension Poly6: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped {} - -// MARK: - 7 types -public protocol _Poly7: _Poly6 { - associatedtype G - var g: G? { get } - - init(_ g: G) -} - -public extension _Poly7 { - subscript(_ lookup: G.Type) -> G? { - return g - } -} - -public enum Poly7: _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) - } -} - -extension Poly7: Equatable where A: Equatable, B: Equatable, C: Equatable, D: Equatable, E: Equatable, F: Equatable, G: Equatable {} - -extension Poly7: Codable where A: Codable, B: Codable, C: Codable, D: Codable, E: Codable, F: Codable, G: Codable { - 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? = attempts - .compactMap { $0.value } - .first - - guard let val = maybeVal else { - throw EncodingError.invalidValue(Poly7.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))" - } -} - -extension Poly7: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped {} - -// MARK: - 8 types -public protocol _Poly8: _Poly7 { - associatedtype H - var h: H? { get } - - init(_ h: H) -} - -public extension _Poly8 { - subscript(_ lookup: H.Type) -> H? { - return h - } -} - -public enum Poly8: _Poly8 { - case a(A) - case b(B) - case c(C) - case d(D) - case e(E) - case f(F) - case g(G) - case h(H) - - 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 var h: H? { - guard case let .h(ret) = self else { return nil } - return ret - } - - public init(_ h: H) { - self = .h(h) - } -} - -extension Poly8: Equatable where A: Equatable, B: Equatable, C: Equatable, D: Equatable, E: Equatable, F: Equatable, G: Equatable, H: Equatable {} - -extension Poly8: Codable where A: Codable, B: Codable, C: Codable, D: Codable, E: Codable, F: Codable, G: Codable, H: Codable { - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - - let attempts = [ - try decode(A.self, from: container).map { Poly8.a($0) }, - try decode(B.self, from: container).map { Poly8.b($0) }, - try decode(C.self, from: container).map { Poly8.c($0) }, - try decode(D.self, from: container).map { Poly8.d($0) }, - try decode(E.self, from: container).map { Poly8.e($0) }, - try decode(F.self, from: container).map { Poly8.f($0) }, - try decode(G.self, from: container).map { Poly8.g($0) }, - try decode(H.self, from: container).map { Poly8.h($0) }] - - let maybeVal: Poly8? = attempts - .compactMap { $0.value } - .first - - guard let val = maybeVal else { - throw EncodingError.invalidValue(Poly8.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) - case .h(let h): - try container.encode(h) - } - } -} - -extension Poly8: 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) - case .h(let h): - str = String(describing: h) - } - - return "Poly(\(str))" - } -} - -extension Poly8: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped {} - -// MARK: - 9 types -public protocol _Poly9: _Poly8 { - associatedtype I - var i: I? { get } - - init(_ i: I) -} - -public extension _Poly9 { - subscript(_ lookup: I.Type) -> I? { - return i - } -} - -public enum Poly9: _Poly9 { - case a(A) - case b(B) - case c(C) - case d(D) - case e(E) - case f(F) - case g(G) - case h(H) - case i(I) - - 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 var h: H? { - guard case let .h(ret) = self else { return nil } - return ret - } - - public init(_ h: H) { - self = .h(h) - } - - public var i: I? { - guard case let .i(ret) = self else { return nil } - return ret - } - - public init(_ i: I) { - self = .i(i) - } -} - -extension Poly9: Equatable where A: Equatable, B: Equatable, C: Equatable, D: Equatable, E: Equatable, F: Equatable, G: Equatable, H: Equatable, I: Equatable {} - -extension Poly9: Codable where A: Codable, B: Codable, C: Codable, D: Codable, E: Codable, F: Codable, G: Codable, H: Codable, I: Codable { - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - - let attempts = [ - try decode(A.self, from: container).map { Poly9.a($0) }, - try decode(B.self, from: container).map { Poly9.b($0) }, - try decode(C.self, from: container).map { Poly9.c($0) }, - try decode(D.self, from: container).map { Poly9.d($0) }, - try decode(E.self, from: container).map { Poly9.e($0) }, - try decode(F.self, from: container).map { Poly9.f($0) }, - try decode(G.self, from: container).map { Poly9.g($0) }, - try decode(H.self, from: container).map { Poly9.h($0) }, - try decode(I.self, from: container).map { Poly9.i($0) }] - - let maybeVal: Poly9? = attempts - .compactMap { $0.value } - .first - - guard let val = maybeVal else { - throw EncodingError.invalidValue(Poly9.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) - case .h(let h): - try container.encode(h) - case .i(let i): - try container.encode(i) - } - } -} - -extension Poly9: 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) - case .h(let h): - str = String(describing: h) - case .i(let i): - str = String(describing: i) - } - - return "Poly(\(str))" - } -} - -extension Poly9: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped, I: PolyWrapped {} diff --git a/Tests/JSONAPITests/Document/DocumentTests.swift b/Tests/JSONAPITests/Document/DocumentTests.swift index cc2ff8d..7107323 100644 --- a/Tests/JSONAPITests/Document/DocumentTests.swift +++ b/Tests/JSONAPITests/Document/DocumentTests.swift @@ -7,6 +7,7 @@ import XCTest import JSONAPI +import Poly class DocumentTests: XCTestCase { diff --git a/Tests/JSONAPITests/Poly/PolyProxyTests.swift b/Tests/JSONAPITests/Poly/PolyProxyTests.swift index 093558e..5c6cd87 100644 --- a/Tests/JSONAPITests/Poly/PolyProxyTests.swift +++ b/Tests/JSONAPITests/Poly/PolyProxyTests.swift @@ -7,6 +7,7 @@ import XCTest import JSONAPI +import Poly public class PolyProxyTests: XCTestCase { func test_generalReasonableness() { diff --git a/Tests/JSONAPITests/Poly/PolyTests.swift b/Tests/JSONAPITests/Poly/PolyTests.swift index 8db6509..b12d860 100644 --- a/Tests/JSONAPITests/Poly/PolyTests.swift +++ b/Tests/JSONAPITests/Poly/PolyTests.swift @@ -7,6 +7,7 @@ import XCTest import JSONAPI +import Poly // MARK: - init class PolyTests: XCTestCase {