diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..c93c7bac --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.swift.gyb linguist-language=Swift diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 948b1095..9530a85f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -114,3 +114,17 @@ jobs: - name: swift test run: swift test + + check-gyb-run: + name: Check GYB has been run + runs-on: macOS-latest + steps: + - uses: actions/checkout@v2 + + - name: Install GYB + run: brew install nshipster/formulae/gyb + + - run: ./scripts/generate-KeyPathCodingKeyCollectionBuilder.sh + + - name: Check GYB was run before commit + run: git diff --exit-code diff --git a/Package.resolved b/Package.resolved index 855c4d23..57981c6d 100644 --- a/Package.resolved +++ b/Package.resolved @@ -87,8 +87,8 @@ "repositoryURL": "https://github.com/Realm/SwiftLint", "state": { "branch": null, - "revision": "4f8b7a5f480aad922beab9b3c674023e211bd177", - "version": "0.40.3" + "revision": "d53fc2664df92ef322bfa9ce5238d34f1461526a", + "version": "0.42.0" } }, { @@ -105,8 +105,8 @@ "repositoryURL": "https://github.com/drmohundro/SWXMLHash.git", "state": { "branch": null, - "revision": "a4931e5c3bafbedeb1601d3bb76bbe835c6d475a", - "version": "5.0.1" + "revision": "9183170d20857753d4f331b0ca63f73c60764bf3", + "version": "5.0.2" } }, { @@ -123,8 +123,8 @@ "repositoryURL": "https://github.com/jpsim/Yams.git", "state": { "branch": null, - "revision": "88caa2e6fffdbef2e91c2022d038576062042907", - "version": "4.0.0" + "revision": "9003d51672e516cc59297b7e96bff1dfdedcb4ea", + "version": "4.0.4" } } ] diff --git a/Package.swift b/Package.swift index ab02f335..594e89de 100644 --- a/Package.swift +++ b/Package.swift @@ -14,8 +14,15 @@ let package = Package( .package(url: "https://github.com/Quick/Nimble.git", from: "8.0.0"), ], targets: [ - .target(name: "Partial"), - .testTarget(name: "PartialTests", dependencies: ["Partial", "Quick", "Nimble"]), + .target(name: "Partial", exclude: ["Codable/KeyPathCodingKeyCollectionBuilder.swift.gyb"]), + .testTarget( + name: "PartialTests", + dependencies: ["Partial", "Quick", "Nimble"], + exclude: [ + "Tests/Partial+CodableTests.swift.gyb", + "Tests/PartialBuilder+CodableTests.swift.gyb", + ] + ), ], swiftLanguageVersions: [.v5] ) diff --git a/Package@swift-5.2.swift b/Package@swift-5.2.swift index 4613bcad..3e8a57c6 100644 --- a/Package@swift-5.2.swift +++ b/Package@swift-5.2.swift @@ -14,8 +14,15 @@ let package = Package( .package(url: "https://github.com/Quick/Nimble.git", from: "8.0.0"), ], targets: [ - .target(name: "Partial"), - .testTarget(name: "PartialTests", dependencies: ["Partial", "Quick", "Nimble"]), + .target(name: "Partial", exclude: ["Codable/KeyPathCodingKeyCollectionBuilder.swift.gyb"]), + .testTarget( + name: "PartialTests", + dependencies: ["Partial", "Quick", "Nimble"], + exclude: [ + "Tests/Partial+CodableTests.swift.gyb", + "Tests/PartialBuilder+CodableTests.swift.gyb", + ] + ), ], swiftLanguageVersions: [.v5] ) diff --git a/Package@swift-5.3.swift b/Package@swift-5.3.swift index af2e7ccf..1dd41717 100644 --- a/Package@swift-5.3.swift +++ b/Package@swift-5.3.swift @@ -18,8 +18,15 @@ let package = Package( .package(url: "https://github.com/Realm/SwiftLint", from: "0.32.0"), ], targets: [ - .target(name: "Partial"), - .testTarget(name: "PartialTests", dependencies: ["Partial", "Quick", "Nimble"]), + .target(name: "Partial", exclude: ["Codable/KeyPathCodingKeyCollectionBuilder.swift.gyb"]), + .testTarget( + name: "PartialTests", + dependencies: ["Partial", "Quick", "Nimble"], + exclude: [ + "Tests/Partial+CodableTests.swift.gyb", + "Tests/PartialBuilder+CodableTests.swift.gyb", + ] + ), .target( name: "DangerDependencies", dependencies: [ diff --git a/Partial.podspec b/Partial.podspec index b8824bd5..6d7b6c93 100644 --- a/Partial.podspec +++ b/Partial.podspec @@ -10,7 +10,7 @@ Pod::Spec.new do |spec| :git => "https://github.com/JosephDuffy/Partial.git", :tag => "v#{spec.version}" } - spec.source_files = "Sources/Partial/*.swift" + spec.source_files = "Sources/Partial/**/*.swift" spec.osx.deployment_target = "10.10" spec.ios.deployment_target = "8.0" spec.tvos.deployment_target = "9.0" diff --git a/Partial.xcodeproj/project.pbxproj b/Partial.xcodeproj/project.pbxproj index 9e1c36ea..a6c0e303 100644 --- a/Partial.xcodeproj/project.pbxproj +++ b/Partial.xcodeproj/project.pbxproj @@ -15,6 +15,12 @@ D92E76D1229D8A66003EBC25 /* PartialProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92E76CF229D8A0D003EBC25 /* PartialProtocol.swift */; }; D92E76D2229D8A67003EBC25 /* PartialProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92E76CF229D8A0D003EBC25 /* PartialProtocol.swift */; }; D92E76D3229D8A67003EBC25 /* PartialProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92E76CF229D8A0D003EBC25 /* PartialProtocol.swift */; }; + D92F168525D8A49E003E2D1C /* Partial+CodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92F168425D8A49E003E2D1C /* Partial+CodableTests.swift */; }; + D92F168625D8A49E003E2D1C /* Partial+CodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92F168425D8A49E003E2D1C /* Partial+CodableTests.swift */; }; + D92F168725D8A49E003E2D1C /* Partial+CodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92F168425D8A49E003E2D1C /* Partial+CodableTests.swift */; }; + D92F168925D8A4A9003E2D1C /* PartialBuilder+CodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92F168825D8A4A9003E2D1C /* PartialBuilder+CodableTests.swift */; }; + D92F168A25D8A4A9003E2D1C /* PartialBuilder+CodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92F168825D8A4A9003E2D1C /* PartialBuilder+CodableTests.swift */; }; + D92F168B25D8A4A9003E2D1C /* PartialBuilder+CodableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D92F168825D8A4A9003E2D1C /* PartialBuilder+CodableTests.swift */; }; D9651AC022D24673008DBB0E /* StringWrapperWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9651ABF22D24673008DBB0E /* StringWrapperWrapper.swift */; }; D9651AC122D24673008DBB0E /* StringWrapperWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9651ABF22D24673008DBB0E /* StringWrapperWrapper.swift */; }; D9651AC222D24673008DBB0E /* StringWrapperWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9651ABF22D24673008DBB0E /* StringWrapperWrapper.swift */; }; @@ -40,16 +46,28 @@ D9A27B6E228CBDD2001530A1 /* PartialConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A27B6C228CBDC5001530A1 /* PartialConvertible.swift */; }; D9A27B6F228CBDD3001530A1 /* PartialConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A27B6C228CBDC5001530A1 /* PartialConvertible.swift */; }; D9A27B70228CBDD4001530A1 /* PartialConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A27B6C228CBDC5001530A1 /* PartialConvertible.swift */; }; - D9A5673325D86BE600F7055F /* PartiallyBuilt.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A5673225D86BE600F7055F /* PartiallyBuilt.swift */; }; - D9A5673425D86BE600F7055F /* PartiallyBuilt.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A5673225D86BE600F7055F /* PartiallyBuilt.swift */; }; - D9A5673525D86BE600F7055F /* PartiallyBuilt.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A5673225D86BE600F7055F /* PartiallyBuilt.swift */; }; - D9A5673625D86BE600F7055F /* PartiallyBuilt.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A5673225D86BE600F7055F /* PartiallyBuilt.swift */; }; + D9A4E47425D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A4E47025D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift */; }; + D9A4E47525D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A4E47025D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift */; }; + D9A4E47625D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A4E47025D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift */; }; + D9A4E47725D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A4E47025D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift */; }; + D9A4E47C25D85C8E00F3E6D9 /* PartialCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A4E47225D85C8E00F3E6D9 /* PartialCodable.swift */; }; + D9A4E47D25D85C8E00F3E6D9 /* PartialCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A4E47225D85C8E00F3E6D9 /* PartialCodable.swift */; }; + D9A4E47E25D85C8E00F3E6D9 /* PartialCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A4E47225D85C8E00F3E6D9 /* PartialCodable.swift */; }; + D9A4E47F25D85C8E00F3E6D9 /* PartialCodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A4E47225D85C8E00F3E6D9 /* PartialCodable.swift */; }; + D9A4E48025D85C8E00F3E6D9 /* KeyPathCodingKeyCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A4E47325D85C8E00F3E6D9 /* KeyPathCodingKeyCollection.swift */; }; + D9A4E48125D85C8E00F3E6D9 /* KeyPathCodingKeyCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A4E47325D85C8E00F3E6D9 /* KeyPathCodingKeyCollection.swift */; }; + D9A4E48225D85C8E00F3E6D9 /* KeyPathCodingKeyCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A4E47325D85C8E00F3E6D9 /* KeyPathCodingKeyCollection.swift */; }; + D9A4E48325D85C8E00F3E6D9 /* KeyPathCodingKeyCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A4E47325D85C8E00F3E6D9 /* KeyPathCodingKeyCollection.swift */; }; D9A5673825D86C1F00F7055F /* PartialBuilderSubscriptionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A5673725D86C1F00F7055F /* PartialBuilderSubscriptionTests.swift */; }; D9A5673925D86C1F00F7055F /* PartialBuilderSubscriptionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A5673725D86C1F00F7055F /* PartialBuilderSubscriptionTests.swift */; }; D9A5673A25D86C1F00F7055F /* PartialBuilderSubscriptionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A5673725D86C1F00F7055F /* PartialBuilderSubscriptionTests.swift */; }; D9A5673C25D86C5400F7055F /* PartiallyBuiltTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A5673B25D86C5400F7055F /* PartiallyBuiltTests.swift */; }; D9A5673D25D86C5400F7055F /* PartiallyBuiltTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A5673B25D86C5400F7055F /* PartiallyBuiltTests.swift */; }; D9A5673E25D86C5400F7055F /* PartiallyBuiltTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A5673B25D86C5400F7055F /* PartiallyBuiltTests.swift */; }; + D9A5674F25D8998100F7055F /* PartiallyBuilt.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A5673225D86BE600F7055F /* PartiallyBuilt.swift */; }; + D9A5675025D8998200F7055F /* PartiallyBuilt.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A5673225D86BE600F7055F /* PartiallyBuilt.swift */; }; + D9A5675125D8998200F7055F /* PartiallyBuilt.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A5673225D86BE600F7055F /* PartiallyBuilt.swift */; }; + D9A5675225D8998300F7055F /* PartiallyBuilt.swift in Sources */ = {isa = PBXBuildFile; fileRef = D9A5673225D86BE600F7055F /* PartiallyBuilt.swift */; }; D9C039B1224263610031B393 /* Nimble.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9C039AF224263610031B393 /* Nimble.framework */; }; D9C039B4224263610031B393 /* Quick.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9C039B0224263610031B393 /* Quick.framework */; }; D9E601CF2233E99D00B36B1E /* Partial.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9E601C62233E99D00B36B1E /* Partial.framework */; }; @@ -98,6 +116,7 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + D909A5FA25C200850020D21B /* PartiallyBuilt.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PartiallyBuilt.swift; sourceTree = ""; }; D91505AF221E024900EB5215 /* Partial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Partial.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D91505B2221E024900EB5215 /* Partial.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Partial.h; sourceTree = ""; }; D91505B3221E024900EB5215 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -106,6 +125,9 @@ D91505C9221E04EB00EB5215 /* Partial.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Partial.swift; sourceTree = ""; }; D91505CD221E052600EB5215 /* PartialBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PartialBuilder.swift; sourceTree = ""; }; D92E76CF229D8A0D003EBC25 /* PartialProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PartialProtocol.swift; sourceTree = ""; }; + D92F168325D8A403003E2D1C /* PartialBuilder+CodableTests.swift.gyb */ = {isa = PBXFileReference; lastKnownFileType = text; path = "PartialBuilder+CodableTests.swift.gyb"; sourceTree = ""; }; + D92F168425D8A49E003E2D1C /* Partial+CodableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Partial+CodableTests.swift"; sourceTree = ""; }; + D92F168825D8A4A9003E2D1C /* PartialBuilder+CodableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "PartialBuilder+CodableTests.swift"; sourceTree = ""; }; D9651ABD22D24606008DBB0E /* StringWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringWrapper.swift; sourceTree = ""; }; D9651ABF22D24673008DBB0E /* StringWrapperWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringWrapperWrapper.swift; sourceTree = ""; }; D9651AC622D26A53008DBB0E /* PartialTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PartialTests.swift; sourceTree = ""; }; @@ -114,11 +136,17 @@ D9651AD422D28374008DBB0E /* PartialBuilder+PartialConvertibleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PartialBuilder+PartialConvertibleTests.swift"; sourceTree = ""; }; D992471422C15D1800A2B079 /* beNilWrappedInOptional.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = beNilWrappedInOptional.swift; sourceTree = ""; }; D9A27B6C228CBDC5001530A1 /* PartialConvertible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PartialConvertible.swift; sourceTree = ""; }; + D9A4E47025D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyPathCodingKeyCollectionBuilder.swift; sourceTree = ""; }; + D9A4E47125D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift.gyb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = KeyPathCodingKeyCollectionBuilder.swift.gyb; sourceTree = ""; }; + D9A4E47225D85C8E00F3E6D9 /* PartialCodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PartialCodable.swift; sourceTree = ""; }; + D9A4E47325D85C8E00F3E6D9 /* KeyPathCodingKeyCollection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyPathCodingKeyCollection.swift; sourceTree = ""; }; + D9A4E48425D85CC700F3E6D9 /* Partial+CodableTests.swift.gyb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "Partial+CodableTests.swift.gyb"; sourceTree = ""; }; D9A5673225D86BE600F7055F /* PartiallyBuilt.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PartiallyBuilt.swift; sourceTree = ""; }; D9A5673725D86C1F00F7055F /* PartialBuilderSubscriptionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PartialBuilderSubscriptionTests.swift; sourceTree = ""; }; D9A5673B25D86C5400F7055F /* PartiallyBuiltTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PartiallyBuiltTests.swift; sourceTree = ""; }; D9C039AF224263610031B393 /* Nimble.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Nimble.framework; path = Carthage/Build/iOS/Nimble.framework; sourceTree = SOURCE_ROOT; }; D9C039B0224263610031B393 /* Quick.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quick.framework; path = Carthage/Build/iOS/Quick.framework; sourceTree = SOURCE_ROOT; }; + D9C0663525C1A97400BD0509 /* PartiallyBuiltTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PartiallyBuiltTests.swift; sourceTree = ""; }; D9CA4437222FF3CD000E424B /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = SOURCE_ROOT; }; D9D933B4223492FD00E94AAE /* Partial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Partial.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D9E601C62233E99D00B36B1E /* Partial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Partial.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -194,6 +222,7 @@ D91505BC221E024900EB5215 /* Tests */, D9CA4436222FF3B5000E424B /* Resources */, D91505B0221E024900EB5215 /* Products */, + D9A5674E25D8996A00F7055F /* Recovered References */, ); sourceTree = ""; }; @@ -234,6 +263,7 @@ D930CF9322B0058A00121F2B /* Partial */ = { isa = PBXGroup; children = ( + D9A4E46F25D85C8E00F3E6D9 /* Codable */, D91505C9221E04EB00EB5215 /* Partial.swift */, D91505CD221E052600EB5215 /* PartialBuilder.swift */, D9A27B6C228CBDC5001530A1 /* PartialConvertible.swift */, @@ -267,7 +297,11 @@ D9651ACF22D278FC008DBB0E /* Tests */ = { isa = PBXGroup; children = ( + D92F168425D8A49E003E2D1C /* Partial+CodableTests.swift */, + D9A4E48425D85CC700F3E6D9 /* Partial+CodableTests.swift.gyb */, D9651AD022D27BE7008DBB0E /* Partial+PartialConvertibleTests.swift */, + D92F168825D8A4A9003E2D1C /* PartialBuilder+CodableTests.swift */, + D92F168325D8A403003E2D1C /* PartialBuilder+CodableTests.swift.gyb */, D9651AD422D28374008DBB0E /* PartialBuilder+PartialConvertibleTests.swift */, D9A5673725D86C1F00F7055F /* PartialBuilderSubscriptionTests.swift */, D9651ACA22D26EFB008DBB0E /* PartialBuilderTests.swift */, @@ -285,6 +319,26 @@ path = Matchers; sourceTree = ""; }; + D9A4E46F25D85C8E00F3E6D9 /* Codable */ = { + isa = PBXGroup; + children = ( + D9A4E47025D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift */, + D9A4E47125D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift.gyb */, + D9A4E47225D85C8E00F3E6D9 /* PartialCodable.swift */, + D9A4E47325D85C8E00F3E6D9 /* KeyPathCodingKeyCollection.swift */, + ); + path = Codable; + sourceTree = ""; + }; + D9A5674E25D8996A00F7055F /* Recovered References */ = { + isa = PBXGroup; + children = ( + D909A5FA25C200850020D21B /* PartiallyBuilt.swift */, + D9C0663525C1A97400BD0509 /* PartiallyBuiltTests.swift */, + ); + name = "Recovered References"; + sourceTree = ""; + }; D9C039AE224263140031B393 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -582,11 +636,14 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D9A4E48025D85C8E00F3E6D9 /* KeyPathCodingKeyCollection.swift in Sources */, + D9A4E47425D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift in Sources */, D9F58EE622CA730B00931D29 /* Subscription.swift in Sources */, + D9A5674F25D8998100F7055F /* PartiallyBuilt.swift in Sources */, D91505CA221E04EB00EB5215 /* Partial.swift in Sources */, D9A27B6D228CBDC5001530A1 /* PartialConvertible.swift in Sources */, D91505CE221E052600EB5215 /* PartialBuilder.swift in Sources */, - D9A5673325D86BE600F7055F /* PartiallyBuilt.swift in Sources */, + D9A4E47C25D85C8E00F3E6D9 /* PartialCodable.swift in Sources */, D9F58EE222CA730B00931D29 /* Weak.swift in Sources */, D92E76D0229D8A0D003EBC25 /* PartialProtocol.swift in Sources */, ); @@ -602,6 +659,8 @@ D9651ACB22D2788C008DBB0E /* PartialBuilderTests.swift in Sources */, D9651AC322D24678008DBB0E /* StringWrapper.swift in Sources */, D992471922C15D6300A2B079 /* beNilWrappedInOptional.swift in Sources */, + D92F168525D8A49E003E2D1C /* Partial+CodableTests.swift in Sources */, + D92F168925D8A4A9003E2D1C /* PartialBuilder+CodableTests.swift in Sources */, D9651AD122D27BE7008DBB0E /* Partial+PartialConvertibleTests.swift in Sources */, D9651AD522D28374008DBB0E /* PartialBuilder+PartialConvertibleTests.swift in Sources */, D9651AC722D26A53008DBB0E /* PartialTests.swift in Sources */, @@ -612,11 +671,14 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D9A4E48225D85C8E00F3E6D9 /* KeyPathCodingKeyCollection.swift in Sources */, + D9A4E47625D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift in Sources */, D9F58EE822CA730B00931D29 /* Subscription.swift in Sources */, + D9A5675125D8998200F7055F /* PartiallyBuilt.swift in Sources */, D9FFA6382235A407005D9A4D /* Partial.swift in Sources */, D9A27B6F228CBDD3001530A1 /* PartialConvertible.swift in Sources */, D9FFA63A2235A407005D9A4D /* PartialBuilder.swift in Sources */, - D9A5673525D86BE600F7055F /* PartiallyBuilt.swift in Sources */, + D9A4E47E25D85C8E00F3E6D9 /* PartialCodable.swift in Sources */, D9F58EE422CA730B00931D29 /* Weak.swift in Sources */, D92E76D2229D8A67003EBC25 /* PartialProtocol.swift in Sources */, ); @@ -626,11 +688,14 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D9A4E48125D85C8E00F3E6D9 /* KeyPathCodingKeyCollection.swift in Sources */, + D9A4E47525D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift in Sources */, D9F58EE722CA730B00931D29 /* Subscription.swift in Sources */, + D9A5675025D8998200F7055F /* PartiallyBuilt.swift in Sources */, D9E601DE2233EBED00B36B1E /* Partial.swift in Sources */, D9A27B6E228CBDD2001530A1 /* PartialConvertible.swift in Sources */, D9E601E02233EBED00B36B1E /* PartialBuilder.swift in Sources */, - D9A5673425D86BE600F7055F /* PartiallyBuilt.swift in Sources */, + D9A4E47D25D85C8E00F3E6D9 /* PartialCodable.swift in Sources */, D9F58EE322CA730B00931D29 /* Weak.swift in Sources */, D92E76D1229D8A66003EBC25 /* PartialProtocol.swift in Sources */, ); @@ -646,6 +711,8 @@ D9651ACC22D2788D008DBB0E /* PartialBuilderTests.swift in Sources */, D9651AC422D24678008DBB0E /* StringWrapper.swift in Sources */, D992471A22C15D6500A2B079 /* beNilWrappedInOptional.swift in Sources */, + D92F168625D8A49E003E2D1C /* Partial+CodableTests.swift in Sources */, + D92F168A25D8A4A9003E2D1C /* PartialBuilder+CodableTests.swift in Sources */, D9651AD222D27BE7008DBB0E /* Partial+PartialConvertibleTests.swift in Sources */, D9651AD622D28374008DBB0E /* PartialBuilder+PartialConvertibleTests.swift in Sources */, D9651AC822D26A53008DBB0E /* PartialTests.swift in Sources */, @@ -656,11 +723,14 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D9A4E48325D85C8E00F3E6D9 /* KeyPathCodingKeyCollection.swift in Sources */, + D9A4E47725D85C8E00F3E6D9 /* KeyPathCodingKeyCollectionBuilder.swift in Sources */, D9F58EE922CA730B00931D29 /* Subscription.swift in Sources */, + D9A5675225D8998300F7055F /* PartiallyBuilt.swift in Sources */, D9FFA63B2235A408005D9A4D /* Partial.swift in Sources */, D9A27B70228CBDD4001530A1 /* PartialConvertible.swift in Sources */, D9FFA63D2235A408005D9A4D /* PartialBuilder.swift in Sources */, - D9A5673625D86BE600F7055F /* PartiallyBuilt.swift in Sources */, + D9A4E47F25D85C8E00F3E6D9 /* PartialCodable.swift in Sources */, D9F58EE522CA730B00931D29 /* Weak.swift in Sources */, D92E76D3229D8A67003EBC25 /* PartialProtocol.swift in Sources */, ); @@ -676,6 +746,8 @@ D9651ACD22D2788E008DBB0E /* PartialBuilderTests.swift in Sources */, D9651AC522D24679008DBB0E /* StringWrapper.swift in Sources */, D992471B22C15D6900A2B079 /* beNilWrappedInOptional.swift in Sources */, + D92F168725D8A49E003E2D1C /* Partial+CodableTests.swift in Sources */, + D92F168B25D8A4A9003E2D1C /* PartialBuilder+CodableTests.swift in Sources */, D9651AD322D27BE7008DBB0E /* Partial+PartialConvertibleTests.swift in Sources */, D9651AD722D28374008DBB0E /* PartialBuilder+PartialConvertibleTests.swift in Sources */, D9651AC922D26A53008DBB0E /* PartialTests.swift in Sources */, diff --git a/Sources/Partial/Codable/KeyPathCodingKeyCollection.swift b/Sources/Partial/Codable/KeyPathCodingKeyCollection.swift new file mode 100644 index 00000000..e49c6360 --- /dev/null +++ b/Sources/Partial/Codable/KeyPathCodingKeyCollection.swift @@ -0,0 +1,37 @@ +public struct KeyPathCodingKeyCollection { + public enum EncodeError: Error { + case invalidType(value: Any, expectedType: Any.Type) + } + + private typealias Encoder = (_ value: Any, _ container: inout KeyedEncodingContainer) throws -> Void + private typealias Decoder = (_ codingKey: CodingKey, _ container: KeyedDecodingContainer) throws -> (Any, PartialKeyPath)? + + private var encoders: [PartialKeyPath: Encoder] = [:] + private var decoders: [CodingKey: Decoder] = [:] + + func encode(_ value: Any, forKey keyPath: PartialKeyPath, to container: inout KeyedEncodingContainer) throws { + try encoders[keyPath]?(value, &container) + } + + func decode(_ codingKey: CodingKey, in container: KeyedDecodingContainer) throws -> (Any, PartialKeyPath)? { + return try decoders[codingKey]?(codingKey, container) + } + + public mutating func addPair(keyPath: KeyPath, codingKey: CodingKey) { + encoders[keyPath] = { value, container in + guard let caseValue = value as? Value else { + throw EncodeError.invalidType(value: value, expectedType: Value.self) + } + + try container.encode(caseValue, forKey: codingKey) + } + + decoders[codingKey] = { codingKey, container in + if let decodedValue = try container.decodeIfPresent(Value.self, forKey: codingKey) { + return (decodedValue, keyPath) + } else { + return nil + } + } + } +} diff --git a/Sources/Partial/Codable/KeyPathCodingKeyCollectionBuilder.swift b/Sources/Partial/Codable/KeyPathCodingKeyCollectionBuilder.swift new file mode 100644 index 00000000..79e58a76 --- /dev/null +++ b/Sources/Partial/Codable/KeyPathCodingKeyCollectionBuilder.swift @@ -0,0 +1,1049 @@ +// This file is generated. Do not edit it. +// swiftlint:disable function_parameter_count file_length type_body_length +#if swift(>=5.4) +@resultBuilder +public final class KeyPathCodingKeyCollectionBuilder { + static func buildBlock< + ValueA: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable, + ValueJ: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey), + _ pairJ: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + collection.addPair(keyPath: pairJ.keyPath, codingKey: pairJ.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable, + ValueJ: Codable, + ValueK: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey), + _ pairJ: (keyPath: KeyPath, codingKey: CodingKey), + _ pairK: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + collection.addPair(keyPath: pairJ.keyPath, codingKey: pairJ.codingKey) + collection.addPair(keyPath: pairK.keyPath, codingKey: pairK.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable, + ValueJ: Codable, + ValueK: Codable, + ValueL: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey), + _ pairJ: (keyPath: KeyPath, codingKey: CodingKey), + _ pairK: (keyPath: KeyPath, codingKey: CodingKey), + _ pairL: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + collection.addPair(keyPath: pairJ.keyPath, codingKey: pairJ.codingKey) + collection.addPair(keyPath: pairK.keyPath, codingKey: pairK.codingKey) + collection.addPair(keyPath: pairL.keyPath, codingKey: pairL.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable, + ValueJ: Codable, + ValueK: Codable, + ValueL: Codable, + ValueM: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey), + _ pairJ: (keyPath: KeyPath, codingKey: CodingKey), + _ pairK: (keyPath: KeyPath, codingKey: CodingKey), + _ pairL: (keyPath: KeyPath, codingKey: CodingKey), + _ pairM: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + collection.addPair(keyPath: pairJ.keyPath, codingKey: pairJ.codingKey) + collection.addPair(keyPath: pairK.keyPath, codingKey: pairK.codingKey) + collection.addPair(keyPath: pairL.keyPath, codingKey: pairL.codingKey) + collection.addPair(keyPath: pairM.keyPath, codingKey: pairM.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable, + ValueJ: Codable, + ValueK: Codable, + ValueL: Codable, + ValueM: Codable, + ValueN: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey), + _ pairJ: (keyPath: KeyPath, codingKey: CodingKey), + _ pairK: (keyPath: KeyPath, codingKey: CodingKey), + _ pairL: (keyPath: KeyPath, codingKey: CodingKey), + _ pairM: (keyPath: KeyPath, codingKey: CodingKey), + _ pairN: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + collection.addPair(keyPath: pairJ.keyPath, codingKey: pairJ.codingKey) + collection.addPair(keyPath: pairK.keyPath, codingKey: pairK.codingKey) + collection.addPair(keyPath: pairL.keyPath, codingKey: pairL.codingKey) + collection.addPair(keyPath: pairM.keyPath, codingKey: pairM.codingKey) + collection.addPair(keyPath: pairN.keyPath, codingKey: pairN.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable, + ValueJ: Codable, + ValueK: Codable, + ValueL: Codable, + ValueM: Codable, + ValueN: Codable, + ValueO: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey), + _ pairJ: (keyPath: KeyPath, codingKey: CodingKey), + _ pairK: (keyPath: KeyPath, codingKey: CodingKey), + _ pairL: (keyPath: KeyPath, codingKey: CodingKey), + _ pairM: (keyPath: KeyPath, codingKey: CodingKey), + _ pairN: (keyPath: KeyPath, codingKey: CodingKey), + _ pairO: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + collection.addPair(keyPath: pairJ.keyPath, codingKey: pairJ.codingKey) + collection.addPair(keyPath: pairK.keyPath, codingKey: pairK.codingKey) + collection.addPair(keyPath: pairL.keyPath, codingKey: pairL.codingKey) + collection.addPair(keyPath: pairM.keyPath, codingKey: pairM.codingKey) + collection.addPair(keyPath: pairN.keyPath, codingKey: pairN.codingKey) + collection.addPair(keyPath: pairO.keyPath, codingKey: pairO.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable, + ValueJ: Codable, + ValueK: Codable, + ValueL: Codable, + ValueM: Codable, + ValueN: Codable, + ValueO: Codable, + ValueP: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey), + _ pairJ: (keyPath: KeyPath, codingKey: CodingKey), + _ pairK: (keyPath: KeyPath, codingKey: CodingKey), + _ pairL: (keyPath: KeyPath, codingKey: CodingKey), + _ pairM: (keyPath: KeyPath, codingKey: CodingKey), + _ pairN: (keyPath: KeyPath, codingKey: CodingKey), + _ pairO: (keyPath: KeyPath, codingKey: CodingKey), + _ pairP: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + collection.addPair(keyPath: pairJ.keyPath, codingKey: pairJ.codingKey) + collection.addPair(keyPath: pairK.keyPath, codingKey: pairK.codingKey) + collection.addPair(keyPath: pairL.keyPath, codingKey: pairL.codingKey) + collection.addPair(keyPath: pairM.keyPath, codingKey: pairM.codingKey) + collection.addPair(keyPath: pairN.keyPath, codingKey: pairN.codingKey) + collection.addPair(keyPath: pairO.keyPath, codingKey: pairO.codingKey) + collection.addPair(keyPath: pairP.keyPath, codingKey: pairP.codingKey) + return collection + } +} +#elseif swift(>=5.1) +@_functionBuilder +public final class KeyPathCodingKeyCollectionBuilder { + static func buildBlock< + ValueA: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable, + ValueJ: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey), + _ pairJ: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + collection.addPair(keyPath: pairJ.keyPath, codingKey: pairJ.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable, + ValueJ: Codable, + ValueK: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey), + _ pairJ: (keyPath: KeyPath, codingKey: CodingKey), + _ pairK: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + collection.addPair(keyPath: pairJ.keyPath, codingKey: pairJ.codingKey) + collection.addPair(keyPath: pairK.keyPath, codingKey: pairK.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable, + ValueJ: Codable, + ValueK: Codable, + ValueL: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey), + _ pairJ: (keyPath: KeyPath, codingKey: CodingKey), + _ pairK: (keyPath: KeyPath, codingKey: CodingKey), + _ pairL: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + collection.addPair(keyPath: pairJ.keyPath, codingKey: pairJ.codingKey) + collection.addPair(keyPath: pairK.keyPath, codingKey: pairK.codingKey) + collection.addPair(keyPath: pairL.keyPath, codingKey: pairL.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable, + ValueJ: Codable, + ValueK: Codable, + ValueL: Codable, + ValueM: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey), + _ pairJ: (keyPath: KeyPath, codingKey: CodingKey), + _ pairK: (keyPath: KeyPath, codingKey: CodingKey), + _ pairL: (keyPath: KeyPath, codingKey: CodingKey), + _ pairM: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + collection.addPair(keyPath: pairJ.keyPath, codingKey: pairJ.codingKey) + collection.addPair(keyPath: pairK.keyPath, codingKey: pairK.codingKey) + collection.addPair(keyPath: pairL.keyPath, codingKey: pairL.codingKey) + collection.addPair(keyPath: pairM.keyPath, codingKey: pairM.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable, + ValueJ: Codable, + ValueK: Codable, + ValueL: Codable, + ValueM: Codable, + ValueN: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey), + _ pairJ: (keyPath: KeyPath, codingKey: CodingKey), + _ pairK: (keyPath: KeyPath, codingKey: CodingKey), + _ pairL: (keyPath: KeyPath, codingKey: CodingKey), + _ pairM: (keyPath: KeyPath, codingKey: CodingKey), + _ pairN: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + collection.addPair(keyPath: pairJ.keyPath, codingKey: pairJ.codingKey) + collection.addPair(keyPath: pairK.keyPath, codingKey: pairK.codingKey) + collection.addPair(keyPath: pairL.keyPath, codingKey: pairL.codingKey) + collection.addPair(keyPath: pairM.keyPath, codingKey: pairM.codingKey) + collection.addPair(keyPath: pairN.keyPath, codingKey: pairN.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable, + ValueJ: Codable, + ValueK: Codable, + ValueL: Codable, + ValueM: Codable, + ValueN: Codable, + ValueO: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey), + _ pairJ: (keyPath: KeyPath, codingKey: CodingKey), + _ pairK: (keyPath: KeyPath, codingKey: CodingKey), + _ pairL: (keyPath: KeyPath, codingKey: CodingKey), + _ pairM: (keyPath: KeyPath, codingKey: CodingKey), + _ pairN: (keyPath: KeyPath, codingKey: CodingKey), + _ pairO: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + collection.addPair(keyPath: pairJ.keyPath, codingKey: pairJ.codingKey) + collection.addPair(keyPath: pairK.keyPath, codingKey: pairK.codingKey) + collection.addPair(keyPath: pairL.keyPath, codingKey: pairL.codingKey) + collection.addPair(keyPath: pairM.keyPath, codingKey: pairM.codingKey) + collection.addPair(keyPath: pairN.keyPath, codingKey: pairN.codingKey) + collection.addPair(keyPath: pairO.keyPath, codingKey: pairO.codingKey) + return collection + } + + static func buildBlock< + ValueA: Codable, + ValueB: Codable, + ValueC: Codable, + ValueD: Codable, + ValueE: Codable, + ValueF: Codable, + ValueG: Codable, + ValueH: Codable, + ValueI: Codable, + ValueJ: Codable, + ValueK: Codable, + ValueL: Codable, + ValueM: Codable, + ValueN: Codable, + ValueO: Codable, + ValueP: Codable + >( + _ pairA: (keyPath: KeyPath, codingKey: CodingKey), + _ pairB: (keyPath: KeyPath, codingKey: CodingKey), + _ pairC: (keyPath: KeyPath, codingKey: CodingKey), + _ pairD: (keyPath: KeyPath, codingKey: CodingKey), + _ pairE: (keyPath: KeyPath, codingKey: CodingKey), + _ pairF: (keyPath: KeyPath, codingKey: CodingKey), + _ pairG: (keyPath: KeyPath, codingKey: CodingKey), + _ pairH: (keyPath: KeyPath, codingKey: CodingKey), + _ pairI: (keyPath: KeyPath, codingKey: CodingKey), + _ pairJ: (keyPath: KeyPath, codingKey: CodingKey), + _ pairK: (keyPath: KeyPath, codingKey: CodingKey), + _ pairL: (keyPath: KeyPath, codingKey: CodingKey), + _ pairM: (keyPath: KeyPath, codingKey: CodingKey), + _ pairN: (keyPath: KeyPath, codingKey: CodingKey), + _ pairO: (keyPath: KeyPath, codingKey: CodingKey), + _ pairP: (keyPath: KeyPath, codingKey: CodingKey) + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: pairA.keyPath, codingKey: pairA.codingKey) + collection.addPair(keyPath: pairB.keyPath, codingKey: pairB.codingKey) + collection.addPair(keyPath: pairC.keyPath, codingKey: pairC.codingKey) + collection.addPair(keyPath: pairD.keyPath, codingKey: pairD.codingKey) + collection.addPair(keyPath: pairE.keyPath, codingKey: pairE.codingKey) + collection.addPair(keyPath: pairF.keyPath, codingKey: pairF.codingKey) + collection.addPair(keyPath: pairG.keyPath, codingKey: pairG.codingKey) + collection.addPair(keyPath: pairH.keyPath, codingKey: pairH.codingKey) + collection.addPair(keyPath: pairI.keyPath, codingKey: pairI.codingKey) + collection.addPair(keyPath: pairJ.keyPath, codingKey: pairJ.codingKey) + collection.addPair(keyPath: pairK.keyPath, codingKey: pairK.codingKey) + collection.addPair(keyPath: pairL.keyPath, codingKey: pairL.codingKey) + collection.addPair(keyPath: pairM.keyPath, codingKey: pairM.codingKey) + collection.addPair(keyPath: pairN.keyPath, codingKey: pairN.codingKey) + collection.addPair(keyPath: pairO.keyPath, codingKey: pairO.codingKey) + collection.addPair(keyPath: pairP.keyPath, codingKey: pairP.codingKey) + return collection + } +} +#endif diff --git a/Sources/Partial/Codable/KeyPathCodingKeyCollectionBuilder.swift.gyb b/Sources/Partial/Codable/KeyPathCodingKeyCollectionBuilder.swift.gyb new file mode 100644 index 00000000..a6c02d0e --- /dev/null +++ b/Sources/Partial/Codable/KeyPathCodingKeyCollectionBuilder.swift.gyb @@ -0,0 +1,82 @@ +% import string +// This file is generated. Do not edit it. +// swiftlint:disable function_parameter_count file_length type_body_length +#if swift(>=5.4) +@resultBuilder +public final class KeyPathCodingKeyCollectionBuilder { +% # 16 is arbitrary, but there has to be a limit somewhere +% parameterCountList = range(16) +% for parameterCount in parameterCountList: +% parametersRange = range(parameterCount + 1) + static func buildBlock< +% for characterIndex in parametersRange: +% isLast = characterIndex == parametersRange[-1] +% character = string.ascii_uppercase[characterIndex] +% if isLast: + Value${character}: Codable +% else: + Value${character}: Codable, +% end +% end + >( +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] +% isLast = characterIndex == parametersRange[-1] +% if isLast: + _ pair${character}: (keyPath: KeyPath, codingKey: CodingKey) +% else: + _ pair${character}: (keyPath: KeyPath, codingKey: CodingKey), +% end +% end + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + collection.addPair(keyPath: pair${character}.keyPath, codingKey: pair${character}.codingKey) +% end + return collection + } +% if parameterCount != parameterCountList[-1]: + +% end +% end +} +#elseif swift(>=5.1) +@_functionBuilder +public final class KeyPathCodingKeyCollectionBuilder { +% for parameterCount in parameterCountList: +% parametersRange = range(parameterCount + 1) + static func buildBlock< +% for characterIndex in parametersRange: +% isLast = characterIndex == parametersRange[-1] +% character = string.ascii_uppercase[characterIndex] +% if isLast: + Value${character}: Codable +% else: + Value${character}: Codable, +% end +% end + >( +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] +% isLast = characterIndex == parametersRange[-1] +% if isLast: + _ pair${character}: (keyPath: KeyPath, codingKey: CodingKey) +% else: + _ pair${character}: (keyPath: KeyPath, codingKey: CodingKey), +% end +% end + ) -> KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + collection.addPair(keyPath: pair${character}.keyPath, codingKey: pair${character}.codingKey) +% end + return collection + } +% if parameterCount != parameterCountList[-1]: + +% end +% end +} +#endif diff --git a/Sources/Partial/Codable/PartialCodable.swift b/Sources/Partial/Codable/PartialCodable.swift new file mode 100644 index 00000000..c30506b1 --- /dev/null +++ b/Sources/Partial/Codable/PartialCodable.swift @@ -0,0 +1,28 @@ +/// A type that can provide a map of key paths and coding keys to enable +/// `Codable` conformance to `Partial`. +public protocol PartialCodable { + /// The `CodingKey` type used to encode and decode values. + /// + /// This type has the extra requirement of being `Hashable`. This conformance is + /// synthesized when using a `Hashable` type as the `RawValue` of a `CodingKey` `enum`. + associatedtype CodingKey: Swift.CodingKey & Hashable + + /// Generate and return a collection of key paths and coding key maps. + /// + /// The `KeyPathCodingKeyCollectionBuilder` result builder is provided to simplify the + /// implementation of this property, for example: + /// + /// ```swift + /// struct CodableType: Codable, PartialCodable, Hashable { + /// @KeyPathCodingKeyCollectionBuilder + /// static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + /// (\Self.stringValue, CodingKeys.stringValue) + /// (\Self.intValue, CodingKeys.intValue) + /// } + /// + /// let stringValue: String + /// let intValue: Int + /// } + /// ``` + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { get } +} diff --git a/Sources/Partial/Partial.swift b/Sources/Partial/Partial.swift index fa882b3b..84b08820 100644 --- a/Sources/Partial/Partial.swift +++ b/Sources/Partial/Partial.swift @@ -3,11 +3,16 @@ import Foundation /// A struct that mirrors the properties of `Wrapped`, making each of the /// types optional. public struct Partial: PartialProtocol, CustomStringConvertible { - /// An error that can be thrown by the `value(for:)` function. public enum Error: Swift.Error { /// The key path has not been set. case keyPathNotSet(KeyPath) + + /// A value has been set to an unexpected type. + /// + /// - parameter value: The set value. + /// - parameter keyPath: The key path the value was set against. + case invalidType(value: Any, keyPath: KeyPath) } /// A textual representation of the Partial's values. @@ -16,7 +21,7 @@ public struct Partial: PartialProtocol, CustomStringConvertible { } /// The values that have been set. - private var values: [PartialKeyPath: Any] = [:] + fileprivate var values: [PartialKeyPath: Any] = [:] /// Create an empty `Partial`. public init() {} @@ -34,7 +39,7 @@ public struct Partial: PartialProtocol, CustomStringConvertible { return value } - preconditionFailure("Value has been set, but is not of type \(Value.self): \(value)") + throw Error.invalidType(value: value, keyPath: keyPath) } /// Updates the stored value for the given key path. @@ -51,5 +56,38 @@ public struct Partial: PartialProtocol, CustomStringConvertible { public mutating func removeValue(for keyPath: KeyPath) { values.removeValue(forKey: keyPath) } +} + +extension Partial: Codable where Wrapped: PartialCodable { + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: Wrapped.CodingKey.self) + let collection = Wrapped.keyPathCodingKeyCollection + values = try container + .allKeys + .reduce(into: [PartialKeyPath: Any](), { values, codingKey in + guard let (value, keyPath) = try collection.decode(codingKey, in: container) else { return } + values[keyPath] = value + }) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: Wrapped.CodingKey.self) + + let collection = Wrapped.keyPathCodingKeyCollection + try values.forEach { pair in + let (keyPath, value) = pair + + try collection.encode(value, forKey: keyPath, to: &container) + } + } +} + +extension Partial where Wrapped: PartialCodable & Codable { + public func decoded() throws -> Wrapped { + let encoder = JSONEncoder() + let data = try encoder.encode(self) + let decoder = JSONDecoder() + return try decoder.decode(Wrapped.self, from: data) + } } diff --git a/Sources/Partial/PartialBuilder.swift b/Sources/Partial/PartialBuilder.swift index 28a4331a..2e5cf88d 100644 --- a/Sources/Partial/PartialBuilder.swift +++ b/Sources/Partial/PartialBuilder.swift @@ -60,7 +60,7 @@ open class PartialBuilder: PartialProtocol, CustomStringConvertible { /// A collection of objects wrapping closures that will be notified when a change to a key path occurs private var keyPathSubscriptions: [PartialKeyPath: Set>] = [:] - + private var attachedSubscription: Subscription? /// Create an empty `PartialBuilder`. @@ -75,6 +75,13 @@ open class PartialBuilder: PartialProtocol, CustomStringConvertible { self.partial = partial } + #if swift(>=5.3) + public required init(from decoder: Decoder) throws where Wrapped: PartialCodable { + let container = try decoder.singleValueContainer() + partial = try container.decode(Partial.self) + } + #endif + /// Adds a closure that will be called when any key path has been updated. The closure will be called with the key /// path that was updated and this `PartialBuilder`. /// @@ -148,7 +155,7 @@ open class PartialBuilder: PartialProtocol, CustomStringConvertible { keyPathSubscriptions[keyPath]?.forEach { $0.wrapped?.notifyOfRemovable(oldValue: oldValue) } allChangesSubscriptions.forEach { $0.wrapped?.updateListener(keyPath, self) } } - + /// Creates a `PartialBuilder` for any `PartialConvertable` field in the type. It will automatically subscribe the original `PartialBuilder` to get updates made to the field's builder. /// /// - Parameter for: The `KeyPath` to create a `PartialBuilder` for. @@ -249,3 +256,20 @@ extension PartialBuilder { extension PartialBuilder.KeyPathUpdate.Kind: Equatable where Value: Equatable {} extension PartialBuilder.KeyPathUpdate: Equatable where Value: Equatable {} + +#if swift(>=5.3) +extension PartialBuilder: Decodable where Wrapped: PartialCodable {} +#endif + +extension PartialBuilder: Encodable where Wrapped: PartialCodable { + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(partial) + } +} + +extension PartialBuilder where Wrapped: PartialCodable & Codable { + public func decoded() throws -> Wrapped { + return try partial.decoded() + } +} diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift index 2c74eaa1..5e25c022 100644 --- a/Tests/LinuxMain.swift +++ b/Tests/LinuxMain.swift @@ -4,9 +4,12 @@ import Quick @testable import PartialTests QCKMain([ - PartialTests.self, + Partial_CodableTests.self, Partial_PartialConvertibleTests.self, - PartialBuilderTests.self, + PartialBuilder_CodableTests.self, PartialBuilder_PartialConvertibleTests.self, PartialBuilderSubscriptionTests.self, + PartialBuilderTests.self, + PartialBuilderSubscriptionTests.self, + PartialTests.self, ]) diff --git a/Tests/PartialTests/Tests/Partial+CodableTests.swift b/Tests/PartialTests/Tests/Partial+CodableTests.swift new file mode 100644 index 00000000..63f28cfb --- /dev/null +++ b/Tests/PartialTests/Tests/Partial+CodableTests.swift @@ -0,0 +1,1775 @@ +// This file is generated. Do not edit it. +// swiftlint:disable cyclomatic_complexity +import Quick +import Nimble +import Foundation + +@testable +import Partial + +final class Partial_CodableTests: QuickSpec { + override func spec() { + describe("Partial+Codable") { + context("with 1 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + return collection + } + #endif + + let stringA: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 2 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + return collection + } + #endif + + let stringA: String + let stringB: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 3 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 4 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 5 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 6 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 7 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 8 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 9 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 10 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + (\Self.stringJ, CodingKeys.stringJ) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + collection.addPair(keyPath: \.stringJ, codingKey: .stringJ) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + let stringJ: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + partial.setValue("Value J", for: \.stringJ) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + expect(try? decodedValue.value(for: \.stringJ)) == "Value J" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 11 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + (\Self.stringJ, CodingKeys.stringJ) + (\Self.stringK, CodingKeys.stringK) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + collection.addPair(keyPath: \.stringJ, codingKey: .stringJ) + collection.addPair(keyPath: \.stringK, codingKey: .stringK) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + let stringJ: String + let stringK: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + partial.setValue("Value J", for: \.stringJ) + partial.setValue("Value K", for: \.stringK) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + expect(try? decodedValue.value(for: \.stringJ)) == "Value J" + expect(try? decodedValue.value(for: \.stringK)) == "Value K" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 12 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + (\Self.stringJ, CodingKeys.stringJ) + (\Self.stringK, CodingKeys.stringK) + (\Self.stringL, CodingKeys.stringL) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + collection.addPair(keyPath: \.stringJ, codingKey: .stringJ) + collection.addPair(keyPath: \.stringK, codingKey: .stringK) + collection.addPair(keyPath: \.stringL, codingKey: .stringL) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + let stringJ: String + let stringK: String + let stringL: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + partial.setValue("Value J", for: \.stringJ) + partial.setValue("Value K", for: \.stringK) + partial.setValue("Value L", for: \.stringL) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + expect(try? decodedValue.value(for: \.stringJ)) == "Value J" + expect(try? decodedValue.value(for: \.stringK)) == "Value K" + expect(try? decodedValue.value(for: \.stringL)) == "Value L" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 13 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + (\Self.stringJ, CodingKeys.stringJ) + (\Self.stringK, CodingKeys.stringK) + (\Self.stringL, CodingKeys.stringL) + (\Self.stringM, CodingKeys.stringM) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + collection.addPair(keyPath: \.stringJ, codingKey: .stringJ) + collection.addPair(keyPath: \.stringK, codingKey: .stringK) + collection.addPair(keyPath: \.stringL, codingKey: .stringL) + collection.addPair(keyPath: \.stringM, codingKey: .stringM) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + let stringJ: String + let stringK: String + let stringL: String + let stringM: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + partial.setValue("Value J", for: \.stringJ) + partial.setValue("Value K", for: \.stringK) + partial.setValue("Value L", for: \.stringL) + partial.setValue("Value M", for: \.stringM) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + expect(decodedValue.stringM) == "Value M" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + expect(try? decodedValue.value(for: \.stringJ)) == "Value J" + expect(try? decodedValue.value(for: \.stringK)) == "Value K" + expect(try? decodedValue.value(for: \.stringL)) == "Value L" + expect(try? decodedValue.value(for: \.stringM)) == "Value M" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 14 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + (\Self.stringJ, CodingKeys.stringJ) + (\Self.stringK, CodingKeys.stringK) + (\Self.stringL, CodingKeys.stringL) + (\Self.stringM, CodingKeys.stringM) + (\Self.stringN, CodingKeys.stringN) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + collection.addPair(keyPath: \.stringJ, codingKey: .stringJ) + collection.addPair(keyPath: \.stringK, codingKey: .stringK) + collection.addPair(keyPath: \.stringL, codingKey: .stringL) + collection.addPair(keyPath: \.stringM, codingKey: .stringM) + collection.addPair(keyPath: \.stringN, codingKey: .stringN) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + let stringJ: String + let stringK: String + let stringL: String + let stringM: String + let stringN: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + partial.setValue("Value J", for: \.stringJ) + partial.setValue("Value K", for: \.stringK) + partial.setValue("Value L", for: \.stringL) + partial.setValue("Value M", for: \.stringM) + partial.setValue("Value N", for: \.stringN) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + expect(decodedValue.stringM) == "Value M" + expect(decodedValue.stringN) == "Value N" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + expect(try? decodedValue.value(for: \.stringJ)) == "Value J" + expect(try? decodedValue.value(for: \.stringK)) == "Value K" + expect(try? decodedValue.value(for: \.stringL)) == "Value L" + expect(try? decodedValue.value(for: \.stringM)) == "Value M" + expect(try? decodedValue.value(for: \.stringN)) == "Value N" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 15 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + (\Self.stringJ, CodingKeys.stringJ) + (\Self.stringK, CodingKeys.stringK) + (\Self.stringL, CodingKeys.stringL) + (\Self.stringM, CodingKeys.stringM) + (\Self.stringN, CodingKeys.stringN) + (\Self.stringO, CodingKeys.stringO) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + collection.addPair(keyPath: \.stringJ, codingKey: .stringJ) + collection.addPair(keyPath: \.stringK, codingKey: .stringK) + collection.addPair(keyPath: \.stringL, codingKey: .stringL) + collection.addPair(keyPath: \.stringM, codingKey: .stringM) + collection.addPair(keyPath: \.stringN, codingKey: .stringN) + collection.addPair(keyPath: \.stringO, codingKey: .stringO) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + let stringJ: String + let stringK: String + let stringL: String + let stringM: String + let stringN: String + let stringO: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + partial.setValue("Value J", for: \.stringJ) + partial.setValue("Value K", for: \.stringK) + partial.setValue("Value L", for: \.stringL) + partial.setValue("Value M", for: \.stringM) + partial.setValue("Value N", for: \.stringN) + partial.setValue("Value O", for: \.stringO) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + expect(decodedValue.stringM) == "Value M" + expect(decodedValue.stringN) == "Value N" + expect(decodedValue.stringO) == "Value O" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + expect(try? decodedValue.value(for: \.stringJ)) == "Value J" + expect(try? decodedValue.value(for: \.stringK)) == "Value K" + expect(try? decodedValue.value(for: \.stringL)) == "Value L" + expect(try? decodedValue.value(for: \.stringM)) == "Value M" + expect(try? decodedValue.value(for: \.stringN)) == "Value N" + expect(try? decodedValue.value(for: \.stringO)) == "Value O" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + context("with 16 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + (\Self.stringJ, CodingKeys.stringJ) + (\Self.stringK, CodingKeys.stringK) + (\Self.stringL, CodingKeys.stringL) + (\Self.stringM, CodingKeys.stringM) + (\Self.stringN, CodingKeys.stringN) + (\Self.stringO, CodingKeys.stringO) + (\Self.stringP, CodingKeys.stringP) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + collection.addPair(keyPath: \.stringJ, codingKey: .stringJ) + collection.addPair(keyPath: \.stringK, codingKey: .stringK) + collection.addPair(keyPath: \.stringL, codingKey: .stringL) + collection.addPair(keyPath: \.stringM, codingKey: .stringM) + collection.addPair(keyPath: \.stringN, codingKey: .stringN) + collection.addPair(keyPath: \.stringO, codingKey: .stringO) + collection.addPair(keyPath: \.stringP, codingKey: .stringP) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + let stringJ: String + let stringK: String + let stringL: String + let stringM: String + let stringN: String + let stringO: String + let stringP: String + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + partial.setValue("Value J", for: \.stringJ) + partial.setValue("Value K", for: \.stringK) + partial.setValue("Value L", for: \.stringL) + partial.setValue("Value M", for: \.stringM) + partial.setValue("Value N", for: \.stringN) + partial.setValue("Value O", for: \.stringO) + partial.setValue("Value P", for: \.stringP) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + expect(decodedValue.stringM) == "Value M" + expect(decodedValue.stringN) == "Value N" + expect(decodedValue.stringO) == "Value O" + expect(decodedValue.stringP) == "Value P" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + expect(try? decodedValue.value(for: \.stringJ)) == "Value J" + expect(try? decodedValue.value(for: \.stringK)) == "Value K" + expect(try? decodedValue.value(for: \.stringL)) == "Value L" + expect(try? decodedValue.value(for: \.stringM)) == "Value M" + expect(try? decodedValue.value(for: \.stringN)) == "Value N" + expect(try? decodedValue.value(for: \.stringO)) == "Value O" + expect(try? decodedValue.value(for: \.stringP)) == "Value P" + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } + } + } +} diff --git a/Tests/PartialTests/Tests/Partial+CodableTests.swift.gyb b/Tests/PartialTests/Tests/Partial+CodableTests.swift.gyb new file mode 100644 index 00000000..51734637 --- /dev/null +++ b/Tests/PartialTests/Tests/Partial+CodableTests.swift.gyb @@ -0,0 +1,103 @@ +% import string +// This file is generated. Do not edit it. +// swiftlint:disable cyclomatic_complexity +import Quick +import Nimble +import Foundation + +@testable +import Partial + +final class Partial_CodableTests: QuickSpec { + override func spec() { + describe("Partial+Codable") { +% parameterCountList = range(16) +% for parameterCount in parameterCountList: +% parametersRange = range(parameterCount + 1) + context("with ${parameterCount + 1} property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + (\Self.string${character}, CodingKeys.string${character}) +% end + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + collection.addPair(keyPath: \.string${character}, codingKey: .string${character}) +% end + return collection + } + #endif + +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + let string${character}: String +% end + } + + var partial: Partial! + + beforeEach { + partial = Partial() + } + + context("with complete value") { + beforeEach { +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + partial.setValue("Value ${character}", for: \.string${character}) +% end + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + expect(decodedValue.string${character}) == "Value ${character}" +% end + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + expect(try? decodedValue.value(for: \.string${character})) == "Value ${character}" +% end + } catch { + fail("Should not throw: \(error)") + } + } + } + } + } +% end + } + } +} diff --git a/Tests/PartialTests/Tests/PartialBuilder+CodableTests.swift b/Tests/PartialTests/Tests/PartialBuilder+CodableTests.swift new file mode 100644 index 00000000..13d7864e --- /dev/null +++ b/Tests/PartialTests/Tests/PartialBuilder+CodableTests.swift @@ -0,0 +1,2103 @@ +// This file is generated. Do not edit it. +// swiftlint:disable cyclomatic_complexity +import Quick +import Nimble +import Foundation + +@testable +import Partial + +final class PartialBuilder_CodableTests: QuickSpec { + override func spec() { + describe("PartialBuilder+Codable") { + context("with 1 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + return collection + } + #endif + + let stringA: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 2 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + return collection + } + #endif + + let stringA: String + let stringB: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 3 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 4 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 5 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 6 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 7 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 8 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 9 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 10 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + (\Self.stringJ, CodingKeys.stringJ) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + collection.addPair(keyPath: \.stringJ, codingKey: .stringJ) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + let stringJ: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + partial.setValue("Value J", for: \.stringJ) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + expect(try? decodedValue.value(for: \.stringJ)) == "Value J" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 11 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + (\Self.stringJ, CodingKeys.stringJ) + (\Self.stringK, CodingKeys.stringK) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + collection.addPair(keyPath: \.stringJ, codingKey: .stringJ) + collection.addPair(keyPath: \.stringK, codingKey: .stringK) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + let stringJ: String + let stringK: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + partial.setValue("Value J", for: \.stringJ) + partial.setValue("Value K", for: \.stringK) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + expect(try? decodedValue.value(for: \.stringJ)) == "Value J" + expect(try? decodedValue.value(for: \.stringK)) == "Value K" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 12 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + (\Self.stringJ, CodingKeys.stringJ) + (\Self.stringK, CodingKeys.stringK) + (\Self.stringL, CodingKeys.stringL) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + collection.addPair(keyPath: \.stringJ, codingKey: .stringJ) + collection.addPair(keyPath: \.stringK, codingKey: .stringK) + collection.addPair(keyPath: \.stringL, codingKey: .stringL) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + let stringJ: String + let stringK: String + let stringL: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + partial.setValue("Value J", for: \.stringJ) + partial.setValue("Value K", for: \.stringK) + partial.setValue("Value L", for: \.stringL) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + expect(try? decodedValue.value(for: \.stringJ)) == "Value J" + expect(try? decodedValue.value(for: \.stringK)) == "Value K" + expect(try? decodedValue.value(for: \.stringL)) == "Value L" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 13 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + (\Self.stringJ, CodingKeys.stringJ) + (\Self.stringK, CodingKeys.stringK) + (\Self.stringL, CodingKeys.stringL) + (\Self.stringM, CodingKeys.stringM) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + collection.addPair(keyPath: \.stringJ, codingKey: .stringJ) + collection.addPair(keyPath: \.stringK, codingKey: .stringK) + collection.addPair(keyPath: \.stringL, codingKey: .stringL) + collection.addPair(keyPath: \.stringM, codingKey: .stringM) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + let stringJ: String + let stringK: String + let stringL: String + let stringM: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + partial.setValue("Value J", for: \.stringJ) + partial.setValue("Value K", for: \.stringK) + partial.setValue("Value L", for: \.stringL) + partial.setValue("Value M", for: \.stringM) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + expect(decodedValue.stringM) == "Value M" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + expect(try? decodedValue.value(for: \.stringJ)) == "Value J" + expect(try? decodedValue.value(for: \.stringK)) == "Value K" + expect(try? decodedValue.value(for: \.stringL)) == "Value L" + expect(try? decodedValue.value(for: \.stringM)) == "Value M" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + expect(decodedValue.stringM) == "Value M" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 14 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + (\Self.stringJ, CodingKeys.stringJ) + (\Self.stringK, CodingKeys.stringK) + (\Self.stringL, CodingKeys.stringL) + (\Self.stringM, CodingKeys.stringM) + (\Self.stringN, CodingKeys.stringN) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + collection.addPair(keyPath: \.stringJ, codingKey: .stringJ) + collection.addPair(keyPath: \.stringK, codingKey: .stringK) + collection.addPair(keyPath: \.stringL, codingKey: .stringL) + collection.addPair(keyPath: \.stringM, codingKey: .stringM) + collection.addPair(keyPath: \.stringN, codingKey: .stringN) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + let stringJ: String + let stringK: String + let stringL: String + let stringM: String + let stringN: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + partial.setValue("Value J", for: \.stringJ) + partial.setValue("Value K", for: \.stringK) + partial.setValue("Value L", for: \.stringL) + partial.setValue("Value M", for: \.stringM) + partial.setValue("Value N", for: \.stringN) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + expect(decodedValue.stringM) == "Value M" + expect(decodedValue.stringN) == "Value N" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + expect(try? decodedValue.value(for: \.stringJ)) == "Value J" + expect(try? decodedValue.value(for: \.stringK)) == "Value K" + expect(try? decodedValue.value(for: \.stringL)) == "Value L" + expect(try? decodedValue.value(for: \.stringM)) == "Value M" + expect(try? decodedValue.value(for: \.stringN)) == "Value N" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + expect(decodedValue.stringM) == "Value M" + expect(decodedValue.stringN) == "Value N" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 15 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + (\Self.stringJ, CodingKeys.stringJ) + (\Self.stringK, CodingKeys.stringK) + (\Self.stringL, CodingKeys.stringL) + (\Self.stringM, CodingKeys.stringM) + (\Self.stringN, CodingKeys.stringN) + (\Self.stringO, CodingKeys.stringO) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + collection.addPair(keyPath: \.stringJ, codingKey: .stringJ) + collection.addPair(keyPath: \.stringK, codingKey: .stringK) + collection.addPair(keyPath: \.stringL, codingKey: .stringL) + collection.addPair(keyPath: \.stringM, codingKey: .stringM) + collection.addPair(keyPath: \.stringN, codingKey: .stringN) + collection.addPair(keyPath: \.stringO, codingKey: .stringO) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + let stringJ: String + let stringK: String + let stringL: String + let stringM: String + let stringN: String + let stringO: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + partial.setValue("Value J", for: \.stringJ) + partial.setValue("Value K", for: \.stringK) + partial.setValue("Value L", for: \.stringL) + partial.setValue("Value M", for: \.stringM) + partial.setValue("Value N", for: \.stringN) + partial.setValue("Value O", for: \.stringO) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + expect(decodedValue.stringM) == "Value M" + expect(decodedValue.stringN) == "Value N" + expect(decodedValue.stringO) == "Value O" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + expect(try? decodedValue.value(for: \.stringJ)) == "Value J" + expect(try? decodedValue.value(for: \.stringK)) == "Value K" + expect(try? decodedValue.value(for: \.stringL)) == "Value L" + expect(try? decodedValue.value(for: \.stringM)) == "Value M" + expect(try? decodedValue.value(for: \.stringN)) == "Value N" + expect(try? decodedValue.value(for: \.stringO)) == "Value O" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + expect(decodedValue.stringM) == "Value M" + expect(decodedValue.stringN) == "Value N" + expect(decodedValue.stringO) == "Value O" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + context("with 16 property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + (\Self.stringA, CodingKeys.stringA) + (\Self.stringB, CodingKeys.stringB) + (\Self.stringC, CodingKeys.stringC) + (\Self.stringD, CodingKeys.stringD) + (\Self.stringE, CodingKeys.stringE) + (\Self.stringF, CodingKeys.stringF) + (\Self.stringG, CodingKeys.stringG) + (\Self.stringH, CodingKeys.stringH) + (\Self.stringI, CodingKeys.stringI) + (\Self.stringJ, CodingKeys.stringJ) + (\Self.stringK, CodingKeys.stringK) + (\Self.stringL, CodingKeys.stringL) + (\Self.stringM, CodingKeys.stringM) + (\Self.stringN, CodingKeys.stringN) + (\Self.stringO, CodingKeys.stringO) + (\Self.stringP, CodingKeys.stringP) + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() + collection.addPair(keyPath: \.stringA, codingKey: .stringA) + collection.addPair(keyPath: \.stringB, codingKey: .stringB) + collection.addPair(keyPath: \.stringC, codingKey: .stringC) + collection.addPair(keyPath: \.stringD, codingKey: .stringD) + collection.addPair(keyPath: \.stringE, codingKey: .stringE) + collection.addPair(keyPath: \.stringF, codingKey: .stringF) + collection.addPair(keyPath: \.stringG, codingKey: .stringG) + collection.addPair(keyPath: \.stringH, codingKey: .stringH) + collection.addPair(keyPath: \.stringI, codingKey: .stringI) + collection.addPair(keyPath: \.stringJ, codingKey: .stringJ) + collection.addPair(keyPath: \.stringK, codingKey: .stringK) + collection.addPair(keyPath: \.stringL, codingKey: .stringL) + collection.addPair(keyPath: \.stringM, codingKey: .stringM) + collection.addPair(keyPath: \.stringN, codingKey: .stringN) + collection.addPair(keyPath: \.stringO, codingKey: .stringO) + collection.addPair(keyPath: \.stringP, codingKey: .stringP) + return collection + } + #endif + + let stringA: String + let stringB: String + let stringC: String + let stringD: String + let stringE: String + let stringF: String + let stringG: String + let stringH: String + let stringI: String + let stringJ: String + let stringK: String + let stringL: String + let stringM: String + let stringN: String + let stringO: String + let stringP: String + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { + partial.setValue("Value A", for: \.stringA) + partial.setValue("Value B", for: \.stringB) + partial.setValue("Value C", for: \.stringC) + partial.setValue("Value D", for: \.stringD) + partial.setValue("Value E", for: \.stringE) + partial.setValue("Value F", for: \.stringF) + partial.setValue("Value G", for: \.stringG) + partial.setValue("Value H", for: \.stringH) + partial.setValue("Value I", for: \.stringI) + partial.setValue("Value J", for: \.stringJ) + partial.setValue("Value K", for: \.stringK) + partial.setValue("Value L", for: \.stringL) + partial.setValue("Value M", for: \.stringM) + partial.setValue("Value N", for: \.stringN) + partial.setValue("Value O", for: \.stringO) + partial.setValue("Value P", for: \.stringP) + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + expect(decodedValue.stringM) == "Value M" + expect(decodedValue.stringN) == "Value N" + expect(decodedValue.stringO) == "Value O" + expect(decodedValue.stringP) == "Value P" + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + + expect(try? decodedValue.value(for: \.stringA)) == "Value A" + expect(try? decodedValue.value(for: \.stringB)) == "Value B" + expect(try? decodedValue.value(for: \.stringC)) == "Value C" + expect(try? decodedValue.value(for: \.stringD)) == "Value D" + expect(try? decodedValue.value(for: \.stringE)) == "Value E" + expect(try? decodedValue.value(for: \.stringF)) == "Value F" + expect(try? decodedValue.value(for: \.stringG)) == "Value G" + expect(try? decodedValue.value(for: \.stringH)) == "Value H" + expect(try? decodedValue.value(for: \.stringI)) == "Value I" + expect(try? decodedValue.value(for: \.stringJ)) == "Value J" + expect(try? decodedValue.value(for: \.stringK)) == "Value K" + expect(try? decodedValue.value(for: \.stringL)) == "Value L" + expect(try? decodedValue.value(for: \.stringM)) == "Value M" + expect(try? decodedValue.value(for: \.stringN)) == "Value N" + expect(try? decodedValue.value(for: \.stringO)) == "Value O" + expect(try? decodedValue.value(for: \.stringP)) == "Value P" + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + + expect(decodedValue.stringA) == "Value A" + expect(decodedValue.stringB) == "Value B" + expect(decodedValue.stringC) == "Value C" + expect(decodedValue.stringD) == "Value D" + expect(decodedValue.stringE) == "Value E" + expect(decodedValue.stringF) == "Value F" + expect(decodedValue.stringG) == "Value G" + expect(decodedValue.stringH) == "Value H" + expect(decodedValue.stringI) == "Value I" + expect(decodedValue.stringJ) == "Value J" + expect(decodedValue.stringK) == "Value K" + expect(decodedValue.stringL) == "Value L" + expect(decodedValue.stringM) == "Value M" + expect(decodedValue.stringN) == "Value N" + expect(decodedValue.stringO) == "Value O" + expect(decodedValue.stringP) == "Value P" + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } + } + } +} diff --git a/Tests/PartialTests/Tests/PartialBuilder+CodableTests.swift.gyb b/Tests/PartialTests/Tests/PartialBuilder+CodableTests.swift.gyb new file mode 100644 index 00000000..b6ceea75 --- /dev/null +++ b/Tests/PartialTests/Tests/PartialBuilder+CodableTests.swift.gyb @@ -0,0 +1,119 @@ +% import string +// This file is generated. Do not edit it. +// swiftlint:disable cyclomatic_complexity +import Quick +import Nimble +import Foundation + +@testable +import Partial + +final class PartialBuilder_CodableTests: QuickSpec { + override func spec() { + describe("PartialBuilder+Codable") { +% parameterCountList = range(16) +% for parameterCount in parameterCountList: +% parametersRange = range(parameterCount + 1) + context("with ${parameterCount + 1} property") { + struct CodableType: Codable, PartialCodable, Hashable { + #if swift(>=5.1) + @KeyPathCodingKeyCollectionBuilder + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + (\Self.string${character}, CodingKeys.string${character}) +% end + } + #else + static var keyPathCodingKeyCollection: KeyPathCodingKeyCollection { + var collection = KeyPathCodingKeyCollection() +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + collection.addPair(keyPath: \.string${character}, codingKey: .string${character}) +% end + return collection + } + #endif + +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + let string${character}: String +% end + } + + var partial: PartialBuilder! + + beforeEach { + partial = PartialBuilder() + } + + context("with complete value") { + beforeEach { +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + partial.setValue("Value ${character}", for: \.string${character}) +% end + } + + context("the encoded data") { + var encodedData: Data! + + beforeEach { + let encoder = JSONEncoder() + encodedData = try? encoder.encode(partial) + } + + it("should not be nil") { + expect(encodedData).toNot(beNil()) + } + + it("should be usable to decode Wrapped") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(CodableType.self, from: encodedData) + +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + expect(decodedValue.string${character}) == "Value ${character}" +% end + } catch { + fail("Should not throw: \(error)") + } + } + + it("should be usable to decode Partial") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(Partial.self, from: encodedData) + +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + expect(try? decodedValue.value(for: \.string${character})) == "Value ${character}" +% end + } catch { + fail("Should not throw: \(error)") + } + } + + #if swift(>=5.3) + it("should be usable to decode PartialBuilder") { + do { + let decoder = JSONDecoder() + let decodedValue = try decoder.decode(PartialBuilder.self, from: encodedData) + +% for characterIndex in parametersRange: +% character = string.ascii_uppercase[characterIndex] + expect(decodedValue.string${character}) == "Value ${character}" +% end + } catch { + fail("Should not throw: \(error)") + } + } + #endif + } + } + } +% end + } + } +} diff --git a/scripts/generate-KeyPathCodingKeyCollectionBuilder.sh b/scripts/generate-KeyPathCodingKeyCollectionBuilder.sh new file mode 100755 index 00000000..c4196e6a --- /dev/null +++ b/scripts/generate-KeyPathCodingKeyCollectionBuilder.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +KeyPathCodingKeyCollectionBuilder_FILE="Sources/Partial/Codable/KeyPathCodingKeyCollectionBuilder.swift" +PartialCodableTests_FILE="Tests/PartialTests/Tests/Partial+CodableTests.swift" +PartialBuilderCodableTests_FILE="Tests/PartialTests/Tests/PartialBuilder+CodableTests.swift" + +gyb --line-directive '' -o "$KeyPathCodingKeyCollectionBuilder_FILE" "$KeyPathCodingKeyCollectionBuilder_FILE.gyb" +gyb --line-directive '' -o "$PartialCodableTests_FILE" "$PartialCodableTests_FILE.gyb" +gyb --line-directive '' -o "$PartialBuilderCodableTests_FILE" "$PartialBuilderCodableTests_FILE.gyb"