From c3e5ee7a6a2e7f80e199e417fd2f32a66e169b6f Mon Sep 17 00:00:00 2001 From: Andrew Eng Date: Wed, 28 Mar 2018 15:35:20 +0800 Subject: [PATCH 1/2] Added Codable support --- MessagePack.xcodeproj/project.pbxproj | 190 +++++++ .../Decoder/MessagePackDecoder.swift | 74 +++ .../MessagePackKeyedDecodingContainer.swift | 215 ++++++++ ...sagePackSingleValueDecodingContainer.swift | 70 +++ .../MessagePackUnkeyedDecodingContainer.swift | 131 +++++ .../Encoder/MessagePackEncoder.swift | 41 ++ .../MessagePackKeyedEncodingContainer.swift | 135 +++++ ...sagePackSingleValueEncodingContainer.swift | 65 +++ .../Encoder/MessagePackStorage.swift | 73 +++ .../MessagePackUnkeyedEncodingContainer.swift | 83 +++ .../Encoder/_MessagePackEncoder.swift | 87 ++++ .../MessagePackRepresentable.swift | 119 +++++ .../Codable/MessagePackDecoderTests.swift | 376 ++++++++++++++ .../Codable/MessagePackEncoderTests.swift | 491 ++++++++++++++++++ .../Codable/ModelProtocol.swift | 17 + Tests/MessagePackTests/Codable/Models.swift | 59 +++ .../Codable/OptionalModels.swift | 122 +++++ .../Codable/SingleOptionalTypeModels.swift | 133 +++++ .../Codable/SingleTypeModels.swift | 108 ++++ 19 files changed, 2589 insertions(+) create mode 100644 Sources/MessagePack/Decoder/MessagePackDecoder.swift create mode 100644 Sources/MessagePack/Decoder/MessagePackKeyedDecodingContainer.swift create mode 100644 Sources/MessagePack/Decoder/MessagePackSingleValueDecodingContainer.swift create mode 100644 Sources/MessagePack/Decoder/MessagePackUnkeyedDecodingContainer.swift create mode 100644 Sources/MessagePack/Encoder/MessagePackEncoder.swift create mode 100644 Sources/MessagePack/Encoder/MessagePackKeyedEncodingContainer.swift create mode 100644 Sources/MessagePack/Encoder/MessagePackSingleValueEncodingContainer.swift create mode 100644 Sources/MessagePack/Encoder/MessagePackStorage.swift create mode 100644 Sources/MessagePack/Encoder/MessagePackUnkeyedEncodingContainer.swift create mode 100644 Sources/MessagePack/Encoder/_MessagePackEncoder.swift create mode 100644 Sources/MessagePack/MessagePackRepresentable.swift create mode 100644 Tests/MessagePackTests/Codable/MessagePackDecoderTests.swift create mode 100644 Tests/MessagePackTests/Codable/MessagePackEncoderTests.swift create mode 100644 Tests/MessagePackTests/Codable/ModelProtocol.swift create mode 100644 Tests/MessagePackTests/Codable/Models.swift create mode 100644 Tests/MessagePackTests/Codable/OptionalModels.swift create mode 100644 Tests/MessagePackTests/Codable/SingleOptionalTypeModels.swift create mode 100644 Tests/MessagePackTests/Codable/SingleTypeModels.swift diff --git a/MessagePack.xcodeproj/project.pbxproj b/MessagePack.xcodeproj/project.pbxproj index c8279a5..e53d25c 100644 --- a/MessagePack.xcodeproj/project.pbxproj +++ b/MessagePack.xcodeproj/project.pbxproj @@ -93,6 +93,71 @@ 825322491EFFCBC700914B55 /* Pack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8253219B1EFFCA0D00914B55 /* Pack.swift */; }; 8253224A1EFFCBC700914B55 /* Subdata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8253219C1EFFCA0D00914B55 /* Subdata.swift */; }; 8253224B1EFFCBC700914B55 /* Unpack.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8253219D1EFFCA0D00914B55 /* Unpack.swift */; }; + BDB77A5C206B3F57001925D0 /* MessagePackUnkeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A51206B3F57001925D0 /* MessagePackUnkeyedDecodingContainer.swift */; }; + BDB77A5D206B3F57001925D0 /* MessagePackUnkeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A51206B3F57001925D0 /* MessagePackUnkeyedDecodingContainer.swift */; }; + BDB77A5E206B3F57001925D0 /* MessagePackUnkeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A51206B3F57001925D0 /* MessagePackUnkeyedDecodingContainer.swift */; }; + BDB77A5F206B3F57001925D0 /* MessagePackUnkeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A51206B3F57001925D0 /* MessagePackUnkeyedDecodingContainer.swift */; }; + BDB77A60206B3F57001925D0 /* MessagePackKeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A52206B3F57001925D0 /* MessagePackKeyedDecodingContainer.swift */; }; + BDB77A61206B3F57001925D0 /* MessagePackKeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A52206B3F57001925D0 /* MessagePackKeyedDecodingContainer.swift */; }; + BDB77A62206B3F57001925D0 /* MessagePackKeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A52206B3F57001925D0 /* MessagePackKeyedDecodingContainer.swift */; }; + BDB77A63206B3F57001925D0 /* MessagePackKeyedDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A52206B3F57001925D0 /* MessagePackKeyedDecodingContainer.swift */; }; + BDB77A64206B3F57001925D0 /* MessagePackDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A53206B3F57001925D0 /* MessagePackDecoder.swift */; }; + BDB77A65206B3F57001925D0 /* MessagePackDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A53206B3F57001925D0 /* MessagePackDecoder.swift */; }; + BDB77A66206B3F57001925D0 /* MessagePackDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A53206B3F57001925D0 /* MessagePackDecoder.swift */; }; + BDB77A67206B3F57001925D0 /* MessagePackDecoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A53206B3F57001925D0 /* MessagePackDecoder.swift */; }; + BDB77A68206B3F57001925D0 /* MessagePackSingleValueDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A54206B3F57001925D0 /* MessagePackSingleValueDecodingContainer.swift */; }; + BDB77A69206B3F57001925D0 /* MessagePackSingleValueDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A54206B3F57001925D0 /* MessagePackSingleValueDecodingContainer.swift */; }; + BDB77A6A206B3F57001925D0 /* MessagePackSingleValueDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A54206B3F57001925D0 /* MessagePackSingleValueDecodingContainer.swift */; }; + BDB77A6B206B3F57001925D0 /* MessagePackSingleValueDecodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A54206B3F57001925D0 /* MessagePackSingleValueDecodingContainer.swift */; }; + BDB77A6C206B3F57001925D0 /* MessagePackSingleValueEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A56206B3F57001925D0 /* MessagePackSingleValueEncodingContainer.swift */; }; + BDB77A6D206B3F57001925D0 /* MessagePackSingleValueEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A56206B3F57001925D0 /* MessagePackSingleValueEncodingContainer.swift */; }; + BDB77A6E206B3F57001925D0 /* MessagePackSingleValueEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A56206B3F57001925D0 /* MessagePackSingleValueEncodingContainer.swift */; }; + BDB77A6F206B3F57001925D0 /* MessagePackSingleValueEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A56206B3F57001925D0 /* MessagePackSingleValueEncodingContainer.swift */; }; + BDB77A70206B3F57001925D0 /* _MessagePackEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A57206B3F57001925D0 /* _MessagePackEncoder.swift */; }; + BDB77A71206B3F57001925D0 /* _MessagePackEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A57206B3F57001925D0 /* _MessagePackEncoder.swift */; }; + BDB77A72206B3F57001925D0 /* _MessagePackEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A57206B3F57001925D0 /* _MessagePackEncoder.swift */; }; + BDB77A73206B3F57001925D0 /* _MessagePackEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A57206B3F57001925D0 /* _MessagePackEncoder.swift */; }; + BDB77A74206B3F57001925D0 /* MessagePackStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A58206B3F57001925D0 /* MessagePackStorage.swift */; }; + BDB77A75206B3F57001925D0 /* MessagePackStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A58206B3F57001925D0 /* MessagePackStorage.swift */; }; + BDB77A76206B3F57001925D0 /* MessagePackStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A58206B3F57001925D0 /* MessagePackStorage.swift */; }; + BDB77A77206B3F57001925D0 /* MessagePackStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A58206B3F57001925D0 /* MessagePackStorage.swift */; }; + BDB77A78206B3F57001925D0 /* MessagePackUnkeyedEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A59206B3F57001925D0 /* MessagePackUnkeyedEncodingContainer.swift */; }; + BDB77A79206B3F57001925D0 /* MessagePackUnkeyedEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A59206B3F57001925D0 /* MessagePackUnkeyedEncodingContainer.swift */; }; + BDB77A7A206B3F57001925D0 /* MessagePackUnkeyedEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A59206B3F57001925D0 /* MessagePackUnkeyedEncodingContainer.swift */; }; + BDB77A7B206B3F57001925D0 /* MessagePackUnkeyedEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A59206B3F57001925D0 /* MessagePackUnkeyedEncodingContainer.swift */; }; + BDB77A7C206B3F57001925D0 /* MessagePackKeyedEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A5A206B3F57001925D0 /* MessagePackKeyedEncodingContainer.swift */; }; + BDB77A7D206B3F57001925D0 /* MessagePackKeyedEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A5A206B3F57001925D0 /* MessagePackKeyedEncodingContainer.swift */; }; + BDB77A7E206B3F57001925D0 /* MessagePackKeyedEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A5A206B3F57001925D0 /* MessagePackKeyedEncodingContainer.swift */; }; + BDB77A7F206B3F57001925D0 /* MessagePackKeyedEncodingContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A5A206B3F57001925D0 /* MessagePackKeyedEncodingContainer.swift */; }; + BDB77A80206B3F57001925D0 /* MessagePackEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A5B206B3F57001925D0 /* MessagePackEncoder.swift */; }; + BDB77A81206B3F57001925D0 /* MessagePackEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A5B206B3F57001925D0 /* MessagePackEncoder.swift */; }; + BDB77A82206B3F57001925D0 /* MessagePackEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A5B206B3F57001925D0 /* MessagePackEncoder.swift */; }; + BDB77A83206B3F57001925D0 /* MessagePackEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A5B206B3F57001925D0 /* MessagePackEncoder.swift */; }; + BDB77A85206B40FF001925D0 /* MessagePackRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A84206B40FF001925D0 /* MessagePackRepresentable.swift */; }; + BDB77A86206B40FF001925D0 /* MessagePackRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A84206B40FF001925D0 /* MessagePackRepresentable.swift */; }; + BDB77A87206B40FF001925D0 /* MessagePackRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A84206B40FF001925D0 /* MessagePackRepresentable.swift */; }; + BDB77A88206B40FF001925D0 /* MessagePackRepresentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A84206B40FF001925D0 /* MessagePackRepresentable.swift */; }; + BDB77A8C206B6ADC001925D0 /* MessagePackDecoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A8A206B6ADC001925D0 /* MessagePackDecoderTests.swift */; }; + BDB77A8D206B6ADC001925D0 /* MessagePackDecoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A8A206B6ADC001925D0 /* MessagePackDecoderTests.swift */; }; + BDB77A8E206B6ADC001925D0 /* MessagePackDecoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A8A206B6ADC001925D0 /* MessagePackDecoderTests.swift */; }; + BDB77A8F206B6ADC001925D0 /* MessagePackEncoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A8B206B6ADC001925D0 /* MessagePackEncoderTests.swift */; }; + BDB77A90206B6ADC001925D0 /* MessagePackEncoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A8B206B6ADC001925D0 /* MessagePackEncoderTests.swift */; }; + BDB77A91206B6ADC001925D0 /* MessagePackEncoderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A8B206B6ADC001925D0 /* MessagePackEncoderTests.swift */; }; + BDB77A98206B6B14001925D0 /* SingleOptionalTypeModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A92206B6B14001925D0 /* SingleOptionalTypeModels.swift */; }; + BDB77A99206B6B14001925D0 /* SingleOptionalTypeModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A92206B6B14001925D0 /* SingleOptionalTypeModels.swift */; }; + BDB77A9A206B6B14001925D0 /* SingleOptionalTypeModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A92206B6B14001925D0 /* SingleOptionalTypeModels.swift */; }; + BDB77A9E206B6B14001925D0 /* Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A94206B6B14001925D0 /* Models.swift */; }; + BDB77A9F206B6B14001925D0 /* Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A94206B6B14001925D0 /* Models.swift */; }; + BDB77AA0206B6B14001925D0 /* Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A94206B6B14001925D0 /* Models.swift */; }; + BDB77AA1206B6B14001925D0 /* OptionalModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A95206B6B14001925D0 /* OptionalModels.swift */; }; + BDB77AA2206B6B14001925D0 /* OptionalModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A95206B6B14001925D0 /* OptionalModels.swift */; }; + BDB77AA3206B6B14001925D0 /* OptionalModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A95206B6B14001925D0 /* OptionalModels.swift */; }; + BDB77AA4206B6B14001925D0 /* ModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A96206B6B14001925D0 /* ModelProtocol.swift */; }; + BDB77AA5206B6B14001925D0 /* ModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A96206B6B14001925D0 /* ModelProtocol.swift */; }; + BDB77AA6206B6B14001925D0 /* ModelProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A96206B6B14001925D0 /* ModelProtocol.swift */; }; + BDB77AA7206B6B14001925D0 /* SingleTypeModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A97206B6B14001925D0 /* SingleTypeModels.swift */; }; + BDB77AA8206B6B14001925D0 /* SingleTypeModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A97206B6B14001925D0 /* SingleTypeModels.swift */; }; + BDB77AA9206B6B14001925D0 /* SingleTypeModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BDB77A97206B6B14001925D0 /* SingleTypeModels.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -155,6 +220,24 @@ 825321E81EFFCAFA00914B55 /* MessagePackTests-tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "MessagePackTests-tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 825321FC1EFFCB2A00914B55 /* MessagePack.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MessagePack.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 825322041EFFCB2B00914B55 /* MessagePackTests-macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "MessagePackTests-macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; + BDB77A51206B3F57001925D0 /* MessagePackUnkeyedDecodingContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackUnkeyedDecodingContainer.swift; sourceTree = ""; }; + BDB77A52206B3F57001925D0 /* MessagePackKeyedDecodingContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackKeyedDecodingContainer.swift; sourceTree = ""; }; + BDB77A53206B3F57001925D0 /* MessagePackDecoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackDecoder.swift; sourceTree = ""; }; + BDB77A54206B3F57001925D0 /* MessagePackSingleValueDecodingContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackSingleValueDecodingContainer.swift; sourceTree = ""; }; + BDB77A56206B3F57001925D0 /* MessagePackSingleValueEncodingContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackSingleValueEncodingContainer.swift; sourceTree = ""; }; + BDB77A57206B3F57001925D0 /* _MessagePackEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = _MessagePackEncoder.swift; sourceTree = ""; }; + BDB77A58206B3F57001925D0 /* MessagePackStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackStorage.swift; sourceTree = ""; }; + BDB77A59206B3F57001925D0 /* MessagePackUnkeyedEncodingContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackUnkeyedEncodingContainer.swift; sourceTree = ""; }; + BDB77A5A206B3F57001925D0 /* MessagePackKeyedEncodingContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackKeyedEncodingContainer.swift; sourceTree = ""; }; + BDB77A5B206B3F57001925D0 /* MessagePackEncoder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackEncoder.swift; sourceTree = ""; }; + BDB77A84206B40FF001925D0 /* MessagePackRepresentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackRepresentable.swift; sourceTree = ""; }; + BDB77A8A206B6ADC001925D0 /* MessagePackDecoderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackDecoderTests.swift; sourceTree = ""; }; + BDB77A8B206B6ADC001925D0 /* MessagePackEncoderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MessagePackEncoderTests.swift; sourceTree = ""; }; + BDB77A92206B6B14001925D0 /* SingleOptionalTypeModels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleOptionalTypeModels.swift; sourceTree = ""; }; + BDB77A94206B6B14001925D0 /* Models.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Models.swift; sourceTree = ""; }; + BDB77A95206B6B14001925D0 /* OptionalModels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptionalModels.swift; sourceTree = ""; }; + BDB77A96206B6B14001925D0 /* ModelProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ModelProtocol.swift; sourceTree = ""; }; + BDB77A97206B6B14001925D0 /* SingleTypeModels.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SingleTypeModels.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -240,6 +323,9 @@ 8253217F1EFFC9C400914B55 /* MessagePack */ = { isa = PBXGroup; children = ( + BDB77A55206B3F57001925D0 /* Encoder */, + BDB77A50206B3F57001925D0 /* Decoder */, + BDB77A84206B40FF001925D0 /* MessagePackRepresentable.swift */, 825321971EFFCA0D00914B55 /* ConvenienceInitializers.swift */, 825321981EFFCA0D00914B55 /* ConvenienceProperties.swift */, 825321991EFFCA0D00914B55 /* LiteralConvertibles.swift */, @@ -255,6 +341,7 @@ 8253218A1EFFC9C500914B55 /* MessagePackTests */ = { isa = PBXGroup; children = ( + BDB77A89206B67A8001925D0 /* Codable */, 825321A51EFFCA1C00914B55 /* ArrayTests.swift */, 825321A61EFFCA1C00914B55 /* BinaryTests.swift */, 825321A71EFFCA1C00914B55 /* ConvenienceInitializersTests.swift */, @@ -288,6 +375,44 @@ path = Resources; sourceTree = ""; }; + BDB77A50206B3F57001925D0 /* Decoder */ = { + isa = PBXGroup; + children = ( + BDB77A53206B3F57001925D0 /* MessagePackDecoder.swift */, + BDB77A52206B3F57001925D0 /* MessagePackKeyedDecodingContainer.swift */, + BDB77A54206B3F57001925D0 /* MessagePackSingleValueDecodingContainer.swift */, + BDB77A51206B3F57001925D0 /* MessagePackUnkeyedDecodingContainer.swift */, + ); + path = Decoder; + sourceTree = ""; + }; + BDB77A55206B3F57001925D0 /* Encoder */ = { + isa = PBXGroup; + children = ( + BDB77A5B206B3F57001925D0 /* MessagePackEncoder.swift */, + BDB77A57206B3F57001925D0 /* _MessagePackEncoder.swift */, + BDB77A5A206B3F57001925D0 /* MessagePackKeyedEncodingContainer.swift */, + BDB77A56206B3F57001925D0 /* MessagePackSingleValueEncodingContainer.swift */, + BDB77A59206B3F57001925D0 /* MessagePackUnkeyedEncodingContainer.swift */, + BDB77A58206B3F57001925D0 /* MessagePackStorage.swift */, + ); + path = Encoder; + sourceTree = ""; + }; + BDB77A89206B67A8001925D0 /* Codable */ = { + isa = PBXGroup; + children = ( + BDB77A8B206B6ADC001925D0 /* MessagePackEncoderTests.swift */, + BDB77A8A206B6ADC001925D0 /* MessagePackDecoderTests.swift */, + BDB77A96206B6B14001925D0 /* ModelProtocol.swift */, + BDB77A97206B6B14001925D0 /* SingleTypeModels.swift */, + BDB77A92206B6B14001925D0 /* SingleOptionalTypeModels.swift */, + BDB77A94206B6B14001925D0 /* Models.swift */, + BDB77A95206B6B14001925D0 /* OptionalModels.swift */, + ); + path = Codable; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -571,13 +696,24 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + BDB77A60206B3F57001925D0 /* MessagePackKeyedDecodingContainer.swift in Sources */, 825321A41EFFCA0D00914B55 /* Unpack.swift in Sources */, + BDB77A7C206B3F57001925D0 /* MessagePackKeyedEncodingContainer.swift in Sources */, + BDB77A78206B3F57001925D0 /* MessagePackUnkeyedEncodingContainer.swift in Sources */, + BDB77A68206B3F57001925D0 /* MessagePackSingleValueDecodingContainer.swift in Sources */, 825321A31EFFCA0D00914B55 /* Subdata.swift in Sources */, 825321A11EFFCA0D00914B55 /* MessagePack.swift in Sources */, 825321A01EFFCA0D00914B55 /* LiteralConvertibles.swift in Sources */, + BDB77A74206B3F57001925D0 /* MessagePackStorage.swift in Sources */, 8253219F1EFFCA0D00914B55 /* ConvenienceProperties.swift in Sources */, + BDB77A70206B3F57001925D0 /* _MessagePackEncoder.swift in Sources */, + BDB77A5C206B3F57001925D0 /* MessagePackUnkeyedDecodingContainer.swift in Sources */, 8253219E1EFFCA0D00914B55 /* ConvenienceInitializers.swift in Sources */, + BDB77A85206B40FF001925D0 /* MessagePackRepresentable.swift in Sources */, + BDB77A6C206B3F57001925D0 /* MessagePackSingleValueEncodingContainer.swift in Sources */, 825321A21EFFCA0D00914B55 /* Pack.swift in Sources */, + BDB77A80206B3F57001925D0 /* MessagePackEncoder.swift in Sources */, + BDB77A64206B3F57001925D0 /* MessagePackDecoder.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -586,15 +722,22 @@ buildActionMask = 2147483647; files = ( 825321C31EFFCA1C00914B55 /* IntegerTests.swift in Sources */, + BDB77AA7206B6B14001925D0 /* SingleTypeModels.swift in Sources */, 825321C21EFFCA1C00914B55 /* HashValueTests.swift in Sources */, + BDB77A8C206B6ADC001925D0 /* MessagePackDecoderTests.swift in Sources */, 825321C11EFFCA1C00914B55 /* FloatTests.swift in Sources */, 825321BB1EFFCA1C00914B55 /* DescriptionTests.swift in Sources */, 825321B91EFFCA1C00914B55 /* ConvenienceInitializersTests.swift in Sources */, 825321BF1EFFCA1C00914B55 /* ExtendedTests.swift in Sources */, 825321C61EFFCA1C00914B55 /* StringTests.swift in Sources */, + BDB77AA1206B6B14001925D0 /* OptionalModels.swift in Sources */, 825321BC1EFFCA1C00914B55 /* DoubleTests.swift in Sources */, 825321C81EFFCA1C00914B55 /* TrueTests.swift in Sources */, + BDB77AA4206B6B14001925D0 /* ModelProtocol.swift in Sources */, + BDB77A9E206B6B14001925D0 /* Models.swift in Sources */, + BDB77A98206B6B14001925D0 /* SingleOptionalTypeModels.swift in Sources */, 825321B71EFFCA1C00914B55 /* ArrayTests.swift in Sources */, + BDB77A8F206B6ADC001925D0 /* MessagePackEncoderTests.swift in Sources */, 825321B81EFFCA1C00914B55 /* BinaryTests.swift in Sources */, 825321BA1EFFCA1C00914B55 /* ConveniencePropertiesTests.swift in Sources */, 825321C41EFFCA1C00914B55 /* MapTests.swift in Sources */, @@ -610,13 +753,24 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + BDB77A63206B3F57001925D0 /* MessagePackKeyedDecodingContainer.swift in Sources */, 8253224B1EFFCBC700914B55 /* Unpack.swift in Sources */, + BDB77A7F206B3F57001925D0 /* MessagePackKeyedEncodingContainer.swift in Sources */, + BDB77A7B206B3F57001925D0 /* MessagePackUnkeyedEncodingContainer.swift in Sources */, + BDB77A6B206B3F57001925D0 /* MessagePackSingleValueDecodingContainer.swift in Sources */, 8253224A1EFFCBC700914B55 /* Subdata.swift in Sources */, 825322481EFFCBC700914B55 /* MessagePack.swift in Sources */, 825322471EFFCBC700914B55 /* LiteralConvertibles.swift in Sources */, + BDB77A77206B3F57001925D0 /* MessagePackStorage.swift in Sources */, 825322461EFFCBC700914B55 /* ConvenienceProperties.swift in Sources */, + BDB77A73206B3F57001925D0 /* _MessagePackEncoder.swift in Sources */, + BDB77A5F206B3F57001925D0 /* MessagePackUnkeyedDecodingContainer.swift in Sources */, 825322451EFFCBC700914B55 /* ConvenienceInitializers.swift in Sources */, + BDB77A88206B40FF001925D0 /* MessagePackRepresentable.swift in Sources */, + BDB77A6F206B3F57001925D0 /* MessagePackSingleValueEncodingContainer.swift in Sources */, 825322491EFFCBC700914B55 /* Pack.swift in Sources */, + BDB77A83206B3F57001925D0 /* MessagePackEncoder.swift in Sources */, + BDB77A67206B3F57001925D0 /* MessagePackDecoder.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -624,13 +778,24 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + BDB77A62206B3F57001925D0 /* MessagePackKeyedDecodingContainer.swift in Sources */, 825322441EFFCBC700914B55 /* Unpack.swift in Sources */, + BDB77A7E206B3F57001925D0 /* MessagePackKeyedEncodingContainer.swift in Sources */, + BDB77A7A206B3F57001925D0 /* MessagePackUnkeyedEncodingContainer.swift in Sources */, + BDB77A6A206B3F57001925D0 /* MessagePackSingleValueDecodingContainer.swift in Sources */, 825322431EFFCBC700914B55 /* Subdata.swift in Sources */, 825322411EFFCBC700914B55 /* MessagePack.swift in Sources */, 825322401EFFCBC700914B55 /* LiteralConvertibles.swift in Sources */, + BDB77A76206B3F57001925D0 /* MessagePackStorage.swift in Sources */, 8253223F1EFFCBC700914B55 /* ConvenienceProperties.swift in Sources */, + BDB77A72206B3F57001925D0 /* _MessagePackEncoder.swift in Sources */, + BDB77A5E206B3F57001925D0 /* MessagePackUnkeyedDecodingContainer.swift in Sources */, 8253223E1EFFCBC700914B55 /* ConvenienceInitializers.swift in Sources */, + BDB77A87206B40FF001925D0 /* MessagePackRepresentable.swift in Sources */, + BDB77A6E206B3F57001925D0 /* MessagePackSingleValueEncodingContainer.swift in Sources */, 825322421EFFCBC700914B55 /* Pack.swift in Sources */, + BDB77A82206B3F57001925D0 /* MessagePackEncoder.swift in Sources */, + BDB77A66206B3F57001925D0 /* MessagePackDecoder.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -639,15 +804,22 @@ buildActionMask = 2147483647; files = ( 825322281EFFCBC400914B55 /* ConveniencePropertiesTests.swift in Sources */, + BDB77AA9206B6B14001925D0 /* SingleTypeModels.swift in Sources */, 8253222E1EFFCBC400914B55 /* FalseTests.swift in Sources */, + BDB77A8E206B6ADC001925D0 /* MessagePackDecoderTests.swift in Sources */, 825322291EFFCBC400914B55 /* DescriptionTests.swift in Sources */, 825322361EFFCBC400914B55 /* TrueTests.swift in Sources */, 8253222D1EFFCBC400914B55 /* ExtendedTests.swift in Sources */, 825322321EFFCBC400914B55 /* MapTests.swift in Sources */, 8253222B1EFFCBC400914B55 /* EqualityTests.swift in Sources */, + BDB77AA3206B6B14001925D0 /* OptionalModels.swift in Sources */, 825322341EFFCBC400914B55 /* StringTests.swift in Sources */, 825322311EFFCBC400914B55 /* IntegerTests.swift in Sources */, + BDB77AA6206B6B14001925D0 /* ModelProtocol.swift in Sources */, + BDB77AA0206B6B14001925D0 /* Models.swift in Sources */, + BDB77A9A206B6B14001925D0 /* SingleOptionalTypeModels.swift in Sources */, 825322271EFFCBC400914B55 /* ConvenienceInitializersTests.swift in Sources */, + BDB77A91206B6ADC001925D0 /* MessagePackEncoderTests.swift in Sources */, 8253222C1EFFCBC400914B55 /* ExampleTests.swift in Sources */, 825322301EFFCBC400914B55 /* HashValueTests.swift in Sources */, 825322261EFFCBC400914B55 /* BinaryTests.swift in Sources */, @@ -663,13 +835,24 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + BDB77A61206B3F57001925D0 /* MessagePackKeyedDecodingContainer.swift in Sources */, 8253223D1EFFCBC700914B55 /* Unpack.swift in Sources */, + BDB77A7D206B3F57001925D0 /* MessagePackKeyedEncodingContainer.swift in Sources */, + BDB77A79206B3F57001925D0 /* MessagePackUnkeyedEncodingContainer.swift in Sources */, + BDB77A69206B3F57001925D0 /* MessagePackSingleValueDecodingContainer.swift in Sources */, 8253223C1EFFCBC700914B55 /* Subdata.swift in Sources */, 8253223A1EFFCBC700914B55 /* MessagePack.swift in Sources */, 825322391EFFCBC700914B55 /* LiteralConvertibles.swift in Sources */, + BDB77A75206B3F57001925D0 /* MessagePackStorage.swift in Sources */, 825322381EFFCBC700914B55 /* ConvenienceProperties.swift in Sources */, + BDB77A71206B3F57001925D0 /* _MessagePackEncoder.swift in Sources */, + BDB77A5D206B3F57001925D0 /* MessagePackUnkeyedDecodingContainer.swift in Sources */, 825322371EFFCBC700914B55 /* ConvenienceInitializers.swift in Sources */, + BDB77A86206B40FF001925D0 /* MessagePackRepresentable.swift in Sources */, + BDB77A6D206B3F57001925D0 /* MessagePackSingleValueEncodingContainer.swift in Sources */, 8253223B1EFFCBC700914B55 /* Pack.swift in Sources */, + BDB77A81206B3F57001925D0 /* MessagePackEncoder.swift in Sources */, + BDB77A65206B3F57001925D0 /* MessagePackDecoder.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -678,15 +861,22 @@ buildActionMask = 2147483647; files = ( 825322161EFFCBC400914B55 /* ConveniencePropertiesTests.swift in Sources */, + BDB77AA8206B6B14001925D0 /* SingleTypeModels.swift in Sources */, 8253221C1EFFCBC400914B55 /* FalseTests.swift in Sources */, + BDB77A8D206B6ADC001925D0 /* MessagePackDecoderTests.swift in Sources */, 825322171EFFCBC400914B55 /* DescriptionTests.swift in Sources */, 825322241EFFCBC400914B55 /* TrueTests.swift in Sources */, 8253221B1EFFCBC400914B55 /* ExtendedTests.swift in Sources */, 825322201EFFCBC400914B55 /* MapTests.swift in Sources */, 825322191EFFCBC400914B55 /* EqualityTests.swift in Sources */, + BDB77AA2206B6B14001925D0 /* OptionalModels.swift in Sources */, 825322221EFFCBC400914B55 /* StringTests.swift in Sources */, 8253221F1EFFCBC400914B55 /* IntegerTests.swift in Sources */, + BDB77AA5206B6B14001925D0 /* ModelProtocol.swift in Sources */, + BDB77A9F206B6B14001925D0 /* Models.swift in Sources */, + BDB77A99206B6B14001925D0 /* SingleOptionalTypeModels.swift in Sources */, 825322151EFFCBC400914B55 /* ConvenienceInitializersTests.swift in Sources */, + BDB77A90206B6ADC001925D0 /* MessagePackEncoderTests.swift in Sources */, 8253221A1EFFCBC400914B55 /* ExampleTests.swift in Sources */, 8253221E1EFFCBC400914B55 /* HashValueTests.swift in Sources */, 825322141EFFCBC400914B55 /* BinaryTests.swift in Sources */, diff --git a/Sources/MessagePack/Decoder/MessagePackDecoder.swift b/Sources/MessagePack/Decoder/MessagePackDecoder.swift new file mode 100644 index 0000000..489ddf3 --- /dev/null +++ b/Sources/MessagePack/Decoder/MessagePackDecoder.swift @@ -0,0 +1,74 @@ +// +// MessagePackDecoder.swift +// MessagePack +// +// Created by Andrew Eng on 20/2/18. +// + +import Foundation + +open class MessagePackDecoder { + public init() {} + + open func decode(_ type: T.Type, from data: Data) throws -> T { + let messagePack = try decodeToMessagePack(from: data) + return try decodeMessagePack(type, from: messagePack) + } + + open func decodeToMessagePack(from data: Data) throws -> MessagePackValue { + return try unpackFirst(data) + } + + open func decodeMessagePack(_ type: T.Type, from messagePack: MessagePackValue) throws -> T { + let decoder = _MessagePackDecoder(value: messagePack) + return try T(from: decoder) + } +} + +// MARK: - _MessagePackDecoder + +final class _MessagePackDecoder { + + private let value: MessagePackValue + + init(value: MessagePackValue) { + self.value = value + } +} + +// MARK: Decoder +extension _MessagePackDecoder: Decoder { + + // TODO: Implement Me! + var codingPath: [CodingKey] { return [] } + + // TODO: Implement Me! + var userInfo: [CodingUserInfoKey : Any] { return [:] } + + func container(keyedBy type: Key.Type) throws -> KeyedDecodingContainer { + + guard case let .map(map) = value else { + let msg = "Cannot decode map from \(value)" + let context = DecodingError.Context(codingPath: [], debugDescription: msg) + throw DecodingError.typeMismatch([MessagePackValue: MessagePackValue].self, context) + } + + let container = MessagePackKeyedDecodingContainer(map: map) + return KeyedDecodingContainer(container) + } + + func unkeyedContainer() throws -> UnkeyedDecodingContainer { + + guard case let .array(array) = value else { + let msg = "Cannot decode array from \(value)" + let context = DecodingError.Context(codingPath: [], debugDescription: msg) + throw DecodingError.typeMismatch([MessagePackValue].self, context) + } + + return MessagePackUnkeyedDecodingContainer(array: array) + } + + func singleValueContainer() throws -> SingleValueDecodingContainer { + return MessagePackSingleValueDecodingContainer(value: value) + } +} diff --git a/Sources/MessagePack/Decoder/MessagePackKeyedDecodingContainer.swift b/Sources/MessagePack/Decoder/MessagePackKeyedDecodingContainer.swift new file mode 100644 index 0000000..7656fba --- /dev/null +++ b/Sources/MessagePack/Decoder/MessagePackKeyedDecodingContainer.swift @@ -0,0 +1,215 @@ +// +// MessagePackKeyedDecodingContainer.swift +// MessagePack +// +// Created by Andrew Eng on 20/2/18. +// + +import Foundation + +final class MessagePackKeyedDecodingContainer { + + let map: [MessagePackValue: MessagePackValue] + + init(map: [MessagePackValue: MessagePackValue]) { + self.map = map + } +} + +// MARK: - Helper +extension MessagePackKeyedDecodingContainer { + + private func _decode(_ type: T.Type, forKey key: Key) throws -> T { + let value = try valueForKey(key) + return try _decode(value, type: type) + } + + private func _decode(_ value: MessagePackValue, type: T.Type) throws -> T { + + guard let decoded = T(messagePack: value) else { + let msg = "Cannot decode \(type) from \(value)" + let context = DecodingError.Context(codingPath: [], debugDescription: msg) + throw DecodingError.typeMismatch(type, context) + } + return decoded + } + + private func _decodeIfPresent(_ type: T.Type, forKey key: Key) throws -> T? { + + guard let value = map[.string(key.stringValue)] else { + return nil + } + + if case .`nil` = value { + return nil + } else { + return try _decode(value, type: type) + } + } + + private func _decodeDecodable(_ type: T.Type, forKey key: Key) throws -> T { + let value = try valueForKey(key) + return try _decodeDecodable(value, type: type) + } + + private func _decodeDecodable(_ value: MessagePackValue, type: T.Type) throws -> T { + let decoder = _MessagePackDecoder(value: value) + return try T(from: decoder) + } + + private func _decodeDecodableIfPresent(_ type: T.Type, forKey key: Key) throws -> T? { + + guard let value = map[.string(key.stringValue)] else { + return nil + } + + if case .`nil` = value { + return nil + } else { + return try _decodeDecodable(value, type: type) + } + } + + private func valueForKey(_ key: Key) throws -> MessagePackValue { + + guard let value = map[.string(key.stringValue)] else { + let msg = "Key not found : \(key)" + let context = DecodingError.Context(codingPath: [], debugDescription: msg) + throw DecodingError.keyNotFound(key, context) + } + return value + } +} + +// MARK: - KeyedDecodingContainerProtocol +extension MessagePackKeyedDecodingContainer: KeyedDecodingContainerProtocol { + typealias Key = K + + // TODO: Implement Me! + var codingPath: [CodingKey] { return [] } + + var allKeys: [Key] { + return map.keys.flatMap() { + guard let stringValue = $0.stringValue else { return nil } + return Key(stringValue: stringValue) + } + } + + func contains(_ key: Key) -> Bool { + return map[.string(key.stringValue)] != nil + } + + func decodeNil(forKey key: Key) throws -> Bool { + let value = try valueForKey(key) + return (value == .`nil`) + } + + func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool { return try _decode(type, forKey: key) } + func decode(_ type: Int.Type, forKey key: Key) throws -> Int { return try _decode(type, forKey: key) } + func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 { return try _decode(type, forKey: key) } + func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 { return try _decode(type, forKey: key) } + func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 { return try _decode(type, forKey: key) } + func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 { return try _decode(type, forKey: key) } + func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt { return try _decode(type, forKey: key) } + func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 { return try _decode(type, forKey: key) } + func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 { return try _decode(type, forKey: key) } + func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 { return try _decode(type, forKey: key) } + func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 { return try _decode(type, forKey: key) } + func decode(_ type: Float.Type, forKey key: Key) throws -> Float { return try _decode(type, forKey: key) } + func decode(_ type: Double.Type, forKey key: Key) throws -> Double { return try _decode(type, forKey: key) } + func decode(_ type: String.Type, forKey key: Key) throws -> String { return try _decode(type, forKey: key) } + + func decode(_ type: T.Type, forKey key: Key) throws -> T { + + if T.self == Data.self || T.self == NSData.self { + return try _decode(Data.self, forKey: key) as! T + } else { + return try _decodeDecodable(type, forKey: key) + } + } + + func decodeIfPresent(_ type: Bool.Type, forKey key: Key) throws -> Bool? { + return try _decodeIfPresent(type, forKey: key) + } + func decodeIfPresent(_ type: Int.Type, forKey key: Key) throws -> Int? { + return try _decodeIfPresent(type, forKey: key) + } + func decodeIfPresent(_ type: Int8.Type, forKey key: Key) throws -> Int8? { + return try _decodeIfPresent(type, forKey: key) + } + func decodeIfPresent(_ type: Int16.Type, forKey key: Key) throws -> Int16? { + return try _decodeIfPresent(type, forKey: key) + } + func decodeIfPresent(_ type: Int32.Type, forKey key: Key) throws -> Int32? { + return try _decodeIfPresent(type, forKey: key) + } + func decodeIfPresent(_ type: Int64.Type, forKey key: Key) throws -> Int64? { + return try _decodeIfPresent(type, forKey: key) + } + func decodeIfPresent(_ type: UInt.Type, forKey key: Key) throws -> UInt? { + return try _decodeIfPresent(type, forKey: key) + } + func decodeIfPresent(_ type: UInt8.Type, forKey key: Key) throws -> UInt8? { + return try _decodeIfPresent(type, forKey: key) + } + func decodeIfPresent(_ type: UInt16.Type, forKey key: Key) throws -> UInt16? { + return try _decodeIfPresent(type, forKey: key) + } + func decodeIfPresent(_ type: UInt32.Type, forKey key: Key) throws -> UInt32? { + return try _decodeIfPresent(type, forKey: key) + } + func decodeIfPresent(_ type: UInt64.Type, forKey key: Key) throws -> UInt64? { + return try _decodeIfPresent(type, forKey: key) + } + func decodeIfPresent(_ type: Float.Type, forKey key: Key) throws -> Float? { + return try _decodeIfPresent(type, forKey: key) + } + func decodeIfPresent(_ type: Double.Type, forKey key: Key) throws -> Double? { + return try _decodeIfPresent(type, forKey: key) + } + func decodeIfPresent(_ type: String.Type, forKey key: Key) throws -> String? { + return try _decodeIfPresent(type, forKey: key) + } + + func decodeIfPresent(_ type: T.Type, forKey key: K) throws -> T? { + + if T.self == Data.self || T.self == NSData.self { + return try _decodeIfPresent(Data.self, forKey: key) as! T? + } else { + return try _decodeDecodableIfPresent(type, forKey: key) + } + } + + func nestedContainer(keyedBy type: NestedKey.Type, forKey key: Key) + throws -> KeyedDecodingContainer + { + let value = try valueForKey(key) + + guard case let .map(map) = value else { + let msg = "Cannot decode map from \(value)" + let context = DecodingError.Context(codingPath: [], debugDescription: msg) + throw DecodingError.typeMismatch([MessagePackValue: MessagePackValue].self, context) + } + + let container = MessagePackKeyedDecodingContainer(map: map) + return KeyedDecodingContainer(container) + } + + func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer { + let value = try valueForKey(key) + + guard case let .array(array) = value else { + let msg = "Cannot decode array from \(value)" + let context = DecodingError.Context(codingPath: [], debugDescription: msg) + throw DecodingError.typeMismatch([MessagePackValue].self, context) + } + + return MessagePackUnkeyedDecodingContainer(array: array) + } + + // TODO: Implement Me! + func superDecoder() throws -> Decoder { abort() } + + // TODO: Implement Me! + func superDecoder(forKey key: Key) throws -> Decoder { abort() } +} diff --git a/Sources/MessagePack/Decoder/MessagePackSingleValueDecodingContainer.swift b/Sources/MessagePack/Decoder/MessagePackSingleValueDecodingContainer.swift new file mode 100644 index 0000000..5627873 --- /dev/null +++ b/Sources/MessagePack/Decoder/MessagePackSingleValueDecodingContainer.swift @@ -0,0 +1,70 @@ +// +// MessagePackSingleValueDecodingContainer.swift +// MessagePack +// +// Created by Andrew Eng on 20/2/18. +// + +import Foundation + +final class MessagePackSingleValueDecodingContainer { + + let value: MessagePackValue + + init(value: MessagePackValue) { + self.value = value + } +} + +// MARK: - Helper +extension MessagePackSingleValueDecodingContainer { + + private func _decode(_ type: T.Type) throws -> T { + + guard let value = T(messagePack: self.value) else { + let msg = "Cannot decode \(type) from \(self.value)" + let context = DecodingError.Context(codingPath: [], debugDescription: msg) + throw DecodingError.typeMismatch(type, context) + } + + return value + } + + private func _decodeDecodable(_ type: T.Type) throws -> T { + + let decoder = _MessagePackDecoder(value: value) + return try T(from: decoder) + } +} + +// MARK: - SingleValueDecodingContainer +extension MessagePackSingleValueDecodingContainer: SingleValueDecodingContainer { + + // TODO: Implement Me! + var codingPath: [CodingKey] { return [] } + + func decodeNil() -> Bool { return value == .`nil` } + func decode(_ type: Bool.Type) throws -> Bool { return try _decode(type) } + func decode(_ type: Int.Type) throws -> Int { return try _decode(type) } + func decode(_ type: Int8.Type) throws -> Int8 { return try _decode(type) } + func decode(_ type: Int16.Type) throws -> Int16 { return try _decode(type) } + func decode(_ type: Int32.Type) throws -> Int32 { return try _decode(type) } + func decode(_ type: Int64.Type) throws -> Int64 { return try _decode(type) } + func decode(_ type: UInt.Type) throws -> UInt { return try _decode(type) } + func decode(_ type: UInt8.Type) throws -> UInt8 { return try _decode(type) } + func decode(_ type: UInt16.Type) throws -> UInt16 { return try _decode(type) } + func decode(_ type: UInt32.Type) throws -> UInt32 { return try _decode(type) } + func decode(_ type: UInt64.Type) throws -> UInt64 { return try _decode(type) } + func decode(_ type: Float.Type) throws -> Float { return try _decode(type) } + func decode(_ type: Double.Type) throws -> Double { return try _decode(type) } + func decode(_ type: String.Type) throws -> String { return try _decode(type) } + + func decode(_ type: T.Type) throws -> T { + + if T.self == Data.self || T.self == NSData.self { + return try _decode(Data.self) as! T + } else { + return try _decodeDecodable(type) + } + } +} diff --git a/Sources/MessagePack/Decoder/MessagePackUnkeyedDecodingContainer.swift b/Sources/MessagePack/Decoder/MessagePackUnkeyedDecodingContainer.swift new file mode 100644 index 0000000..de94b87 --- /dev/null +++ b/Sources/MessagePack/Decoder/MessagePackUnkeyedDecodingContainer.swift @@ -0,0 +1,131 @@ +// +// MessagePackUnkeyedDecodingContainer.swift +// MessagePack +// +// Created by Andrew Eng on 20/2/18. +// + +import Foundation + +final class MessagePackUnkeyedDecodingContainer { + + let array: [MessagePackValue] + private(set) var currentIndex: Int + + init(array: [MessagePackValue]) { + self.array = array + self.currentIndex = 0 + } +} + +// MARK: - Helper +extension MessagePackUnkeyedDecodingContainer { + + private func _decode(_ type: T.Type) throws -> T { + try ensureNotAtEnd(type: type) + + guard let value = T(messagePack: array[currentIndex]) else { + let msg = "Cannot decode \(type) from \(array[currentIndex])" + let context = DecodingError.Context(codingPath: [], debugDescription: msg) + throw DecodingError.typeMismatch(type, context) + } + + currentIndex += 1 + return value + } + + private func _decodeDecodable(_ type: T.Type) throws -> T { + try ensureNotAtEnd(type: type) + + let decoder = _MessagePackDecoder(value: array[currentIndex]) + let decoded = try T(from: decoder) + + currentIndex += 1 + return decoded + } + + private func ensureNotAtEnd(type: Any.Type) throws { + + guard !isAtEnd else { + let msg = "Unkeyed container is at end" + let context = DecodingError.Context(codingPath: [], debugDescription: msg) + throw DecodingError.valueNotFound(type, context) + } + } +} + +// MARK: - UnkeyedDecodingContainer +extension MessagePackUnkeyedDecodingContainer: UnkeyedDecodingContainer { + + // TODO: Implement Me! + var codingPath: [CodingKey] { return [] } + + var count: Int? { return array.count } + var isAtEnd: Bool { return (currentIndex == array.count) } + + func decodeNil() throws -> Bool { + try ensureNotAtEnd(type: Bool.self) + + if case .`nil` = array[currentIndex] { + currentIndex += 1 + return true + } else { + return false + } + } + + func decode(_ type: Bool.Type) throws -> Bool { return try _decode(type) } + func decode(_ type: Int.Type) throws -> Int { return try _decode(type) } + func decode(_ type: Int8.Type) throws -> Int8 { return try _decode(type) } + func decode(_ type: Int16.Type) throws -> Int16 { return try _decode(type) } + func decode(_ type: Int32.Type) throws -> Int32 { return try _decode(type) } + func decode(_ type: Int64.Type) throws -> Int64 { return try _decode(type) } + func decode(_ type: UInt.Type) throws -> UInt { return try _decode(type) } + func decode(_ type: UInt8.Type) throws -> UInt8 { return try _decode(type) } + func decode(_ type: UInt16.Type) throws -> UInt16 { return try _decode(type) } + func decode(_ type: UInt32.Type) throws -> UInt32 { return try _decode(type) } + func decode(_ type: UInt64.Type) throws -> UInt64 { return try _decode(type) } + func decode(_ type: Float.Type) throws -> Float { return try _decode(type) } + func decode(_ type: Double.Type) throws -> Double { return try _decode(type) } + func decode(_ type: String.Type) throws -> String { return try _decode(type) } + + func decode(_ type: T.Type) throws -> T where T : Decodable { + + if T.self == Data.self || T.self == NSData.self { + return try _decode(Data.self) as! T + } else { + return try _decodeDecodable(type) + } + } + + func nestedContainer(keyedBy type: NestedKey.Type) + throws -> KeyedDecodingContainer + { + try ensureNotAtEnd(type: [MessagePackValue: MessagePackValue].self) + + guard case let .map(map) = array[currentIndex] else { + let msg = "Cannot decode map from \(array[currentIndex])" + let context = DecodingError.Context(codingPath: [], debugDescription: msg) + throw DecodingError.typeMismatch([MessagePackValue: MessagePackValue].self, context) + } + + let container = MessagePackKeyedDecodingContainer(map: map) + return KeyedDecodingContainer(container) + } + + func nestedUnkeyedContainer() throws -> UnkeyedDecodingContainer { + try ensureNotAtEnd(type: [MessagePackValue].self) + + guard case let .array(array) = array[currentIndex] else { + let msg = "Cannot decode array from \(self.array[currentIndex])" + let context = DecodingError.Context(codingPath: [], debugDescription: msg) + throw DecodingError.typeMismatch([MessagePackValue].self, context) + } + + currentIndex += 1 + return MessagePackUnkeyedDecodingContainer(array: array) + } + + // TODO: Implement Me! + func superDecoder() throws -> Decoder { abort() } +} diff --git a/Sources/MessagePack/Encoder/MessagePackEncoder.swift b/Sources/MessagePack/Encoder/MessagePackEncoder.swift new file mode 100644 index 0000000..17b7d72 --- /dev/null +++ b/Sources/MessagePack/Encoder/MessagePackEncoder.swift @@ -0,0 +1,41 @@ +// +// MessagePackEncoder.swift +// MessagePack +// +// Created by Andrew Eng on 20/2/18. +// + +import Foundation + +open class MessagePackEncoder { + + open var userInfo: [CodingUserInfoKey: Any] = [:] + + public struct KeyedEncodingOptions: OptionSet { + public let rawValue: Int + public init(rawValue: Int) { self.rawValue = rawValue } + + public static let ignoreKeysWithNilValue = KeyedEncodingOptions(rawValue: 1 << 0) + } + open static var defaultKeyedEncodingOptions: KeyedEncodingOptions = [] + open var keyedEncodingOptions = MessagePackEncoder.defaultKeyedEncodingOptions + + public init() {} + + open func encode(_ value: T) throws -> Data { + let messagePack = try encodeToMessagePack(value) + return try encodeMessagePack(messagePack) + } + + open func encodeToMessagePack(_ value: T) throws -> MessagePackValue { + let options = _MessagePackEncoder.Options(keyedEncodingOptions: keyedEncodingOptions, + userInfo: userInfo) + let encoder = _MessagePackEncoder(options: options) + try value.encode(to: encoder) + return encoder.messagePack + } + + open func encodeMessagePack(_ messagePack: MessagePackValue) throws -> Data { + return pack(messagePack) + } +} diff --git a/Sources/MessagePack/Encoder/MessagePackKeyedEncodingContainer.swift b/Sources/MessagePack/Encoder/MessagePackKeyedEncodingContainer.swift new file mode 100644 index 0000000..f2543e9 --- /dev/null +++ b/Sources/MessagePack/Encoder/MessagePackKeyedEncodingContainer.swift @@ -0,0 +1,135 @@ +// +// MessagePackKeyedEncodingContainer.swift +// MessagePack +// +// Created by Andrew Eng on 20/2/18. +// + +import Foundation + +final class MessagePackKeyedEncodingContainer { + + private let storage: MessagePackDictionaryStorage + private let options: _MessagePackEncoder.Options + + init(storage: MessagePackDictionaryStorage, options: _MessagePackEncoder.Options) { + self.storage = storage + self.options = options + } +} + +// MARK: Helper +extension MessagePackKeyedEncodingContainer { + + private func _encode(_ value: T, forKey key: K) throws { + storage[key.stringValue] = value.messagePack + } + + private func _encodeIfPresent(_ value: T?, forKey key: K) throws { + if options.keyedEncodingOptions.contains(.ignoreKeysWithNilValue) && (value == nil) { + return + } + + if let value = value { + try _encode(value, forKey: key) + } else { + storage[key.stringValue] = .`nil` + } + } + + private func _encodeEncodable(_ value: T, forKey key: Key) throws { + let encoder = _MessagePackEncoder(options: options) + try value.encode(to: encoder) + storage[key.stringValue] = encoder.messagePack + } + + private func _encodeEncodableIfPresent(_ value: T?, forKey key: Key) throws { + if options.keyedEncodingOptions.contains(.ignoreKeysWithNilValue) && (value == nil) { + return + } + + if let value = value { + try _encodeEncodable(value, forKey: key) + } else { + storage[key.stringValue] = .`nil` + } + } +} + +// MARK: - KeyedEncodingContainerProtocols +extension MessagePackKeyedEncodingContainer: KeyedEncodingContainerProtocol { + typealias Key = K + + // TODO: Implement Me! + var codingPath: [CodingKey] { return [] } + + func encodeNil(forKey key: Key) throws { storage[key.stringValue] = .`nil` } + func encode(_ value: Bool, forKey key: Key) throws { try _encode(value, forKey: key) } + func encode(_ value: Int, forKey key: Key) throws { try _encode(value, forKey: key) } + func encode(_ value: Int8, forKey key: Key) throws { try _encode(value, forKey: key) } + func encode(_ value: Int16, forKey key: Key) throws { try _encode(value, forKey: key) } + func encode(_ value: Int32, forKey key: Key) throws { try _encode(value, forKey: key) } + func encode(_ value: Int64, forKey key: Key) throws { try _encode(value, forKey: key) } + func encode(_ value: UInt, forKey key: Key) throws { try _encode(value, forKey: key) } + func encode(_ value: UInt8, forKey key: Key) throws { try _encode(value, forKey: key) } + func encode(_ value: UInt16, forKey key: Key) throws { try _encode(value, forKey: key) } + func encode(_ value: UInt32, forKey key: Key) throws { try _encode(value, forKey: key) } + func encode(_ value: UInt64, forKey key: Key) throws { try _encode(value, forKey: key) } + func encode(_ value: Float, forKey key: Key) throws { try _encode(value, forKey: key) } + func encode(_ value: Double, forKey key: Key) throws { try _encode(value, forKey: key) } + func encode(_ value: String, forKey key: Key) throws { try _encode(value, forKey: key) } + + func encode(_ value: T, forKey key: Key) throws { + + if T.self == Data.self || T.self == NSData.self { + try _encode(value as! Data, forKey: key) + } else { + try _encodeEncodable(value, forKey: key) + } + } + + func encodeIfPresent(_ value: Bool?, forKey key: Key) throws { try _encodeIfPresent(value, forKey: key) } + func encodeIfPresent(_ value: Int?, forKey key: Key) throws { try _encodeIfPresent(value, forKey: key) } + func encodeIfPresent(_ value: Int8?, forKey key: Key) throws { try _encodeIfPresent(value, forKey: key) } + func encodeIfPresent(_ value: Int16?, forKey key: Key) throws { try _encodeIfPresent(value, forKey: key) } + func encodeIfPresent(_ value: Int32?, forKey key: Key) throws { try _encodeIfPresent(value, forKey: key) } + func encodeIfPresent(_ value: Int64?, forKey key: Key) throws { try _encodeIfPresent(value, forKey: key) } + func encodeIfPresent(_ value: UInt?, forKey key: Key) throws { try _encodeIfPresent(value, forKey: key) } + func encodeIfPresent(_ value: UInt8?, forKey key: Key) throws { try _encodeIfPresent(value, forKey: key) } + func encodeIfPresent(_ value: UInt16?, forKey key: Key) throws { try _encodeIfPresent(value, forKey: key) } + func encodeIfPresent(_ value: UInt32?, forKey key: Key) throws { try _encodeIfPresent(value, forKey: key) } + func encodeIfPresent(_ value: UInt64?, forKey key: Key) throws { try _encodeIfPresent(value, forKey: key) } + func encodeIfPresent(_ value: Float?, forKey key: Key) throws { try _encodeIfPresent(value, forKey: key) } + func encodeIfPresent(_ value: Double?, forKey key: Key) throws { try _encodeIfPresent(value, forKey: key) } + func encodeIfPresent(_ value: String?, forKey key: Key) throws { try _encodeIfPresent(value, forKey: key) } + + func encodeIfPresent(_ value: T?, forKey key: Key) throws { + + if T.self == Data.self || T.self == NSData.self { + try _encodeIfPresent(value as! Data?, forKey: key) + } else { + try _encodeEncodableIfPresent(value, forKey: key) + } + } + + func nestedContainer(keyedBy keyType: NestedKey.Type, forKey key: Key) + -> KeyedEncodingContainer + { + let storage = MessagePackDictionaryStorage() + self.storage[key.stringValue] = storage + let container = MessagePackKeyedEncodingContainer(storage: storage, options: options) + return KeyedEncodingContainer(container) + } + + func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer { + let storage = MessagePackArrayStorage() + self.storage[key.stringValue] = storage + return MessagePackUnkeyedEncodingContainer(storage: storage, options: options) + } + + // TODO: Implement Me! + func superEncoder() -> Encoder { abort() } + + // TODO: Implement Me! + func superEncoder(forKey key: Key) -> Encoder { abort() } +} diff --git a/Sources/MessagePack/Encoder/MessagePackSingleValueEncodingContainer.swift b/Sources/MessagePack/Encoder/MessagePackSingleValueEncodingContainer.swift new file mode 100644 index 0000000..9872f2d --- /dev/null +++ b/Sources/MessagePack/Encoder/MessagePackSingleValueEncodingContainer.swift @@ -0,0 +1,65 @@ +// +// MessagePackSingleValueEncodingContainer.swift +// MessagePack +// +// Created by Andrew Eng on 20/2/18. +// + +import Foundation + +final class MessagePackSingleValueEncodingContainer { + + private let storage: MessagePackValueStorage + private let options: _MessagePackEncoder.Options + + init(storage: MessagePackValueStorage, options: _MessagePackEncoder.Options) { + self.storage = storage + self.options = options + } +} + +// MARK: - Helper +extension MessagePackSingleValueEncodingContainer { + + private func _encode(_ value: T) throws { + storage.value = value.messagePack + } + + private func _encodeEncodable(_ value: T) throws { + let encoder = _MessagePackEncoder(options: options) + try value.encode(to: encoder) + storage.value = encoder.messagePack + } +} + +// MARK: - SingleValueEncodingContainer +extension MessagePackSingleValueEncodingContainer: SingleValueEncodingContainer { + + // TODO: Implement Me! + var codingPath: [CodingKey] { return [] } + + func encodeNil() throws { storage.value = .`nil` } + func encode(_ value: Bool) throws { try _encode(value) } + func encode(_ value: Int) throws { try _encode(value) } + func encode(_ value: Int8) throws { try _encode(value) } + func encode(_ value: Int16) throws { try _encode(value) } + func encode(_ value: Int32) throws { try _encode(value) } + func encode(_ value: Int64) throws { try _encode(value) } + func encode(_ value: UInt) throws { try _encode(value) } + func encode(_ value: UInt8) throws { try _encode(value) } + func encode(_ value: UInt16) throws { try _encode(value) } + func encode(_ value: UInt32) throws { try _encode(value) } + func encode(_ value: UInt64) throws { try _encode(value) } + func encode(_ value: Float) throws { try _encode(value) } + func encode(_ value: Double) throws { try _encode(value) } + func encode(_ value: String) throws { try _encode(value) } + + func encode(_ value: T) throws { + + if T.self == Data.self || T.self == NSData.self { + try _encode(value as! Data) + } else { + try _encodeEncodable(value) + } + } +} diff --git a/Sources/MessagePack/Encoder/MessagePackStorage.swift b/Sources/MessagePack/Encoder/MessagePackStorage.swift new file mode 100644 index 0000000..bb91928 --- /dev/null +++ b/Sources/MessagePack/Encoder/MessagePackStorage.swift @@ -0,0 +1,73 @@ +// +// MessagePackStorage.swift +// MessagePack +// +// Created by Andrew Eng on 20/2/18. +// + +import Foundation + +protocol MessagePackStorage { + var messagePack: MessagePackValue { get } +} + +final class MessagePackValueStorage: MessagePackStorage { + var value: MessagePackValue + + init(_ value: MessagePackValue) { + self.value = value + } + + convenience init() { + self.init(.`nil`) + } + + var messagePack: MessagePackValue { + return value + } +} + +final class MessagePackDictionaryStorage: MessagePackStorage { + private var map: [String: MessagePackStorage] = [:] + + var messagePack: MessagePackValue { + var map = [MessagePackValue: MessagePackValue]() + self.map.forEach { map[.string($0)] = $1.messagePack } + return .map(map) + } + + subscript(key: String) -> MessagePackStorage? { + get { return map[key] } + set { map[key] = newValue } + } + + subscript(key: String) -> MessagePackValue? { + get { return map[key]?.messagePack } + set { + if let newValue = newValue { + map[key] = MessagePackValueStorage(newValue) + } else { + map[key] = nil + } + } + } +} + +final class MessagePackArrayStorage: MessagePackStorage { + private var array: [MessagePackStorage] = [] + + var count: Int { return array.count } + + var messagePack: MessagePackValue { + let array = self.array.map { $0.messagePack } + return .array(array) + } + + func append(_ storage: MessagePackStorage) { + array.append(storage) + } + + func append(_ messagePack: MessagePackValue) { + array.append(MessagePackValueStorage(messagePack)) + } +} diff --git a/Sources/MessagePack/Encoder/MessagePackUnkeyedEncodingContainer.swift b/Sources/MessagePack/Encoder/MessagePackUnkeyedEncodingContainer.swift new file mode 100644 index 0000000..223f7ae --- /dev/null +++ b/Sources/MessagePack/Encoder/MessagePackUnkeyedEncodingContainer.swift @@ -0,0 +1,83 @@ +// +// MessagePackUnkeyedEncodingContainer.swift +// MessagePack +// +// Created by Andrew Eng on 20/2/18. +// + +import Foundation + +final class MessagePackUnkeyedEncodingContainer { + + private let storage: MessagePackArrayStorage + private let options: _MessagePackEncoder.Options + + init(storage: MessagePackArrayStorage, options: _MessagePackEncoder.Options) { + self.storage = storage + self.options = options + } +} + +// MARK: - Helper +extension MessagePackUnkeyedEncodingContainer { + + private func _encode(_ value: T) throws { + storage.append(value.messagePack) + } + + private func _encodeEncodable(_ value: T) throws { + let encoder = _MessagePackEncoder(options: options) + try value.encode(to: encoder) + storage.append(encoder.messagePack) + } +} + +// MARK: - UnkeyedEncodingContainer +extension MessagePackUnkeyedEncodingContainer: UnkeyedEncodingContainer { + + // TODO: Implement Me! + var codingPath: [CodingKey] { return [] } + + var count: Int { return storage.count } + + func encodeNil() throws { storage.append(.`nil`) } + func encode(_ value: Bool) throws { try _encode(value) } + func encode(_ value: Int) throws { try _encode(value) } + func encode(_ value: Int8) throws { try _encode(value) } + func encode(_ value: Int16) throws { try _encode(value) } + func encode(_ value: Int32) throws { try _encode(value) } + func encode(_ value: Int64) throws { try _encode(value) } + func encode(_ value: UInt) throws { try _encode(value) } + func encode(_ value: UInt8) throws { try _encode(value) } + func encode(_ value: UInt16) throws { try _encode(value) } + func encode(_ value: UInt32) throws { try _encode(value) } + func encode(_ value: UInt64) throws { try _encode(value) } + func encode(_ value: Float) throws { try _encode(value) } + func encode(_ value: Double) throws { try _encode(value) } + func encode(_ value: String) throws { try _encode(value) } + + func encode(_ value: T) throws { + + if T.self == Data.self || T.self == NSData.self { + try _encode(value as! Data) + } else { + try _encodeEncodable(value) + } + } + + func nestedContainer(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer { + let storage = MessagePackDictionaryStorage() + self.storage.append(storage) + let container = MessagePackKeyedEncodingContainer(storage: storage, options: options) + return KeyedEncodingContainer(container) + } + + func nestedUnkeyedContainer() -> UnkeyedEncodingContainer { + let storage = MessagePackArrayStorage() + self.storage.append(storage) + return MessagePackUnkeyedEncodingContainer(storage: storage, options: options) + } + + // TODO: Implement Me! + func superEncoder() -> Encoder { abort() } +} diff --git a/Sources/MessagePack/Encoder/_MessagePackEncoder.swift b/Sources/MessagePack/Encoder/_MessagePackEncoder.swift new file mode 100644 index 0000000..43b7009 --- /dev/null +++ b/Sources/MessagePack/Encoder/_MessagePackEncoder.swift @@ -0,0 +1,87 @@ +// +// _MessagePackEncoder.swift +// MessagePack +// +// Created by Andrew Eng on 27/2/18. +// + +import Foundation + +// MARK: - _MessagePackEncoder +final class _MessagePackEncoder { + + var messagePack: MessagePackValue { + return storage?.messagePack ?? .`nil` + } + + struct Options { + let keyedEncodingOptions: MessagePackEncoder.KeyedEncodingOptions + let userInfo: [CodingUserInfoKey: Any] + } + + private let options: Options + private var storage: MessagePackStorage? + + init(options: Options) { + self.options = options + } + + private func existingStorage(type: T.Type) -> T? { + guard let storage = storage else { return nil } + + guard let requiredStorage = storage as? T else { + fatalError() + } + + return requiredStorage + } +} + +// MARK: Encoder +extension _MessagePackEncoder: Encoder { + + // TODO: Implement Me! + var codingPath: [CodingKey] { return [] } + + var userInfo: [CodingUserInfoKey : Any] { return options.userInfo } + + func container(keyedBy type: Key.Type) -> KeyedEncodingContainer { + let storage: MessagePackDictionaryStorage + + if let existingStorage = existingStorage(type: MessagePackDictionaryStorage.self) { + storage = existingStorage + } else { + storage = MessagePackDictionaryStorage() + self.storage = storage + } + + let container = MessagePackKeyedEncodingContainer(storage: storage, options: options) + return KeyedEncodingContainer(container) + } + + func unkeyedContainer() -> UnkeyedEncodingContainer { + let storage: MessagePackArrayStorage + + if let existingStorage = existingStorage(type: MessagePackArrayStorage.self) { + storage = existingStorage + } else { + storage = MessagePackArrayStorage() + self.storage = storage + } + + return MessagePackUnkeyedEncodingContainer(storage: storage, options: options) + } + + func singleValueContainer() -> SingleValueEncodingContainer { + let storage: MessagePackValueStorage + + if let existingStorage = existingStorage(type: MessagePackValueStorage.self) { + storage = existingStorage + } else { + storage = MessagePackValueStorage() + self.storage = storage + } + + return MessagePackSingleValueEncodingContainer(storage: storage, options: options) + } +} diff --git a/Sources/MessagePack/MessagePackRepresentable.swift b/Sources/MessagePack/MessagePackRepresentable.swift new file mode 100644 index 0000000..1ef5a9d --- /dev/null +++ b/Sources/MessagePack/MessagePackRepresentable.swift @@ -0,0 +1,119 @@ +// +// MessagePackRepresentable.swift +// MessagePack +// +// Created by Andrew Eng on 20/2/18. +// + +import Foundation + +protocol MessagePackRepresentable { + init?(messagePack: MessagePackValue) + var messagePack: MessagePackValue { get } +} + +extension Bool: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.boolValue else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} +extension Int: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.intValue else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} +extension Int8: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.int8Value else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} +extension Int16: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.int16Value else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} +extension Int32: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.int32Value else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} +extension Int64: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.int64Value else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} +extension UInt: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.uintValue else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} +extension UInt8: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.uint8Value else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} +extension UInt16: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.uint16Value else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} +extension UInt32: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.uint32Value else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} +extension UInt64: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.uint64Value else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} +extension Float: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.floatValue else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} +extension Double: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.doubleValue else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} +extension String: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.stringValue else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} +extension Data: MessagePackRepresentable { + public init?(messagePack: MessagePackValue) { + guard let value = messagePack.dataValue else { return nil } + self = value + } + var messagePack: MessagePackValue { return MessagePackValue(self) } +} diff --git a/Tests/MessagePackTests/Codable/MessagePackDecoderTests.swift b/Tests/MessagePackTests/Codable/MessagePackDecoderTests.swift new file mode 100644 index 0000000..da6dd5f --- /dev/null +++ b/Tests/MessagePackTests/Codable/MessagePackDecoderTests.swift @@ -0,0 +1,376 @@ +// +// MessagePackDecoderTests.swift +// MessagePackTests +// +// Created by Andrew Eng on 21/2/18. + +import Foundation +import XCTest +@testable import MessagePack + +class MessagePackDecoderTests: XCTestCase { + + private var decoder: MessagePackDecoder! + + override func setUp() { + super.setUp() + decoder = MessagePackDecoder() + } + + override func tearDown() { + decoder = nil + super.tearDown() + } +} + +// MARK: - Single Type Models +extension MessagePackDecoderTests { + + func testShouldDecodeNilModel() { + let model = NilModel() + _testDecode(model: model) + } + func testShouldDecodeBoolModel() { + let model = BoolModel(value: true) + _testDecode(model: model) + } + func testShouldDecodeIntModel() { + let model = IntModel(value: -42) + _testDecode(model: model) + } + func testShouldDecodeInt8Model() { + let model = Int8Model(value: -42) + _testDecode(model: model) + } + func testShouldDecodeInt16Model() { + let model = Int16Model(value: -42) + _testDecode(model: model) + } + func testShouldDecodeInt32Model() { + let model = Int32Model(value: -42) + _testDecode(model: model) + } + func testShouldDecodeInt64Model() { + let model = Int64Model(value: -42) + _testDecode(model: model) + } + func testShouldDecodeUIntModel() { + let model = UIntModel(value: 42) + _testDecode(model: model) + } + func testShouldDecodeUInt8Model() { + let model = UInt8Model(value: 42) + _testDecode(model: model) + } + func testShouldDecodeUInt16Model() { + let model = UInt16Model(value: 42) + _testDecode(model: model) + } + func testShouldDecodeUInt32Model() { + let model = UInt32Model(value: 42) + _testDecode(model: model) + } + func testShouldDecodeUInt64Model() { + let model = UInt64Model(value: 42) + _testDecode(model: model) + } + func testShouldDecodeFloatModel() { + let model = FloatModel(value: 3.14) + _testDecode(model: model) + } + func testShouldDecodeDoubleModel() { + let model = DoubleModel(value: 3.14) + _testDecode(model: model) + } + func testShouldDecodeStringModel() { + let model = StringModel(value: "a") + _testDecode(model: model) + } + func testShouldDecodeDataModel() { + let model = DataModel(value: Data(bytes: [0x42, 0x43, 0x44])) + _testDecode(model: model) + } + func testShouldDecodeArrayModel() { + let model = ArrayModel(value: ["a", "b", "c"]) + _testDecode(model: model) + } + func testShouldDecodeMapModel() { + let model = MapModel(value: ["a": 42, "b": 43]) + _testDecode(model: model) + } +} + +// MARK: - SingleOptionalTypeModel +extension MessagePackDecoderTests { + + func testShouldDecodeOptionalBoolModel() { + let model = OptionalBoolModel(value: true) + _testDecode(model: model) + } + func testShouldDecodeOptionalIntModel() { + let model = OptionalIntModel(value: -42) + _testDecode(model: model) + } + func testShouldDecodeOptionalInt8Model() { + let model = OptionalInt8Model(value: -42) + _testDecode(model: model) + } + func testShouldDecodeOptionalInt16Model() { + let model = OptionalInt16Model(value: -42) + _testDecode(model: model) + } + func testShouldDecodeOptionalInt32Model() { + let model = OptionalInt32Model(value: -42) + _testDecode(model: model) + } + func testShouldDecodeOptionalInt64Model() { + let model = OptionalInt64Model(value: -42) + _testDecode(model: model) + } + func testShouldDecodeOptionalUIntModel() { + let model = OptionalUIntModel(value: 42) + _testDecode(model: model) + } + func testShouldDecodeOptionalUInt8Model() { + let model = OptionalUInt8Model(value: 42) + _testDecode(model: model) + } + func testShouldDecodeOptionalUInt16Model() { + let model = OptionalUInt16Model(value: 42) + _testDecode(model: model) + } + func testShouldDecodeOptionalUInt32Model() { + let model = OptionalUInt32Model(value: 42) + _testDecode(model: model) + } + func testShouldDecodeOptionalUInt64Model() { + let model = OptionalUInt64Model(value: 42) + _testDecode(model: model) + } + func testShouldDecodeOptionalFloatModel() { + let model = OptionalFloatModel(value: 3.14) + _testDecode(model: model) + } + func testShouldDecodeOptionalDoubleModel() { + let model = OptionalDoubleModel(value: 3.14) + _testDecode(model: model) + } + func testShouldDecodeOptionalStringModel() { + let model = OptionalStringModel(value: "a") + _testDecode(model: model) + } + func testShouldDecodeOptionalDataModel() { + let model = OptionalDataModel(value: Data(bytes: [0x42, 0x43, 0x44])) + _testDecode(model: model) + } + func testShouldDecodeOptionalArrayModel() { + let model = OptionalArrayModel(value: ["a", "b", "c"]) + _testDecode(model: model) + } + func testShouldDecodeOptionalMapModel() { + let model = OptionalMapModel(value: ["a": 42, "b": 43]) + _testDecode(model: model) + } +} + +// MARK: Empty SingleOptionalTypeModel +extension MessagePackDecoderTests { + + func testShouldDecodeEmptyOptionalBoolModel() { + let model = OptionalBoolModel(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalIntModel() { + let model = OptionalIntModel(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalInt8Model() { + let model = OptionalInt8Model(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalInt16Model() { + let model = OptionalInt16Model(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalInt32Model() { + let model = OptionalInt32Model(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalInt64Model() { + let model = OptionalInt64Model(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalUIntModel() { + let model = OptionalUIntModel(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalUInt8Model() { + let model = OptionalUInt8Model(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalUInt16Model() { + let model = OptionalUInt16Model(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalUInt32Model() { + let model = OptionalUInt32Model(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalUInt64Model() { + let model = OptionalUInt64Model(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalFloatModel() { + let model = OptionalFloatModel(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalDoubleModel() { + let model = OptionalDoubleModel(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalStringModel() { + let model = OptionalStringModel(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalDataModel() { + let model = OptionalDataModel(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalArrayModel() { + let model = OptionalArrayModel(value: nil) + _testDecode(model: model) + } + func testShouldDecodeEmptyOptionalMapModel() { + let model = OptionalMapModel(value: nil) + _testDecode(model: model) + } +} + +// MARK: SingleOptionalTypeModel with empty map +extension MessagePackDecoderTests { + + func testShouldDecodeOptionalBoolModelWithEmptyMap() { + let model = OptionalBoolModel(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalIntModelWithEmptyMap() { + let model = OptionalIntModel(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalInt8ModelWithEmptyMap() { + let model = OptionalInt8Model(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalInt16ModelWithEmptyMap() { + let model = OptionalInt16Model(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalInt32ModelWithEmptyMap() { + let model = OptionalInt32Model(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalInt64ModelWithEmptyMap() { + let model = OptionalInt64Model(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalUIntModelWithEmptyMap() { + let model = OptionalUIntModel(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalUInt8ModelWithEmptyMap() { + let model = OptionalUInt8Model(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalUInt16ModelWithEmptyMap() { + let model = OptionalUInt16Model(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalUInt32ModelWithEmptyMap() { + let model = OptionalUInt32Model(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalUInt64ModelWithEmptyMap() { + let model = OptionalUInt64Model(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalFloatModelWithEmptyMap() { + let model = OptionalFloatModel(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalDoubleModelWithEmptyMap() { + let model = OptionalDoubleModel(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalStringModelWithEmptyMap() { + let model = OptionalStringModel(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalDataModelWithEmptyMap() { + let model = OptionalDataModel(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalArrayModelWithEmptyMap() { + let model = OptionalArrayModel(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } + func testShouldDecodeOptionalMapModelWithEmptyMap() { + let model = OptionalMapModel(value: nil) + _testDecode(model: model, messagePack: .map([:])) + } +} + +// MARK: - Models +extension MessagePackDecoderTests { + + func testShouldDecodeModel() { + let model = Car.generate(seed: 42) + _testDecode(model: model) + } + + func testShouldDecodeNestedModel() { + let model = CarShop.generate(seed: 42) + _testDecode(model: model) + } + + func testShouldDecodeOptionalModel() { + let model = OptionalCar.generate(seed: 42) + _testDecode(model: model) + } + + func testShouldDecodeOptionalNestedModel() { + let model = OptionalCarShop.generate(seed: 42) + _testDecode(model: model) + } + + func testShouldDecodeEmptyOptionalModel() { + let model = OptionalCar.empty() + _testDecode(model: model) + } + + func testShouldDecodeEmptyOptionalNestedModel() { + let model = OptionalCarShop.empty() + _testDecode(model: model) + } + + func testShouldDecodeOptionalNestedModelWithEmptyMap() { + let model = OptionalCarShop.empty() + _testDecode(model: model, messagePack: .map([:])) + } +} + +// MARK: - Utilities +extension MessagePackDecoderTests { + + private func _testDecode(model: T) { + _testDecode(model: model, messagePack: model.encoded) + } + + private func _testDecode(model: T, messagePack: MessagePackValue) { + do { + let decoded = try decoder.decodeMessagePack(T.self, from: messagePack) + XCTAssertEqual(decoded, model) + } catch { + XCTAssertNil(error) + } + } +} diff --git a/Tests/MessagePackTests/Codable/MessagePackEncoderTests.swift b/Tests/MessagePackTests/Codable/MessagePackEncoderTests.swift new file mode 100644 index 0000000..db99d87 --- /dev/null +++ b/Tests/MessagePackTests/Codable/MessagePackEncoderTests.swift @@ -0,0 +1,491 @@ +// +// MessagePackEncoderTests.swift +// MessagePackTests +// +// Created by Andrew Eng on 21/2/18. +// + +import Foundation +import XCTest +@testable import MessagePack + +class MessagePackEncoderTests: XCTestCase { + + private var encoder: MessagePackEncoder! + private var decoder: MessagePackDecoder! + + override func setUp() { + super.setUp() + encoder = MessagePackEncoder() + decoder = MessagePackDecoder() + } + + override func tearDown() { + decoder = nil + encoder = nil + super.tearDown() + } +} + +// MARK: - SingleTypeModel +extension MessagePackEncoderTests { + + func testShouldEncodeBoolModel() { + let model = BoolModel(value: true) + _testEncode(model: model) + } + func testShouldEncodeIntModel() { + let model = IntModel(value: -42) + _testEncode(model: model) + } + func testShouldEncodeInt8Model() { + let model = Int8Model(value: -42) + _testEncode(model: model) + } + func testShouldEncodeInt16Model() { + let model = Int16Model(value: -42) + _testEncode(model: model) + } + func testShouldEncodeInt32Model() { + let model = Int32Model(value: -42) + _testEncode(model: model) + } + func testShouldEncodeInt64Model() { + let model = Int64Model(value: -42) + _testEncode(model: model) + } + func testShouldEncodeUIntModel() { + let model = UIntModel(value: 42) + _testEncode(model: model) + } + func testShouldEncodeUInt8Model() { + let model = UInt8Model(value: 42) + _testEncode(model: model) + } + func testShouldEncodeUInt16Model() { + let model = UInt16Model(value: 42) + _testEncode(model: model) + } + func testShouldEncodeUInt32Model() { + let model = UInt32Model(value: 42) + _testEncode(model: model) + } + func testShouldEncodeUInt64Model() { + let model = UInt64Model(value: 42) + _testEncode(model: model) + } + func testShouldEncodeFloatModel() { + let model = FloatModel(value: 3.14) + _testEncode(model: model) + } + func testShouldEncodeDoubleModel() { + let model = DoubleModel(value: 3.14) + _testEncode(model: model) + } + func testShouldEncodeStringModel() { + let model = StringModel(value: "a") + _testEncode(model: model) + } + func testShouldEncodeDataModel() { + let model = DataModel(value: Data(bytes: [0x42, 0x43, 0x44])) + _testEncode(model: model) + } + func testShouldEncodeArrayModel() { + let model = ArrayModel(value: ["a", "b", "c"]) + _testEncode(model: model) + } + func testShouldEncodeMapModel() { + let model = MapModel(value: ["a": 42, "b": 43]) + _testEncode(model: model) + } +} + +// MARK: - SingleOptionalTypeModel +extension MessagePackEncoderTests { + + func testShouldEncodeOptionalBoolModel() { + let model = OptionalBoolModel(value: true) + _testEncode(model: model) + } + func testShouldEncodeOptionalIntModel() { + let model = OptionalIntModel(value: -42) + _testEncode(model: model) + } + func testShouldEncodeOptionalInt8Model() { + let model = OptionalInt8Model(value: -42) + _testEncode(model: model) + } + func testShouldEncodeOptionalInt16Model() { + let model = OptionalInt16Model(value: -42) + _testEncode(model: model) + } + func testShouldEncodeOptionalInt32Model() { + let model = OptionalInt32Model(value: -42) + _testEncode(model: model) + } + func testShouldEncodeOptionalInt64Model() { + let model = OptionalInt64Model(value: -42) + _testEncode(model: model) + } + func testShouldEncodeOptionalUIntModel() { + let model = OptionalUIntModel(value: 42) + _testEncode(model: model) + } + func testShouldEncodeOptionalUInt8Model() { + let model = OptionalUInt8Model(value: 42) + _testEncode(model: model) + } + func testShouldEncodeOptionalUInt16Model() { + let model = OptionalUInt16Model(value: 42) + _testEncode(model: model) + } + func testShouldEncodeOptionalUInt32Model() { + let model = OptionalUInt32Model(value: 42) + _testEncode(model: model) + } + func testShouldEncodeOptionalUInt64Model() { + let model = OptionalUInt64Model(value: 42) + _testEncode(model: model) + } + func testShouldEncodeOptionalFloatModel() { + let model = OptionalFloatModel(value: 3.14) + _testEncode(model: model) + } + func testShouldEncodeOptionalDoubleModel() { + let model = OptionalDoubleModel(value: 3.14) + _testEncode(model: model) + } + func testShouldEncodeOptionalStringModel() { + let model = OptionalStringModel(value: "a") + _testEncode(model: model) + } + func testShouldEncodeOptionalDataModel() { + let model = OptionalDataModel(value: Data(bytes: [0x42, 0x43, 0x44])) + _testEncode(model: model) + } + func testShouldEncodeOptionalArrayModel() { + let model = OptionalArrayModel(value: ["a", "b", "c"]) + _testEncode(model: model) + } + func testShouldEncodeOptionalMapModel() { + let model = OptionalMapModel(value: ["a": 42, "b": 43]) + _testEncode(model: model) + } + + // MARK: Empty + + func testShouldEncodeEmptyOptionalBoolModel() { + let model = OptionalBoolModel(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalIntModel() { + let model = OptionalIntModel(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalInt8Model() { + let model = OptionalInt8Model(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalInt16Model() { + let model = OptionalInt16Model(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalInt32Model() { + let model = OptionalInt32Model(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalInt64Model() { + let model = OptionalInt64Model(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalUIntModel() { + let model = OptionalUIntModel(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalUInt8Model() { + let model = OptionalUInt8Model(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalUInt16Model() { + let model = OptionalUInt16Model(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalUInt32Model() { + let model = OptionalUInt32Model(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalUInt64Model() { + let model = OptionalUInt64Model(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalFloatModel() { + let model = OptionalFloatModel(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalDoubleModel() { + let model = OptionalDoubleModel(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalStringModel() { + let model = OptionalStringModel(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalDataModel() { + let model = OptionalDataModel(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalArrayModel() { + let model = OptionalArrayModel(value: nil) + _testEncode(model: model) + } + func testShouldEncodeEmptyOptionalMapModel() { + let model = OptionalMapModel(value: nil) + _testEncode(model: model) + } +} + +// MARK: - SingleOptionalTypeModel ignore key with nil value +extension MessagePackEncoderTests { + + func testShouldNotIgnoreKeyForOptionalBoolModel() { + let model = OptionalBoolModel(value: true) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalIntModel() { + let model = OptionalIntModel(value: -42) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalInt8Model() { + let model = OptionalInt8Model(value: -42) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalInt16Model() { + let model = OptionalInt16Model(value: -42) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalInt32Model() { + let model = OptionalInt32Model(value: -42) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalInt64Model() { + let model = OptionalInt64Model(value: -42) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalUIntModel() { + let model = OptionalUIntModel(value: 42) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalUInt8Model() { + let model = OptionalUInt8Model(value: 42) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalUInt16Model() { + let model = OptionalUInt16Model(value: 42) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalUInt32Model() { + let model = OptionalUInt32Model(value: 42) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalUInt64Model() { + let model = OptionalUInt64Model(value: 42) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalFloatModel() { + let model = OptionalFloatModel(value: 3.14) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalDoubleModel() { + let model = OptionalDoubleModel(value: 3.14) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalStringModel() { + let model = OptionalStringModel(value: "a") + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalDataModel() { + let model = OptionalDataModel(value: Data(bytes: [0x42, 0x43, 0x44])) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalArrayModel() { + let model = OptionalArrayModel(value: ["a", "b", "c"]) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldNotIgnoreKeyForOptionalMapModel() { + let model = OptionalMapModel(value: ["a": 42, "b": 43]) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + + // MARK: Empty + + func testShouldIgnoreKeyForEmptyOptionalBoolModel() { + let model = OptionalBoolModel(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalIntModel() { + let model = OptionalIntModel(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalInt8Model() { + let model = OptionalInt8Model(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalInt16Model() { + let model = OptionalInt16Model(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalInt32Model() { + let model = OptionalInt32Model(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalInt64Model() { + let model = OptionalInt64Model(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalUIntModel() { + let model = OptionalUIntModel(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalUInt8Model() { + let model = OptionalUInt8Model(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalUInt16Model() { + let model = OptionalUInt16Model(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalUInt32Model() { + let model = OptionalUInt32Model(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalUInt64Model() { + let model = OptionalUInt64Model(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalFloatModel() { + let model = OptionalFloatModel(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalDoubleModel() { + let model = OptionalDoubleModel(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalStringModel() { + let model = OptionalStringModel(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalDataModel() { + let model = OptionalDataModel(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalArrayModel() { + let model = OptionalArrayModel(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalMapModel() { + let model = OptionalMapModel(value: nil) + _testEncodeIgnoringKeysWithNilValue(model: model) + } +} + +// MARK: - Models +extension MessagePackEncoderTests { + + // MARK: Model + + func testShouldEncodeModel() { + let model = Car.generate(seed: 42) + _testEncode(model: model) + } + func testShouldEncodeOptionalModelWithValue() { + let model = OptionalCar.generate(seed: 42) + _testEncode(model: model) + } + func testShouldEncodeOptionalModelWithNil() { + let model = OptionalCar.empty() + _testEncode(model: model) + } + func testShouldNotIgnoreKeyForOptionalModel() { + let model = OptionalCar.generate(seed: 42) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalModel() { + let model = OptionalCar.empty() + _testEncodeIgnoringKeysWithNilValue(model: model) + } + + // MARK: Nested Model + + func testShouldEncodeNestedModel() { + let model = CarShop.generate(seed: 42) + _testEncode(model: model) + } + func testShouldEncodeOptionalNestedModelWithValue() { + let model = OptionalCarShop.generate(seed: 42) + _testEncode(model: model) + } + func testShouldEncodeOptionalNestedModelWithNil() { + let model = OptionalCarShop.empty() + _testEncode(model: model) + } + func testShouldNotIgnoreKeyForOptionalNestedModel() { + let model = OptionalCarShop.generate(seed: 42) + _testEncodeIgnoringKeysWithNilValue(model: model) + } + func testShouldIgnoreKeyForEmptyOptionalNestedModel() { + let model = OptionalCarShop.empty() + _testEncodeIgnoringKeysWithNilValue(model: model) + } +} + +// MAKR: - Round Trip +extension MessagePackEncoderTests { + + func testShouldRoundTripModel() { + do { + let model = CarShop.generate(seed: 42) + let data = try encoder.encode(model) + let decodedModel = try decoder.decode(CarShop.self, from: data) + XCTAssertEqual(model, decodedModel) + } catch { + XCTAssertNil(error) + } + } + + func testShouldMultiStepRoundTripModel() { + do { + let model = CarShop.generate(seed: 42) + let messagePack = try encoder.encodeToMessagePack(model) + let data = try encoder.encodeMessagePack(messagePack) + let decodedMessagePack = try decoder.decodeToMessagePack(from: data) + let decodedModel = try decoder.decodeMessagePack(CarShop.self, from: decodedMessagePack) + + XCTAssertEqual(model, decodedModel) + } catch { + XCTAssertNil(error) + } + } +} + +// MARK: - Utilities +extension MessagePackEncoderTests { + + private func _testEncode(model: T) { + do { + let encoded = try encoder.encodeToMessagePack(model) + XCTAssertEqual(encoded, model.encoded) + } catch { + XCTAssertNil(error) + } + } + + private func _testEncodeIgnoringKeysWithNilValue(model: T) { + do { + encoder.keyedEncodingOptions = .ignoreKeysWithNilValue + let encoded = try encoder.encodeToMessagePack(model) + XCTAssertEqual(encoded, model.encodedIgnoringNil) + } catch { + XCTAssertNil(error) + } + } +} diff --git a/Tests/MessagePackTests/Codable/ModelProtocol.swift b/Tests/MessagePackTests/Codable/ModelProtocol.swift new file mode 100644 index 0000000..a0ecc4a --- /dev/null +++ b/Tests/MessagePackTests/Codable/ModelProtocol.swift @@ -0,0 +1,17 @@ +// +// ModelProtocol.swift +// MessagePackTests +// +// Created by Andrew Eng on 23/2/18. +// + +import Foundation +@testable import MessagePack + +protocol Model: Codable, Equatable { + var encoded: MessagePackValue { get } +} + +protocol OptionalModel: Model { + var encodedIgnoringNil: MessagePackValue { get } +} diff --git a/Tests/MessagePackTests/Codable/Models.swift b/Tests/MessagePackTests/Codable/Models.swift new file mode 100644 index 0000000..f3ca8c2 --- /dev/null +++ b/Tests/MessagePackTests/Codable/Models.swift @@ -0,0 +1,59 @@ +// +// Models.swift +// MessagePackTests +// +// Created by Andrew Eng on 21/2/18. +// + +import Foundation +@testable import MessagePack + +struct Car: Model { + let id: Data + let brand: String + let power: Double + + static func ==(lhs: Car, rhs: Car) -> Bool { + return lhs.id == rhs.id && lhs.brand == rhs.brand && lhs.power == rhs.power + } + + var encoded: MessagePackValue { + return .map([ + .string("id"): .binary(id), + .string("brand"): .string(brand), + .string("power"): .double(power) + ]) + } + + static func generate(seed: UInt8) -> Car { + return Car(id: Data(bytes: [seed, seed + 1]), brand: "\(seed)", power: (3.14 * Double(seed))) + } +} + +struct CarShop: Model { + let car: Car + let carArray: [Car] + let carMap: [String: Car] + + static func ==(lhs: CarShop, rhs: CarShop) -> Bool { + return lhs.car == rhs.car && lhs.carArray == rhs.carArray && lhs.carMap == rhs.carMap + } + + var encoded: MessagePackValue { + var map = [MessagePackValue: MessagePackValue]() + carMap.forEach({ map[.string($0)] = $1.encoded }) + return .map([ + .string("car"): car.encoded, + .string("carArray"): .array(carArray.map({ $0.encoded })), + .string("carMap"): .map(map) + ]) + } + + static func generate(seed: UInt8) -> CarShop { + return CarShop( + car: Car.generate(seed: seed), + carArray: [Car.generate(seed: seed + 1), Car.generate(seed: seed + 2)], + carMap: ["a": Car.generate(seed: seed + 3), "b": Car.generate(seed: seed + 4)] + ) + } +} diff --git a/Tests/MessagePackTests/Codable/OptionalModels.swift b/Tests/MessagePackTests/Codable/OptionalModels.swift new file mode 100644 index 0000000..4adf46c --- /dev/null +++ b/Tests/MessagePackTests/Codable/OptionalModels.swift @@ -0,0 +1,122 @@ +// +// OptionalModels.swift +// MessagePackTests +// +// Created by Andrew Eng on 23/2/18. +// + +import Foundation +@testable import MessagePack + +struct OptionalCar: OptionalModel { + let id: Data? + let brand: String? + let power: Double? + + static func ==(lhs: OptionalCar, rhs: OptionalCar) -> Bool { + return lhs.id == rhs.id && lhs.brand == rhs.brand && lhs.power == rhs.power + } + + var encoded: MessagePackValue { + return .map([ + .string("id"): (id != nil ? MessagePackValue.binary(id!) : MessagePackValue.`nil`), + .string("brand"): (brand != nil ? MessagePackValue.string(brand!) : MessagePackValue.`nil`), + .string("power"): (power != nil ? MessagePackValue.double(power!) : MessagePackValue.`nil`) + ]) + } + + var encodedIgnoringNil: MessagePackValue { + var map = [MessagePackValue: MessagePackValue]() + if let id = id { map[.string("id")] = MessagePackValue.binary(id) } + if let brand = brand { map[.string("brand")] = MessagePackValue.string(brand) } + if let power = power { map[.string("power")] = MessagePackValue.double(power) } + return .map(map) + } + + static func generate(seed: UInt8) -> OptionalCar { + return OptionalCar(id: Data(bytes: [seed, seed + 1]), brand: "\(seed)", power: (3.14 * Double(seed))) + } + static func empty() -> OptionalCar { + return OptionalCar(id: nil, brand: nil, power: nil) + } +} + + +struct OptionalCarShop: OptionalModel { + let car: OptionalCar? + let carArray: [OptionalCar]? + let carMap: [String: OptionalCar]? + + static func ==(lhs: OptionalCarShop, rhs: OptionalCarShop) -> Bool { + if lhs.car != rhs.car { + return false + } + + if let lhsArray = lhs.carArray, let rhsArray = rhs.carArray { + if lhsArray != rhsArray { return false } + } else if lhs.carArray != nil || rhs.carArray != nil { + return false + } + + if let lhsMap = lhs.carMap, let rhsMap = rhs.carMap { + if lhsMap != rhsMap { return false } + } else if lhs.carMap != nil || rhs.carMap != nil { + return false + } + + return true + } + + var encoded: MessagePackValue { + + let array: MessagePackValue + if let carArray = carArray { + array = .array(carArray.map({ $0.encoded })) + } else { + array = .`nil` + } + + let map: MessagePackValue + if let carMap = carMap { + var m = [MessagePackValue: MessagePackValue]() + carMap.forEach({ m[.string($0)] = $1.encoded }) + map = .map(m) + } else { + map = .`nil` + } + + return .map([ + .string("car"): car?.encoded ?? .`nil`, + .string("carArray"): array, + .string("carMap"): map + ]) + } + + var encodedIgnoringNil: MessagePackValue { + var map = [MessagePackValue:MessagePackValue]() + if let car = car { + map[.string("car")] = car.encoded + } + if let carArray = carArray { + map[.string("carArray")] = .array(carArray.map({ $0.encoded })) + } + if let carMap = carMap { + var m = [MessagePackValue: MessagePackValue]() + carMap.forEach({ m[.string($0)] = $1.encoded }) + map[.string("carMap")] = .map(m) + } + return .map(map) + } + + static func generate(seed: UInt8) -> OptionalCarShop { + return OptionalCarShop( + car: OptionalCar.generate(seed: seed), + carArray: [OptionalCar.generate(seed: seed + 1), OptionalCar.generate(seed: seed + 2)], + carMap: ["a": OptionalCar.generate(seed: seed + 3), "b": OptionalCar.generate(seed: seed + 4)] + ) + } + + static func empty() -> OptionalCarShop { + return OptionalCarShop(car: nil, carArray: nil, carMap: nil) + } +} diff --git a/Tests/MessagePackTests/Codable/SingleOptionalTypeModels.swift b/Tests/MessagePackTests/Codable/SingleOptionalTypeModels.swift new file mode 100644 index 0000000..e2b2b46 --- /dev/null +++ b/Tests/MessagePackTests/Codable/SingleOptionalTypeModels.swift @@ -0,0 +1,133 @@ +// +// SingleOptionalTypeModels.swift +// MessagePackTests +// +// Created by Andrew Eng on 23/2/18. +// + +import Foundation + +import Foundation +import XCTest +@testable import MessagePack + +protocol SingleOptionalTypeModel: OptionalModel { + associatedtype T: Codable + var value: T? { get } + func _messagePack() -> MessagePackValue? +} + +extension SingleOptionalTypeModel { + var encoded: MessagePackValue { + let value = _messagePack() ?? .`nil` + return .map([.string("value"): value]) + } + var encodedIgnoringNil: MessagePackValue { + if let value = _messagePack() { + return .map([.string("value"): value]) + } else { + return .map([:]) + } + } +} +extension SingleOptionalTypeModel where Self.T: Equatable { + static func ==(lhs: Self, rhs: Self) -> Bool { return lhs.value == rhs.value } +} + +// MARK: - Models + +struct OptionalBoolModel: SingleOptionalTypeModel { + let value: Bool? + func _messagePack() -> MessagePackValue? { return value.map({ .bool($0) }) } +} +struct OptionalIntModel: SingleOptionalTypeModel { + let value: Int? + func _messagePack() -> MessagePackValue? { return value.map({ .int(Int64($0)) }) } +} +struct OptionalInt8Model: SingleOptionalTypeModel { + let value: Int8? + func _messagePack() -> MessagePackValue? { return value.map({ .int(Int64($0)) }) } +} +struct OptionalInt16Model: SingleOptionalTypeModel { + let value: Int16? + func _messagePack() -> MessagePackValue? { return value.map({ .int(Int64($0)) }) } +} +struct OptionalInt32Model: SingleOptionalTypeModel { + let value: Int32? + func _messagePack() -> MessagePackValue? { return value.map({ .int(Int64($0)) }) } +} +struct OptionalInt64Model: SingleOptionalTypeModel { + let value: Int64? + func _messagePack() -> MessagePackValue? { return value.map({ .int($0) }) } +} +struct OptionalUIntModel: SingleOptionalTypeModel { + let value: UInt? + func _messagePack() -> MessagePackValue? { return value.map({ .uint(UInt64($0)) }) } +} +struct OptionalUInt8Model: SingleOptionalTypeModel { + let value: UInt8? + func _messagePack() -> MessagePackValue? { return value.map({ .uint(UInt64($0)) }) } +} +struct OptionalUInt16Model: SingleOptionalTypeModel { + let value: UInt16? + func _messagePack() -> MessagePackValue? { return value.map({ .uint(UInt64($0)) }) } +} +struct OptionalUInt32Model: SingleOptionalTypeModel { + let value: UInt32? + func _messagePack() -> MessagePackValue? { return value.map({ .uint(UInt64($0)) }) } +} +struct OptionalUInt64Model: SingleOptionalTypeModel { + let value: UInt64? + func _messagePack() -> MessagePackValue? { return value.map({ .uint($0) }) } +} +struct OptionalFloatModel: SingleOptionalTypeModel { + let value: Float? + func _messagePack() -> MessagePackValue? { return value.map({ .float($0) }) } +} +struct OptionalDoubleModel: SingleOptionalTypeModel { + let value: Double? + func _messagePack() -> MessagePackValue? { return value.map({ .double($0) }) } +} +struct OptionalStringModel: SingleOptionalTypeModel { + let value: String? + func _messagePack() -> MessagePackValue? { return value.map({ .string($0) }) } +} +struct OptionalDataModel: SingleOptionalTypeModel { + let value: Data? + func _messagePack() -> MessagePackValue? { return value.map({ .binary($0) }) } +} +struct OptionalArrayModel: SingleOptionalTypeModel { + let value: [String]? + func _messagePack() -> MessagePackValue? { + guard let value = value else { return nil } + let array: [MessagePackValue] = value.map({ .string($0) }) + return .array(array) + } + static func ==(lhs: OptionalArrayModel, rhs: OptionalArrayModel) -> Bool { + if let lhsValue = lhs.value, let rhsValue = rhs.value { + return lhsValue == rhsValue + } else if lhs.value == nil && rhs.value == nil { + return true + } else { + return false + } + } +} +struct OptionalMapModel: SingleOptionalTypeModel { + let value: [String: UInt64]? + func _messagePack() -> MessagePackValue? { + guard let value = value else { return nil } + var map = [MessagePackValue: MessagePackValue]() + value.forEach({ map[.string($0)] = .uint($1) }) + return .map(map) + } + static func ==(lhs: OptionalMapModel, rhs: OptionalMapModel) -> Bool { + if let lhsValue = lhs.value, let rhsValue = rhs.value { + return lhsValue == rhsValue + } else if lhs.value == nil && rhs.value == nil { + return true + } else { + return false + } + } +} diff --git a/Tests/MessagePackTests/Codable/SingleTypeModels.swift b/Tests/MessagePackTests/Codable/SingleTypeModels.swift new file mode 100644 index 0000000..d83e7da --- /dev/null +++ b/Tests/MessagePackTests/Codable/SingleTypeModels.swift @@ -0,0 +1,108 @@ +// +// SingleTypeModels.swift +// MessagePackTests +// +// Created by Andrew Eng on 21/2/18. +// + +import Foundation +import XCTest +@testable import MessagePack + +protocol SingleTypeModel: Model { + associatedtype T: Codable + var value: T { get } + func _messagePack() -> MessagePackValue +} + +extension SingleTypeModel { + var encoded: MessagePackValue { return .map([.string("value"): _messagePack()]) } +} +extension SingleTypeModel where Self.T: Equatable { + static func ==(lhs: Self, rhs: Self) -> Bool { return lhs.value == rhs.value } +} + +// MARK: - Models + +struct NilModel: SingleTypeModel { + let value: Bool? = nil + func _messagePack() -> MessagePackValue { return .`nil` } + static func ==(lhs: NilModel, rhs: NilModel) -> Bool { return lhs.value == rhs.value } +} +struct BoolModel: SingleTypeModel { + let value: Bool + func _messagePack() -> MessagePackValue { return .bool(value) } +} +struct IntModel: SingleTypeModel { + let value: Int + func _messagePack() -> MessagePackValue { return .int(Int64(value)) } +} +struct Int8Model: SingleTypeModel { + let value: Int8 + func _messagePack() -> MessagePackValue { return .int(Int64(value)) } +} +struct Int16Model: SingleTypeModel { + let value: Int16 + func _messagePack() -> MessagePackValue { return .int(Int64(value)) } +} +struct Int32Model: SingleTypeModel { + let value: Int32 + func _messagePack() -> MessagePackValue { return .int(Int64(value)) } +} +struct Int64Model: SingleTypeModel { + let value: Int64 + func _messagePack() -> MessagePackValue { return .int(value) } +} +struct UIntModel: SingleTypeModel { + let value: UInt + func _messagePack() -> MessagePackValue { return .uint(UInt64(value)) } +} +struct UInt8Model: SingleTypeModel { + let value: UInt8 + func _messagePack() -> MessagePackValue { return .uint(UInt64(value)) } +} +struct UInt16Model: SingleTypeModel { + let value: UInt16 + func _messagePack() -> MessagePackValue { return .uint(UInt64(value)) } +} +struct UInt32Model: SingleTypeModel { + let value: UInt32 + func _messagePack() -> MessagePackValue { return .uint(UInt64(value)) } +} +struct UInt64Model: SingleTypeModel { + let value: UInt64 + func _messagePack() -> MessagePackValue { return .uint(value) } +} +struct FloatModel: SingleTypeModel { + let value: Float + func _messagePack() -> MessagePackValue { return .float(value) } +} +struct DoubleModel: SingleTypeModel { + let value: Double + func _messagePack() -> MessagePackValue { return .double(value) } +} +struct StringModel: SingleTypeModel { + let value: String + func _messagePack() -> MessagePackValue { return .string(value) } +} +struct DataModel: SingleTypeModel { + let value: Data + func _messagePack() -> MessagePackValue { return .binary(value) } +} +struct ArrayModel: SingleTypeModel { + let value: [String] + func _messagePack() -> MessagePackValue { + let array: [MessagePackValue] = value.map({ .string($0) }) + return .array(array) + } + static func ==(lhs: ArrayModel, rhs: ArrayModel) -> Bool { return lhs.value == rhs.value } +} +struct MapModel: SingleTypeModel { + let value: [String: UInt64] + func _messagePack() -> MessagePackValue { + var map = [MessagePackValue: MessagePackValue]() + value.forEach({ map[.string($0)] = .uint($1) }) + return .map(map) + } + static func ==(lhs: MapModel, rhs: MapModel) -> Bool { return lhs.value == rhs.value } +} From bfa2f9e7b52436c6d3b65727551cc3a439f9f9ed Mon Sep 17 00:00:00 2001 From: Andrew Eng Date: Wed, 28 Mar 2018 17:28:09 +0800 Subject: [PATCH 2/2] Changed private to fileprivate to go around travis error when running swift test --- .../MessagePack/Decoder/MessagePackDecoder.swift | 2 +- .../MessagePackKeyedDecodingContainer.swift | 14 +++++++------- .../MessagePackSingleValueDecodingContainer.swift | 4 ++-- .../MessagePackUnkeyedDecodingContainer.swift | 8 ++++---- .../MessagePackKeyedEncodingContainer.swift | 12 ++++++------ .../MessagePackSingleValueEncodingContainer.swift | 8 ++++---- .../MessagePackUnkeyedEncodingContainer.swift | 8 ++++---- .../MessagePack/Encoder/_MessagePackEncoder.swift | 6 +++--- .../Codable/MessagePackDecoderTests.swift | 6 +++--- .../Codable/MessagePackEncoderTests.swift | 8 ++++---- 10 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Sources/MessagePack/Decoder/MessagePackDecoder.swift b/Sources/MessagePack/Decoder/MessagePackDecoder.swift index 489ddf3..37d7a79 100644 --- a/Sources/MessagePack/Decoder/MessagePackDecoder.swift +++ b/Sources/MessagePack/Decoder/MessagePackDecoder.swift @@ -29,7 +29,7 @@ open class MessagePackDecoder { final class _MessagePackDecoder { - private let value: MessagePackValue + fileprivate let value: MessagePackValue init(value: MessagePackValue) { self.value = value diff --git a/Sources/MessagePack/Decoder/MessagePackKeyedDecodingContainer.swift b/Sources/MessagePack/Decoder/MessagePackKeyedDecodingContainer.swift index 7656fba..75fe558 100644 --- a/Sources/MessagePack/Decoder/MessagePackKeyedDecodingContainer.swift +++ b/Sources/MessagePack/Decoder/MessagePackKeyedDecodingContainer.swift @@ -19,12 +19,12 @@ final class MessagePackKeyedDecodingContainer { // MARK: - Helper extension MessagePackKeyedDecodingContainer { - private func _decode(_ type: T.Type, forKey key: Key) throws -> T { + fileprivate func _decode(_ type: T.Type, forKey key: Key) throws -> T { let value = try valueForKey(key) return try _decode(value, type: type) } - private func _decode(_ value: MessagePackValue, type: T.Type) throws -> T { + fileprivate func _decode(_ value: MessagePackValue, type: T.Type) throws -> T { guard let decoded = T(messagePack: value) else { let msg = "Cannot decode \(type) from \(value)" @@ -34,7 +34,7 @@ extension MessagePackKeyedDecodingContainer { return decoded } - private func _decodeIfPresent(_ type: T.Type, forKey key: Key) throws -> T? { + fileprivate func _decodeIfPresent(_ type: T.Type, forKey key: Key) throws -> T? { guard let value = map[.string(key.stringValue)] else { return nil @@ -47,17 +47,17 @@ extension MessagePackKeyedDecodingContainer { } } - private func _decodeDecodable(_ type: T.Type, forKey key: Key) throws -> T { + fileprivate func _decodeDecodable(_ type: T.Type, forKey key: Key) throws -> T { let value = try valueForKey(key) return try _decodeDecodable(value, type: type) } - private func _decodeDecodable(_ value: MessagePackValue, type: T.Type) throws -> T { + fileprivate func _decodeDecodable(_ value: MessagePackValue, type: T.Type) throws -> T { let decoder = _MessagePackDecoder(value: value) return try T(from: decoder) } - private func _decodeDecodableIfPresent(_ type: T.Type, forKey key: Key) throws -> T? { + fileprivate func _decodeDecodableIfPresent(_ type: T.Type, forKey key: Key) throws -> T? { guard let value = map[.string(key.stringValue)] else { return nil @@ -70,7 +70,7 @@ extension MessagePackKeyedDecodingContainer { } } - private func valueForKey(_ key: Key) throws -> MessagePackValue { + fileprivate func valueForKey(_ key: Key) throws -> MessagePackValue { guard let value = map[.string(key.stringValue)] else { let msg = "Key not found : \(key)" diff --git a/Sources/MessagePack/Decoder/MessagePackSingleValueDecodingContainer.swift b/Sources/MessagePack/Decoder/MessagePackSingleValueDecodingContainer.swift index 5627873..811e8f1 100644 --- a/Sources/MessagePack/Decoder/MessagePackSingleValueDecodingContainer.swift +++ b/Sources/MessagePack/Decoder/MessagePackSingleValueDecodingContainer.swift @@ -19,7 +19,7 @@ final class MessagePackSingleValueDecodingContainer { // MARK: - Helper extension MessagePackSingleValueDecodingContainer { - private func _decode(_ type: T.Type) throws -> T { + fileprivate func _decode(_ type: T.Type) throws -> T { guard let value = T(messagePack: self.value) else { let msg = "Cannot decode \(type) from \(self.value)" @@ -30,7 +30,7 @@ extension MessagePackSingleValueDecodingContainer { return value } - private func _decodeDecodable(_ type: T.Type) throws -> T { + fileprivate func _decodeDecodable(_ type: T.Type) throws -> T { let decoder = _MessagePackDecoder(value: value) return try T(from: decoder) diff --git a/Sources/MessagePack/Decoder/MessagePackUnkeyedDecodingContainer.swift b/Sources/MessagePack/Decoder/MessagePackUnkeyedDecodingContainer.swift index de94b87..684e746 100644 --- a/Sources/MessagePack/Decoder/MessagePackUnkeyedDecodingContainer.swift +++ b/Sources/MessagePack/Decoder/MessagePackUnkeyedDecodingContainer.swift @@ -10,7 +10,7 @@ import Foundation final class MessagePackUnkeyedDecodingContainer { let array: [MessagePackValue] - private(set) var currentIndex: Int + fileprivate(set) var currentIndex: Int init(array: [MessagePackValue]) { self.array = array @@ -21,7 +21,7 @@ final class MessagePackUnkeyedDecodingContainer { // MARK: - Helper extension MessagePackUnkeyedDecodingContainer { - private func _decode(_ type: T.Type) throws -> T { + fileprivate func _decode(_ type: T.Type) throws -> T { try ensureNotAtEnd(type: type) guard let value = T(messagePack: array[currentIndex]) else { @@ -34,7 +34,7 @@ extension MessagePackUnkeyedDecodingContainer { return value } - private func _decodeDecodable(_ type: T.Type) throws -> T { + fileprivate func _decodeDecodable(_ type: T.Type) throws -> T { try ensureNotAtEnd(type: type) let decoder = _MessagePackDecoder(value: array[currentIndex]) @@ -44,7 +44,7 @@ extension MessagePackUnkeyedDecodingContainer { return decoded } - private func ensureNotAtEnd(type: Any.Type) throws { + fileprivate func ensureNotAtEnd(type: Any.Type) throws { guard !isAtEnd else { let msg = "Unkeyed container is at end" diff --git a/Sources/MessagePack/Encoder/MessagePackKeyedEncodingContainer.swift b/Sources/MessagePack/Encoder/MessagePackKeyedEncodingContainer.swift index f2543e9..d8adc15 100644 --- a/Sources/MessagePack/Encoder/MessagePackKeyedEncodingContainer.swift +++ b/Sources/MessagePack/Encoder/MessagePackKeyedEncodingContainer.swift @@ -9,8 +9,8 @@ import Foundation final class MessagePackKeyedEncodingContainer { - private let storage: MessagePackDictionaryStorage - private let options: _MessagePackEncoder.Options + fileprivate let storage: MessagePackDictionaryStorage + fileprivate let options: _MessagePackEncoder.Options init(storage: MessagePackDictionaryStorage, options: _MessagePackEncoder.Options) { self.storage = storage @@ -21,11 +21,11 @@ final class MessagePackKeyedEncodingContainer { // MARK: Helper extension MessagePackKeyedEncodingContainer { - private func _encode(_ value: T, forKey key: K) throws { + fileprivate func _encode(_ value: T, forKey key: K) throws { storage[key.stringValue] = value.messagePack } - private func _encodeIfPresent(_ value: T?, forKey key: K) throws { + fileprivate func _encodeIfPresent(_ value: T?, forKey key: K) throws { if options.keyedEncodingOptions.contains(.ignoreKeysWithNilValue) && (value == nil) { return } @@ -37,13 +37,13 @@ extension MessagePackKeyedEncodingContainer { } } - private func _encodeEncodable(_ value: T, forKey key: Key) throws { + fileprivate func _encodeEncodable(_ value: T, forKey key: Key) throws { let encoder = _MessagePackEncoder(options: options) try value.encode(to: encoder) storage[key.stringValue] = encoder.messagePack } - private func _encodeEncodableIfPresent(_ value: T?, forKey key: Key) throws { + fileprivate func _encodeEncodableIfPresent(_ value: T?, forKey key: Key) throws { if options.keyedEncodingOptions.contains(.ignoreKeysWithNilValue) && (value == nil) { return } diff --git a/Sources/MessagePack/Encoder/MessagePackSingleValueEncodingContainer.swift b/Sources/MessagePack/Encoder/MessagePackSingleValueEncodingContainer.swift index 9872f2d..8de77a2 100644 --- a/Sources/MessagePack/Encoder/MessagePackSingleValueEncodingContainer.swift +++ b/Sources/MessagePack/Encoder/MessagePackSingleValueEncodingContainer.swift @@ -9,8 +9,8 @@ import Foundation final class MessagePackSingleValueEncodingContainer { - private let storage: MessagePackValueStorage - private let options: _MessagePackEncoder.Options + fileprivate let storage: MessagePackValueStorage + fileprivate let options: _MessagePackEncoder.Options init(storage: MessagePackValueStorage, options: _MessagePackEncoder.Options) { self.storage = storage @@ -21,11 +21,11 @@ final class MessagePackSingleValueEncodingContainer { // MARK: - Helper extension MessagePackSingleValueEncodingContainer { - private func _encode(_ value: T) throws { + fileprivate func _encode(_ value: T) throws { storage.value = value.messagePack } - private func _encodeEncodable(_ value: T) throws { + fileprivate func _encodeEncodable(_ value: T) throws { let encoder = _MessagePackEncoder(options: options) try value.encode(to: encoder) storage.value = encoder.messagePack diff --git a/Sources/MessagePack/Encoder/MessagePackUnkeyedEncodingContainer.swift b/Sources/MessagePack/Encoder/MessagePackUnkeyedEncodingContainer.swift index 223f7ae..495397b 100644 --- a/Sources/MessagePack/Encoder/MessagePackUnkeyedEncodingContainer.swift +++ b/Sources/MessagePack/Encoder/MessagePackUnkeyedEncodingContainer.swift @@ -9,8 +9,8 @@ import Foundation final class MessagePackUnkeyedEncodingContainer { - private let storage: MessagePackArrayStorage - private let options: _MessagePackEncoder.Options + fileprivate let storage: MessagePackArrayStorage + fileprivate let options: _MessagePackEncoder.Options init(storage: MessagePackArrayStorage, options: _MessagePackEncoder.Options) { self.storage = storage @@ -21,11 +21,11 @@ final class MessagePackUnkeyedEncodingContainer { // MARK: - Helper extension MessagePackUnkeyedEncodingContainer { - private func _encode(_ value: T) throws { + fileprivate func _encode(_ value: T) throws { storage.append(value.messagePack) } - private func _encodeEncodable(_ value: T) throws { + fileprivate func _encodeEncodable(_ value: T) throws { let encoder = _MessagePackEncoder(options: options) try value.encode(to: encoder) storage.append(encoder.messagePack) diff --git a/Sources/MessagePack/Encoder/_MessagePackEncoder.swift b/Sources/MessagePack/Encoder/_MessagePackEncoder.swift index 43b7009..566c13f 100644 --- a/Sources/MessagePack/Encoder/_MessagePackEncoder.swift +++ b/Sources/MessagePack/Encoder/_MessagePackEncoder.swift @@ -19,14 +19,14 @@ final class _MessagePackEncoder { let userInfo: [CodingUserInfoKey: Any] } - private let options: Options - private var storage: MessagePackStorage? + fileprivate let options: Options + fileprivate var storage: MessagePackStorage? init(options: Options) { self.options = options } - private func existingStorage(type: T.Type) -> T? { + fileprivate func existingStorage(type: T.Type) -> T? { guard let storage = storage else { return nil } guard let requiredStorage = storage as? T else { diff --git a/Tests/MessagePackTests/Codable/MessagePackDecoderTests.swift b/Tests/MessagePackTests/Codable/MessagePackDecoderTests.swift index da6dd5f..4559ded 100644 --- a/Tests/MessagePackTests/Codable/MessagePackDecoderTests.swift +++ b/Tests/MessagePackTests/Codable/MessagePackDecoderTests.swift @@ -10,7 +10,7 @@ import XCTest class MessagePackDecoderTests: XCTestCase { - private var decoder: MessagePackDecoder! + fileprivate var decoder: MessagePackDecoder! override func setUp() { super.setUp() @@ -361,11 +361,11 @@ extension MessagePackDecoderTests { // MARK: - Utilities extension MessagePackDecoderTests { - private func _testDecode(model: T) { + fileprivate func _testDecode(model: T) { _testDecode(model: model, messagePack: model.encoded) } - private func _testDecode(model: T, messagePack: MessagePackValue) { + fileprivate func _testDecode(model: T, messagePack: MessagePackValue) { do { let decoded = try decoder.decodeMessagePack(T.self, from: messagePack) XCTAssertEqual(decoded, model) diff --git a/Tests/MessagePackTests/Codable/MessagePackEncoderTests.swift b/Tests/MessagePackTests/Codable/MessagePackEncoderTests.swift index db99d87..f11cd9b 100644 --- a/Tests/MessagePackTests/Codable/MessagePackEncoderTests.swift +++ b/Tests/MessagePackTests/Codable/MessagePackEncoderTests.swift @@ -11,8 +11,8 @@ import XCTest class MessagePackEncoderTests: XCTestCase { - private var encoder: MessagePackEncoder! - private var decoder: MessagePackDecoder! + fileprivate var encoder: MessagePackEncoder! + fileprivate var decoder: MessagePackDecoder! override func setUp() { super.setUp() @@ -470,7 +470,7 @@ extension MessagePackEncoderTests { // MARK: - Utilities extension MessagePackEncoderTests { - private func _testEncode(model: T) { + fileprivate func _testEncode(model: T) { do { let encoded = try encoder.encodeToMessagePack(model) XCTAssertEqual(encoded, model.encoded) @@ -479,7 +479,7 @@ extension MessagePackEncoderTests { } } - private func _testEncodeIgnoringKeysWithNilValue(model: T) { + fileprivate func _testEncodeIgnoringKeysWithNilValue(model: T) { do { encoder.keyedEncodingOptions = .ignoreKeysWithNilValue let encoded = try encoder.encodeToMessagePack(model)