mirror of
https://github.com/Dev1an/MsgPack.git
synced 2026-04-27 14:57:46 +00:00
Encode keyed containers
This commit is contained in:
parent
43dff2cc5b
commit
0490d2cd6f
6 changed files with 363 additions and 156 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/MsgPack/JSON.swift
|
||||||
|
|
@ -7,12 +7,12 @@
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
|
7495EA251F30B393000EBDF6 /* Encoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74FA3B621F2C9096005CE521 /* Encoder.swift */; };
|
||||||
74A1AE171F2E3E8300B139A3 /* Format.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74A1AE161F2E3E8300B139A3 /* Format.swift */; };
|
74A1AE171F2E3E8300B139A3 /* Format.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74A1AE161F2E3E8300B139A3 /* Format.swift */; };
|
||||||
74FA3B501F2C9060005CE521 /* MsgPack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 74FA3B461F2C9060005CE521 /* MsgPack.framework */; };
|
74FA3B501F2C9060005CE521 /* MsgPack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 74FA3B461F2C9060005CE521 /* MsgPack.framework */; };
|
||||||
74FA3B551F2C9060005CE521 /* MsgPackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74FA3B541F2C9060005CE521 /* MsgPackTests.swift */; };
|
74FA3B551F2C9060005CE521 /* MsgPackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74FA3B541F2C9060005CE521 /* MsgPackTests.swift */; };
|
||||||
74FA3B571F2C9060005CE521 /* MsgPack.h in Headers */ = {isa = PBXBuildFile; fileRef = 74FA3B491F2C9060005CE521 /* MsgPack.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
74FA3B571F2C9060005CE521 /* MsgPack.h in Headers */ = {isa = PBXBuildFile; fileRef = 74FA3B491F2C9060005CE521 /* MsgPack.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||||
74FA3B611F2C908D005CE521 /* DecoderHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74FA3B601F2C908D005CE521 /* DecoderHelper.swift */; };
|
74FA3B611F2C908D005CE521 /* DecoderHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74FA3B601F2C908D005CE521 /* DecoderHelper.swift */; };
|
||||||
74FA3B631F2C9096005CE521 /* Encoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74FA3B621F2C9096005CE521 /* Encoder.swift */; };
|
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
|
|
@ -27,6 +27,7 @@
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
74A1AE161F2E3E8300B139A3 /* Format.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Format.swift; sourceTree = "<group>"; };
|
74A1AE161F2E3E8300B139A3 /* Format.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Format.swift; sourceTree = "<group>"; };
|
||||||
|
74A426DB1F30774F001BE9C4 /* JSON.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = "<group>"; };
|
||||||
74FA3B461F2C9060005CE521 /* MsgPack.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MsgPack.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
74FA3B461F2C9060005CE521 /* MsgPack.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MsgPack.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
74FA3B491F2C9060005CE521 /* MsgPack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MsgPack.h; sourceTree = "<group>"; };
|
74FA3B491F2C9060005CE521 /* MsgPack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MsgPack.h; sourceTree = "<group>"; };
|
||||||
74FA3B4A1F2C9060005CE521 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
74FA3B4A1F2C9060005CE521 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
|
@ -82,6 +83,7 @@
|
||||||
74FA3B621F2C9096005CE521 /* Encoder.swift */,
|
74FA3B621F2C9096005CE521 /* Encoder.swift */,
|
||||||
74A1AE161F2E3E8300B139A3 /* Format.swift */,
|
74A1AE161F2E3E8300B139A3 /* Format.swift */,
|
||||||
74FA3B4A1F2C9060005CE521 /* Info.plist */,
|
74FA3B4A1F2C9060005CE521 /* Info.plist */,
|
||||||
|
74A426DB1F30774F001BE9C4 /* JSON.swift */,
|
||||||
);
|
);
|
||||||
path = MsgPack;
|
path = MsgPack;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -204,7 +206,7 @@
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
74FA3B631F2C9096005CE521 /* Encoder.swift in Sources */,
|
7495EA251F30B393000EBDF6 /* Encoder.swift in Sources */,
|
||||||
74A1AE171F2E3E8300B139A3 /* Format.swift in Sources */,
|
74A1AE171F2E3E8300B139A3 /* Format.swift in Sources */,
|
||||||
74FA3B611F2C908D005CE521 /* DecoderHelper.swift in Sources */,
|
74FA3B611F2C908D005CE521 /* DecoderHelper.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
|
@ -353,7 +355,7 @@
|
||||||
DYLIB_CURRENT_VERSION = 1;
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||||
FRAMEWORK_VERSION = A;
|
FRAMEWORK_VERSION = A;
|
||||||
GCC_OPTIMIZATION_LEVEL = fast;
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
INFOPLIST_FILE = MsgPack/Info.plist;
|
INFOPLIST_FILE = MsgPack/Info.plist;
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
|
||||||
|
|
|
||||||
|
|
@ -9,26 +9,29 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class Encoder {
|
public class Encoder {
|
||||||
let serialiser = Serialiser()
|
let intermediate = IntermediateEncoder()
|
||||||
|
|
||||||
public init() {}
|
public init() {}
|
||||||
|
|
||||||
public func encode<T : Encodable>(_ value: T) throws -> Data {
|
public func encode<T : Encodable>(_ value: T) throws -> Data {
|
||||||
try value.encode(to: serialiser)
|
try value.encode(to: intermediate)
|
||||||
var data = Data()
|
var data = Data()
|
||||||
try serialiser.storage?.appendTo(data: &data)
|
try intermediate.container?.getFormat().appendTo(data: &data)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Serialiser: Swift.Encoder {
|
class IntermediateEncoder: Swift.Encoder {
|
||||||
|
|
||||||
var codingPath = [CodingKey]()
|
var codingPath = [CodingKey]()
|
||||||
var userInfo = [CodingUserInfoKey : Any]()
|
var userInfo = [CodingUserInfoKey : Any]()
|
||||||
|
|
||||||
var storage: Format?
|
var container: MessagePackEncodingContainer?
|
||||||
|
|
||||||
func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {
|
func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {
|
||||||
preconditionFailure()
|
let keyedContainer = MsgPackKeyedEncodingContainer<Key>()
|
||||||
|
container = keyedContainer
|
||||||
|
return KeyedEncodingContainer(keyedContainer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func unkeyedContainer() -> UnkeyedEncodingContainer {
|
func unkeyedContainer() -> UnkeyedEncodingContainer {
|
||||||
|
|
@ -36,13 +39,82 @@ class Serialiser: Swift.Encoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
func singleValueContainer() -> SingleValueEncodingContainer {
|
func singleValueContainer() -> SingleValueEncodingContainer {
|
||||||
return self
|
let singleValueContainer = MsgPackSingleValueEncodingContainer()
|
||||||
|
container = singleValueContainer
|
||||||
|
return singleValueContainer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MsgPack.Serialiser: SingleValueEncodingContainer {
|
extension Format {
|
||||||
|
static func from(string: String) throws -> Format {
|
||||||
|
guard let data = string.data(using: .utf8) else {throw MsgPackEncodingError.stringNotConvertibleToUTF8(string)}
|
||||||
|
switch data.count {
|
||||||
|
case 1..<32:
|
||||||
|
return .fixString(data)
|
||||||
|
case 32..<256:
|
||||||
|
return .string8(data)
|
||||||
|
case 256..<65536:
|
||||||
|
return .string16(data)
|
||||||
|
default:
|
||||||
|
return .string32(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func from(keyValuePairs: [(Format, Format)]) -> Format {
|
||||||
|
switch keyValuePairs.count {
|
||||||
|
case 1..<16:
|
||||||
|
return .fixMap(keyValuePairs)
|
||||||
|
case 16..<65536:
|
||||||
|
return .map16(keyValuePairs)
|
||||||
|
default:
|
||||||
|
return .map32(keyValuePairs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static func from(int: Int) -> Format {
|
||||||
|
#if arch(arm) || arch(i386)
|
||||||
|
return .int32(Int32(int))
|
||||||
|
#else
|
||||||
|
return .int64(Int64(int))
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static func from(uInt: UInt) -> Format {
|
||||||
|
#if arch(arm) || arch(i386)
|
||||||
|
return .uInt32(UInt32(uInt))
|
||||||
|
#else
|
||||||
|
return .uInt64(UInt64(uInt))
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MessagePackEncodingContainer {
|
||||||
|
var codingPath: [CodingKey] = []
|
||||||
|
|
||||||
|
func getFormat() throws -> Format {
|
||||||
|
preconditionFailure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MsgPackEncodingError: Swift.Error {
|
||||||
|
case notImplemented, stringNotConvertibleToUTF8(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
class MsgPackSingleValueEncodingContainer: MessagePackEncodingContainer, SingleValueEncodingContainer {
|
||||||
|
|
||||||
|
var storage: Format?
|
||||||
|
|
||||||
enum Error: Swift.Error {
|
enum Error: Swift.Error {
|
||||||
case notImplemented, stringNotConvertibleToUTF8
|
case noValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override func getFormat() throws -> Format {
|
||||||
|
guard let format = storage else {throw Error.noValue}
|
||||||
|
return format
|
||||||
|
}
|
||||||
|
|
||||||
|
init(with storage: Format? = nil) {
|
||||||
|
self.storage = storage
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeNil() throws {
|
func encodeNil() throws {
|
||||||
|
|
@ -54,11 +126,7 @@ extension MsgPack.Serialiser: SingleValueEncodingContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode(_ value: Int) throws {
|
func encode(_ value: Int) throws {
|
||||||
#if arch(arm) || arch(i386)
|
storage = .from(int: value)
|
||||||
storage = .int32(Int32(value))
|
|
||||||
#else
|
|
||||||
storage = .int64(Int64(value))
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode(_ value: Int8) throws {
|
func encode(_ value: Int8) throws {
|
||||||
|
|
@ -78,11 +146,7 @@ extension MsgPack.Serialiser: SingleValueEncodingContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode(_ value: UInt) throws {
|
func encode(_ value: UInt) throws {
|
||||||
#if arch(arm) || arch(i386)
|
storage = .from(uInt: value)
|
||||||
storage = .uInt32(UInt32(value))
|
|
||||||
#else
|
|
||||||
storage = .uInt64(UInt64(value))
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode(_ value: UInt8) throws {
|
func encode(_ value: UInt8) throws {
|
||||||
|
|
@ -110,20 +174,104 @@ extension MsgPack.Serialiser: SingleValueEncodingContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode(_ value: String) throws {
|
func encode(_ value: String) throws {
|
||||||
guard let data = value.data(using: .utf8) else {throw Error.stringNotConvertibleToUTF8}
|
storage = try .from(string: value)
|
||||||
switch data.count {
|
|
||||||
case 1..<32:
|
|
||||||
storage = .fixString(data)
|
|
||||||
case 32..<256:
|
|
||||||
storage = .string8(data)
|
|
||||||
case 256..<65536:
|
|
||||||
storage = .string16(data)
|
|
||||||
default:
|
|
||||||
storage = .string32(data)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func encode<T : Encodable>(_ value: T) throws {
|
func encode<T : Encodable>(_ value: T) throws {
|
||||||
throw Error.notImplemented
|
throw MsgPackEncodingError.notImplemented
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MsgPackKeyedEncodingContainer<K: CodingKey>: MessagePackEncodingContainer, KeyedEncodingContainerProtocol {
|
||||||
|
var userInfo = [CodingUserInfoKey : Any]()
|
||||||
|
|
||||||
|
var storage = [String: MessagePackEncodingContainer]()
|
||||||
|
|
||||||
|
override func getFormat() throws -> Format {
|
||||||
|
return try Format.from(keyValuePairs: storage.map {
|
||||||
|
(try Format.from(string: $0.key), try $0.value.getFormat())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func encodeNil(forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = MsgPackSingleValueEncodingContainer(with: .nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ value: Bool, forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = MsgPackSingleValueEncodingContainer(with: .boolean(value) )
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ value: Int, forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = MsgPackSingleValueEncodingContainer(with: .from(int: value) )
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ value: Int8, forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = MsgPackSingleValueEncodingContainer(with: .int8(value) )
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ value: Int16, forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = MsgPackSingleValueEncodingContainer(with: .int16(value) )
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ value: Int32, forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = MsgPackSingleValueEncodingContainer(with: .int32(value) )
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ value: Int64, forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = MsgPackSingleValueEncodingContainer(with: .int64(value) )
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ value: UInt, forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = MsgPackSingleValueEncodingContainer(with: .from(uInt: value) )
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ value: UInt8, forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = MsgPackSingleValueEncodingContainer(with: .uInt8(value) )
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ value: UInt16, forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = MsgPackSingleValueEncodingContainer(with: .uInt16(value) )
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ value: UInt32, forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = MsgPackSingleValueEncodingContainer(with: .uInt32(value) )
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ value: UInt64, forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = MsgPackSingleValueEncodingContainer(with: .uInt64(value) )
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ value: Float, forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = MsgPackSingleValueEncodingContainer(with: .float32(value) )
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ value: Double, forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = MsgPackSingleValueEncodingContainer(with: .float64(value) )
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(_ value: String, forKey key: K) throws {
|
||||||
|
storage[key.stringValue] = try MsgPackSingleValueEncodingContainer(with: .from(string: value) )
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode<T>(_ value: T, forKey key: K) throws where T : Encodable {
|
||||||
|
throw MsgPackEncodingError.notImplemented
|
||||||
|
}
|
||||||
|
|
||||||
|
func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: K) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
|
||||||
|
let keyedContainer = MsgPackKeyedEncodingContainer<NestedKey>()
|
||||||
|
storage[key.stringValue] = keyedContainer
|
||||||
|
return KeyedEncodingContainer(keyedContainer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func nestedUnkeyedContainer(forKey key: K) -> UnkeyedEncodingContainer {
|
||||||
|
preconditionFailure("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func superEncoder() -> Swift.Encoder {
|
||||||
|
preconditionFailure("not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func superEncoder(forKey key: K) -> Swift.Encoder {
|
||||||
|
preconditionFailure("not implemented")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,21 @@ enum Format {
|
||||||
case float64(Double)
|
case float64(Double)
|
||||||
|
|
||||||
case fixString(Data)
|
case fixString(Data)
|
||||||
case string8(Data)
|
case string8 (Data)
|
||||||
case string16(Data)
|
case string16 (Data)
|
||||||
case string32(Data)
|
case string32 (Data)
|
||||||
|
|
||||||
|
case fixArray([Format])
|
||||||
|
case array16 ([Format])
|
||||||
|
case array32 ([Format])
|
||||||
|
|
||||||
|
case fixMap([(key: Format, value: Format)])
|
||||||
|
case map16 ([(key: Format, value: Format)])
|
||||||
|
case map32 ([(key: Format, value: Format)])
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension Format {
|
||||||
func appendTo(data: inout Data) {
|
func appendTo(data: inout Data) {
|
||||||
switch self {
|
switch self {
|
||||||
|
|
||||||
|
|
@ -59,117 +70,136 @@ enum Format {
|
||||||
data.append(value)
|
data.append(value)
|
||||||
case .uInt16(let value):
|
case .uInt16(let value):
|
||||||
var newData = Data(count: 3)
|
var newData = Data(count: 3)
|
||||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
newData[0] = 0xCD
|
||||||
byteContainer.pointee = 0xCD
|
newData.write(value: value.bigEndian, offset: 1)
|
||||||
byteContainer.advanced(by: 1).withMemoryRebound(to: UInt16.self, capacity: 1) {
|
|
||||||
$0.pointee = value.bigEndian
|
|
||||||
}
|
|
||||||
})
|
|
||||||
data.append(newData)
|
data.append(newData)
|
||||||
case .uInt32(let value):
|
case .uInt32(let value):
|
||||||
var newData = Data(count: 5)
|
var newData = Data(count: 5)
|
||||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
newData[0] = 0xCE
|
||||||
byteContainer.pointee = 0xCE
|
newData.write(value: value.bigEndian, offset: 1)
|
||||||
byteContainer.advanced(by: 1).withMemoryRebound(to: UInt32.self, capacity: 1) {
|
|
||||||
$0.pointee = value.bigEndian
|
|
||||||
}
|
|
||||||
})
|
|
||||||
data.append(newData)
|
data.append(newData)
|
||||||
case .uInt64(let value):
|
case .uInt64(let value):
|
||||||
var newData = Data(count: 9)
|
var newData = Data(count: 9)
|
||||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
newData[0] = 0xCF
|
||||||
byteContainer.pointee = 0xCF
|
newData.write(value: value.bigEndian, offset: 1)
|
||||||
byteContainer.advanced(by: 1).withMemoryRebound(to: UInt64.self, capacity: 1) {
|
|
||||||
$0.pointee = value.bigEndian
|
|
||||||
}
|
|
||||||
})
|
|
||||||
data.append(newData)
|
data.append(newData)
|
||||||
|
|
||||||
// MARK: Signed integers
|
// MARK: Signed integers
|
||||||
case .int8(let value):
|
case .int8(let value):
|
||||||
var newData = Data(count: 2)
|
var newData = Data(count: 2)
|
||||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
newData[0] = 0xD0
|
||||||
byteContainer.pointee = 0xD1
|
newData.write(value: value.bigEndian, offset: 1)
|
||||||
byteContainer.advanced(by: 1).withMemoryRebound(to: Int8.self, capacity: 1) {
|
|
||||||
$0.pointee = value.bigEndian
|
|
||||||
}
|
|
||||||
})
|
|
||||||
data.append(newData)
|
data.append(newData)
|
||||||
case .int16(let value):
|
case .int16(let value):
|
||||||
var newData = Data(count: 3)
|
var newData = Data(count: 3)
|
||||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
newData[0] = 0xD1
|
||||||
byteContainer.pointee = 0xD2
|
newData.write(value: value.bigEndian, offset: 1)
|
||||||
byteContainer.advanced(by: 1).withMemoryRebound(to: Int16.self, capacity: 1) {
|
|
||||||
$0.pointee = value.bigEndian
|
|
||||||
}
|
|
||||||
})
|
|
||||||
data.append(newData)
|
data.append(newData)
|
||||||
case .int32(let value):
|
case .int32(let value):
|
||||||
var newData = Data(count: 5)
|
var newData = Data(count: 5)
|
||||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
newData[0] = 0xD2
|
||||||
byteContainer.pointee = 0xD2
|
newData.write(value: value.bigEndian, offset: 1)
|
||||||
byteContainer.advanced(by: 1).withMemoryRebound(to: Int32.self, capacity: 1) {
|
|
||||||
$0.pointee = value.bigEndian
|
|
||||||
}
|
|
||||||
})
|
|
||||||
data.append(newData)
|
data.append(newData)
|
||||||
case .int64(let value):
|
case .int64(let value):
|
||||||
var newData = Data(count: 9)
|
var newData = Data(count: 9)
|
||||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
newData[0] = 0xD3
|
||||||
byteContainer.pointee = 0xD3
|
newData.write(value: value.bigEndian, offset: 1)
|
||||||
byteContainer.advanced(by: 1).withMemoryRebound(to: Int64.self, capacity: 1) {
|
|
||||||
$0.pointee = value.bigEndian
|
|
||||||
}
|
|
||||||
})
|
|
||||||
data.append(newData)
|
data.append(newData)
|
||||||
|
|
||||||
// MARK: Floats
|
// MARK: Floats
|
||||||
case .float32(let value):
|
case .float32(let value):
|
||||||
var newData = Data(count: 5)
|
var newData = Data(count: 5)
|
||||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
newData[0] = 0xCA
|
||||||
byteContainer.pointee = 0xCA
|
newData.write(value: value.bitPattern.bigEndian, offset: 1)
|
||||||
byteContainer.advanced(by: 1).withMemoryRebound(to: UInt32.self, capacity: 1) {
|
|
||||||
$0.pointee = value.bitPattern.bigEndian
|
|
||||||
}
|
|
||||||
})
|
|
||||||
data.append(newData)
|
data.append(newData)
|
||||||
case .float64(let value):
|
case .float64(let value):
|
||||||
var newData = Data(count: 9)
|
var newData = Data(count: 9)
|
||||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
newData[0] = 0xCB
|
||||||
byteContainer.pointee = 0xCB
|
newData.write(value: value.bitPattern.bigEndian, offset: 1)
|
||||||
byteContainer.advanced(by: 1).withMemoryRebound(to: UInt64.self, capacity: 1) {
|
|
||||||
$0.pointee = value.bitPattern.bigEndian
|
|
||||||
}
|
|
||||||
})
|
|
||||||
data.append(newData)
|
data.append(newData)
|
||||||
|
|
||||||
// MARK: Strings
|
// MARK: Strings
|
||||||
case .fixString(let value):
|
case .fixString(let utf8Data):
|
||||||
data.append(UInt8(value.count) & 0b00011111 | 0b10100000)
|
precondition(utf8Data.count < 32, "fix strings cannot contain more than 31 bytes")
|
||||||
data.append(value)
|
data.append( UInt8(utf8Data.count) | 0b10100000)
|
||||||
case .string8(let value):
|
data.append(utf8Data)
|
||||||
data.append(contentsOf: [0xD9, UInt8(value.count)])
|
case .string8(let utf8Data):
|
||||||
data.append(value)
|
data.append(contentsOf: [0xD9, UInt8(utf8Data.count)])
|
||||||
case .string16(let value):
|
data.append(utf8Data)
|
||||||
|
case .string16(let utf8Data):
|
||||||
var prefix = Data(count: 3)
|
var prefix = Data(count: 3)
|
||||||
prefix.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
prefix[0] = 0xDA
|
||||||
byteContainer.pointee = 0xDA
|
prefix.write(value: UInt16(utf8Data.count).bigEndian, offset: 1)
|
||||||
byteContainer.advanced(by: 1).withMemoryRebound(to: UInt16.self, capacity: 1) {
|
|
||||||
$0.pointee = UInt16(value.count).bigEndian
|
|
||||||
}
|
|
||||||
})
|
|
||||||
data.append(prefix)
|
data.append(prefix)
|
||||||
data.append(value)
|
data.append(utf8Data)
|
||||||
case .string32(let value):
|
case .string32(let utf8Data):
|
||||||
var prefix = Data(count: 5)
|
var prefix = Data(count: 5)
|
||||||
prefix.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
prefix[0] = 0xDB
|
||||||
byteContainer.pointee = 0xDB
|
prefix.write(value: UInt32(utf8Data.count).bigEndian, offset: 1)
|
||||||
byteContainer.advanced(by: 1).withMemoryRebound(to: UInt32.self, capacity: 1) {
|
|
||||||
$0.pointee = UInt32(value.count).bigEndian
|
|
||||||
}
|
|
||||||
})
|
|
||||||
data.append(prefix)
|
data.append(prefix)
|
||||||
data.append(value)
|
data.append(utf8Data)
|
||||||
|
|
||||||
|
// MARK: Arrays
|
||||||
|
case .fixArray(let array):
|
||||||
|
precondition(array.count < 16, "fix arrays cannot contain more than 15 elements")
|
||||||
|
data.append( UInt8(array.count) | 0b10010000)
|
||||||
|
for element in array {
|
||||||
|
element.appendTo(data: &data)
|
||||||
|
}
|
||||||
|
case .array16(let array):
|
||||||
|
var prefix = Data(count: 3)
|
||||||
|
prefix[0] = 0xDC
|
||||||
|
prefix.write(value: UInt16(array.count).bigEndian, offset: 1)
|
||||||
|
data.append(prefix)
|
||||||
|
for element in array {
|
||||||
|
element.appendTo(data: &data)
|
||||||
|
}
|
||||||
|
case .array32(let array):
|
||||||
|
var prefix = Data(count: 5)
|
||||||
|
prefix[0] = 0xDD
|
||||||
|
prefix.write(value: UInt32(array.count).bigEndian, offset: 1)
|
||||||
|
data.append(prefix)
|
||||||
|
for element in array {
|
||||||
|
element.appendTo(data: &data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Maps
|
||||||
|
case .fixMap(let pairs):
|
||||||
|
precondition(pairs.count < 16, "fix maps cannot contain more than 15 key-value pairs")
|
||||||
|
data.append( UInt8(pairs.count) | 0b10000000)
|
||||||
|
for (key, value) in pairs {
|
||||||
|
key.appendTo(data: &data)
|
||||||
|
value.appendTo(data: &data)
|
||||||
|
}
|
||||||
|
case .map16(let pairs):
|
||||||
|
var prefix = Data(count: 3)
|
||||||
|
prefix[0] = 0xDE
|
||||||
|
prefix.write(value: UInt16(pairs.count).bigEndian, offset: 1)
|
||||||
|
data.append(prefix)
|
||||||
|
for (key, value) in pairs {
|
||||||
|
key.appendTo(data: &data)
|
||||||
|
value.appendTo(data: &data)
|
||||||
|
}
|
||||||
|
case .map32(let pairs):
|
||||||
|
var prefix = Data(count: 5)
|
||||||
|
prefix[0] = 0xDE
|
||||||
|
prefix.write(value: UInt32(pairs.count).bigEndian, offset: 1)
|
||||||
|
data.append(prefix)
|
||||||
|
for (key, value) in pairs {
|
||||||
|
key.appendTo(data: &data)
|
||||||
|
value.appendTo(data: &data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension Data {
|
||||||
|
mutating func write<T>(value: T, offset: Int) {
|
||||||
|
withUnsafeMutableBytes {(byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
||||||
|
byteContainer.advanced(by: offset).withMemoryRebound(to: T.self, capacity: 1) {
|
||||||
|
$0.pointee = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,10 @@ import XCTest
|
||||||
@testable import MsgPack
|
@testable import MsgPack
|
||||||
|
|
||||||
class MsgPackTests: XCTestCase {
|
class MsgPackTests: XCTestCase {
|
||||||
|
// override func tearDown() {
|
||||||
|
// // Put teardown code here. This method is called after the invocation of each test method in the class.
|
||||||
|
// super.tearDown()
|
||||||
|
// }
|
||||||
|
|
||||||
var encoder: MsgPack.Encoder!
|
var encoder: MsgPack.Encoder!
|
||||||
|
|
||||||
|
|
@ -19,10 +23,6 @@ class MsgPackTests: XCTestCase {
|
||||||
encoder = Encoder()
|
encoder = Encoder()
|
||||||
}
|
}
|
||||||
|
|
||||||
// override func tearDown() {
|
|
||||||
// // Put teardown code here. This method is called after the invocation of each test method in the class.
|
|
||||||
// super.tearDown()
|
|
||||||
// }
|
|
||||||
|
|
||||||
func testEncodeTrue() {
|
func testEncodeTrue() {
|
||||||
do {
|
do {
|
||||||
|
|
@ -107,5 +107,27 @@ class MsgPackTests: XCTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// var encoder = MsgPack.JSONEncoder2()
|
||||||
|
//
|
||||||
|
// struct Obj: Encodable {
|
||||||
|
// let i: Int
|
||||||
|
// let p: Person
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// struct Person: Encodable {
|
||||||
|
// let name: String
|
||||||
|
// let friend: Friend
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// struct Friend: Encodable {
|
||||||
|
// let count: Double
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func testDinges() {
|
||||||
|
// try! encoder.encode(
|
||||||
|
// Obj(i: 3, p: Person(name: "Dinges", friend: Friend(count: 8)))
|
||||||
|
// )
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,23 +5,27 @@ import Foundation
|
||||||
|
|
||||||
let encoder = Encoder()
|
let encoder = Encoder()
|
||||||
|
|
||||||
let integerData = try encoder.encode(0x0102030405060708)
|
try encoder.encode(0x0102030405060708)
|
||||||
String(integerData[0], radix: 16)
|
|
||||||
|
|
||||||
integerData[1]
|
try encoder.encode("Hello")
|
||||||
integerData[2]
|
|
||||||
integerData[3]
|
|
||||||
integerData[4]
|
|
||||||
integerData[5]
|
|
||||||
integerData[6]
|
|
||||||
integerData[7]
|
|
||||||
integerData[8]
|
|
||||||
|
|
||||||
let doubleData = try encoder.encode("Hello there 123456789012345678901")
|
try encoder.encode("😇")
|
||||||
String(doubleData[0], radix: 16)
|
|
||||||
|
|
||||||
String(doubleData[1], radix: 16)
|
var n: Int?
|
||||||
String(doubleData[2], radix: 16)
|
try encoder.encode(n)
|
||||||
String(doubleData[3], radix: 16)
|
|
||||||
String(doubleData[4], radix: 16)
|
struct Position: Encodable {
|
||||||
String(doubleData[5], radix: 16)
|
let x: Int8
|
||||||
|
let y: Int8
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Circle: Encodable {
|
||||||
|
let center: Position
|
||||||
|
let radius: UInt
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
try encoder.encode(Circle(center: Position(x: -1, y: 2), radius: 50)).forEach { print(String($0, radix: 16)) }
|
||||||
|
} catch {
|
||||||
|
error
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue