Encode keyed containers

This commit is contained in:
Damiaan Dufaux 2017-08-01 17:26:55 +02:00
parent 43dff2cc5b
commit 0490d2cd6f
6 changed files with 363 additions and 156 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/MsgPack/JSON.swift

View file

@ -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";

View file

@ -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")
} }
} }

View file

@ -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
}
} }
} }
} }

View file

@ -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)))
// )
// }
} }

View file

@ -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
}