mirror of
https://github.com/Dev1an/MsgPack.git
synced 2026-03-25 08:45:55 +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 = {
|
||||
|
||||
/* 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 */; };
|
||||
74FA3B501F2C9060005CE521 /* MsgPack.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 74FA3B461F2C9060005CE521 /* MsgPack.framework */; };
|
||||
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, ); }; };
|
||||
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 */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
/* Begin PBXFileReference section */
|
||||
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; };
|
||||
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>"; };
|
||||
|
|
@ -82,6 +83,7 @@
|
|||
74FA3B621F2C9096005CE521 /* Encoder.swift */,
|
||||
74A1AE161F2E3E8300B139A3 /* Format.swift */,
|
||||
74FA3B4A1F2C9060005CE521 /* Info.plist */,
|
||||
74A426DB1F30774F001BE9C4 /* JSON.swift */,
|
||||
);
|
||||
path = MsgPack;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -204,7 +206,7 @@
|
|||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
74FA3B631F2C9096005CE521 /* Encoder.swift in Sources */,
|
||||
7495EA251F30B393000EBDF6 /* Encoder.swift in Sources */,
|
||||
74A1AE171F2E3E8300B139A3 /* Format.swift in Sources */,
|
||||
74FA3B611F2C908D005CE521 /* DecoderHelper.swift in Sources */,
|
||||
);
|
||||
|
|
@ -353,7 +355,7 @@
|
|||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
FRAMEWORK_VERSION = A;
|
||||
GCC_OPTIMIZATION_LEVEL = fast;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
INFOPLIST_FILE = MsgPack/Info.plist;
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
|
||||
|
|
|
|||
|
|
@ -9,26 +9,29 @@
|
|||
import Foundation
|
||||
|
||||
public class Encoder {
|
||||
let serialiser = Serialiser()
|
||||
let intermediate = IntermediateEncoder()
|
||||
|
||||
public init() {}
|
||||
|
||||
public func encode<T : Encodable>(_ value: T) throws -> Data {
|
||||
try value.encode(to: serialiser)
|
||||
try value.encode(to: intermediate)
|
||||
var data = Data()
|
||||
try serialiser.storage?.appendTo(data: &data)
|
||||
try intermediate.container?.getFormat().appendTo(data: &data)
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
||||
class Serialiser: Swift.Encoder {
|
||||
class IntermediateEncoder: Swift.Encoder {
|
||||
|
||||
var codingPath = [CodingKey]()
|
||||
var userInfo = [CodingUserInfoKey : Any]()
|
||||
|
||||
var storage: Format?
|
||||
var container: MessagePackEncodingContainer?
|
||||
|
||||
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 {
|
||||
|
|
@ -36,94 +39,239 @@ class Serialiser: Swift.Encoder {
|
|||
}
|
||||
|
||||
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 {
|
||||
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 {
|
||||
storage = .nil
|
||||
}
|
||||
|
||||
|
||||
func encode(_ value: Bool) throws {
|
||||
storage = .boolean(value)
|
||||
}
|
||||
|
||||
|
||||
func encode(_ value: Int) throws {
|
||||
#if arch(arm) || arch(i386)
|
||||
storage = .int32(Int32(value))
|
||||
#else
|
||||
storage = .int64(Int64(value))
|
||||
#endif
|
||||
storage = .from(int: value)
|
||||
}
|
||||
|
||||
|
||||
func encode(_ value: Int8) throws {
|
||||
storage = .int8(value)
|
||||
}
|
||||
|
||||
|
||||
func encode(_ value: Int16) throws {
|
||||
storage = .int16(value)
|
||||
}
|
||||
|
||||
|
||||
func encode(_ value: Int32) throws {
|
||||
storage = .int32(value)
|
||||
}
|
||||
|
||||
|
||||
func encode(_ value: Int64) throws {
|
||||
storage = .int64(value)
|
||||
}
|
||||
|
||||
|
||||
func encode(_ value: UInt) throws {
|
||||
#if arch(arm) || arch(i386)
|
||||
storage = .uInt32(UInt32(value))
|
||||
#else
|
||||
storage = .uInt64(UInt64(value))
|
||||
#endif
|
||||
storage = .from(uInt: value)
|
||||
}
|
||||
|
||||
|
||||
func encode(_ value: UInt8) throws {
|
||||
storage = .uInt8(value)
|
||||
}
|
||||
|
||||
|
||||
func encode(_ value: UInt16) throws {
|
||||
storage = .uInt16(value)
|
||||
}
|
||||
|
||||
|
||||
func encode(_ value: UInt32) throws {
|
||||
storage = .uInt32(value)
|
||||
}
|
||||
|
||||
|
||||
func encode(_ value: UInt64) throws {
|
||||
storage = .uInt64(value)
|
||||
}
|
||||
|
||||
|
||||
func encode(_ value: Float) throws {
|
||||
storage = .float32(value)
|
||||
}
|
||||
|
||||
|
||||
func encode(_ value: Double) throws {
|
||||
storage = .float64(value)
|
||||
}
|
||||
|
||||
|
||||
func encode(_ value: String) throws {
|
||||
guard let data = value.data(using: .utf8) else {throw Error.stringNotConvertibleToUTF8}
|
||||
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)
|
||||
}
|
||||
storage = try .from(string: value)
|
||||
}
|
||||
|
||||
|
||||
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 fixString(Data)
|
||||
case string8(Data)
|
||||
case string16(Data)
|
||||
case string32(Data)
|
||||
case string8 (Data)
|
||||
case string16 (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) {
|
||||
switch self {
|
||||
|
||||
|
|
@ -59,117 +70,136 @@ enum Format {
|
|||
data.append(value)
|
||||
case .uInt16(let value):
|
||||
var newData = Data(count: 3)
|
||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
||||
byteContainer.pointee = 0xCD
|
||||
byteContainer.advanced(by: 1).withMemoryRebound(to: UInt16.self, capacity: 1) {
|
||||
$0.pointee = value.bigEndian
|
||||
}
|
||||
})
|
||||
newData[0] = 0xCD
|
||||
newData.write(value: value.bigEndian, offset: 1)
|
||||
data.append(newData)
|
||||
case .uInt32(let value):
|
||||
var newData = Data(count: 5)
|
||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
||||
byteContainer.pointee = 0xCE
|
||||
byteContainer.advanced(by: 1).withMemoryRebound(to: UInt32.self, capacity: 1) {
|
||||
$0.pointee = value.bigEndian
|
||||
}
|
||||
})
|
||||
newData[0] = 0xCE
|
||||
newData.write(value: value.bigEndian, offset: 1)
|
||||
data.append(newData)
|
||||
case .uInt64(let value):
|
||||
var newData = Data(count: 9)
|
||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
||||
byteContainer.pointee = 0xCF
|
||||
byteContainer.advanced(by: 1).withMemoryRebound(to: UInt64.self, capacity: 1) {
|
||||
$0.pointee = value.bigEndian
|
||||
}
|
||||
})
|
||||
newData[0] = 0xCF
|
||||
newData.write(value: value.bigEndian, offset: 1)
|
||||
data.append(newData)
|
||||
|
||||
// MARK: Signed integers
|
||||
case .int8(let value):
|
||||
var newData = Data(count: 2)
|
||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
||||
byteContainer.pointee = 0xD1
|
||||
byteContainer.advanced(by: 1).withMemoryRebound(to: Int8.self, capacity: 1) {
|
||||
$0.pointee = value.bigEndian
|
||||
}
|
||||
})
|
||||
newData[0] = 0xD0
|
||||
newData.write(value: value.bigEndian, offset: 1)
|
||||
data.append(newData)
|
||||
case .int16(let value):
|
||||
var newData = Data(count: 3)
|
||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
||||
byteContainer.pointee = 0xD2
|
||||
byteContainer.advanced(by: 1).withMemoryRebound(to: Int16.self, capacity: 1) {
|
||||
$0.pointee = value.bigEndian
|
||||
}
|
||||
})
|
||||
newData[0] = 0xD1
|
||||
newData.write(value: value.bigEndian, offset: 1)
|
||||
data.append(newData)
|
||||
case .int32(let value):
|
||||
var newData = Data(count: 5)
|
||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
||||
byteContainer.pointee = 0xD2
|
||||
byteContainer.advanced(by: 1).withMemoryRebound(to: Int32.self, capacity: 1) {
|
||||
$0.pointee = value.bigEndian
|
||||
}
|
||||
})
|
||||
newData[0] = 0xD2
|
||||
newData.write(value: value.bigEndian, offset: 1)
|
||||
data.append(newData)
|
||||
case .int64(let value):
|
||||
var newData = Data(count: 9)
|
||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
||||
byteContainer.pointee = 0xD3
|
||||
byteContainer.advanced(by: 1).withMemoryRebound(to: Int64.self, capacity: 1) {
|
||||
$0.pointee = value.bigEndian
|
||||
}
|
||||
})
|
||||
newData[0] = 0xD3
|
||||
newData.write(value: value.bigEndian, offset: 1)
|
||||
data.append(newData)
|
||||
|
||||
// MARK: Floats
|
||||
case .float32(let value):
|
||||
var newData = Data(count: 5)
|
||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
||||
byteContainer.pointee = 0xCA
|
||||
byteContainer.advanced(by: 1).withMemoryRebound(to: UInt32.self, capacity: 1) {
|
||||
$0.pointee = value.bitPattern.bigEndian
|
||||
}
|
||||
})
|
||||
newData[0] = 0xCA
|
||||
newData.write(value: value.bitPattern.bigEndian, offset: 1)
|
||||
data.append(newData)
|
||||
case .float64(let value):
|
||||
var newData = Data(count: 9)
|
||||
newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
||||
byteContainer.pointee = 0xCB
|
||||
byteContainer.advanced(by: 1).withMemoryRebound(to: UInt64.self, capacity: 1) {
|
||||
$0.pointee = value.bitPattern.bigEndian
|
||||
}
|
||||
})
|
||||
newData[0] = 0xCB
|
||||
newData.write(value: value.bitPattern.bigEndian, offset: 1)
|
||||
data.append(newData)
|
||||
|
||||
// MARK: Strings
|
||||
case .fixString(let value):
|
||||
data.append(UInt8(value.count) & 0b00011111 | 0b10100000)
|
||||
data.append(value)
|
||||
case .string8(let value):
|
||||
data.append(contentsOf: [0xD9, UInt8(value.count)])
|
||||
data.append(value)
|
||||
case .string16(let value):
|
||||
case .fixString(let utf8Data):
|
||||
precondition(utf8Data.count < 32, "fix strings cannot contain more than 31 bytes")
|
||||
data.append( UInt8(utf8Data.count) | 0b10100000)
|
||||
data.append(utf8Data)
|
||||
case .string8(let utf8Data):
|
||||
data.append(contentsOf: [0xD9, UInt8(utf8Data.count)])
|
||||
data.append(utf8Data)
|
||||
case .string16(let utf8Data):
|
||||
var prefix = Data(count: 3)
|
||||
prefix.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
||||
byteContainer.pointee = 0xDA
|
||||
byteContainer.advanced(by: 1).withMemoryRebound(to: UInt16.self, capacity: 1) {
|
||||
$0.pointee = UInt16(value.count).bigEndian
|
||||
}
|
||||
})
|
||||
prefix[0] = 0xDA
|
||||
prefix.write(value: UInt16(utf8Data.count).bigEndian, offset: 1)
|
||||
data.append(prefix)
|
||||
data.append(value)
|
||||
case .string32(let value):
|
||||
data.append(utf8Data)
|
||||
case .string32(let utf8Data):
|
||||
var prefix = Data(count: 5)
|
||||
prefix.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer<UInt8>) -> Void in
|
||||
byteContainer.pointee = 0xDB
|
||||
byteContainer.advanced(by: 1).withMemoryRebound(to: UInt32.self, capacity: 1) {
|
||||
$0.pointee = UInt32(value.count).bigEndian
|
||||
}
|
||||
})
|
||||
prefix[0] = 0xDB
|
||||
prefix.write(value: UInt32(utf8Data.count).bigEndian, offset: 1)
|
||||
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,20 +10,20 @@ import XCTest
|
|||
@testable import MsgPack
|
||||
|
||||
class MsgPackTests: XCTestCase {
|
||||
|
||||
var encoder: MsgPack.Encoder!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
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()
|
||||
// }
|
||||
|
||||
|
||||
var encoder: MsgPack.Encoder!
|
||||
|
||||
override func setUp() {
|
||||
super.setUp()
|
||||
|
||||
encoder = Encoder()
|
||||
}
|
||||
|
||||
|
||||
func testEncodeTrue() {
|
||||
do {
|
||||
let data = try encoder.encode(true)
|
||||
|
|
@ -99,7 +99,7 @@ class MsgPackTests: XCTestCase {
|
|||
XCTFail(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func testPerformanceOf2MilionUInt32Encodings() {
|
||||
self.measure {
|
||||
for _ in 0 ..< 2000000 {
|
||||
|
|
@ -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 integerData = try encoder.encode(0x0102030405060708)
|
||||
String(integerData[0], radix: 16)
|
||||
try encoder.encode(0x0102030405060708)
|
||||
|
||||
integerData[1]
|
||||
integerData[2]
|
||||
integerData[3]
|
||||
integerData[4]
|
||||
integerData[5]
|
||||
integerData[6]
|
||||
integerData[7]
|
||||
integerData[8]
|
||||
try encoder.encode("Hello")
|
||||
|
||||
let doubleData = try encoder.encode("Hello there 123456789012345678901")
|
||||
String(doubleData[0], radix: 16)
|
||||
try encoder.encode("😇")
|
||||
|
||||
String(doubleData[1], radix: 16)
|
||||
String(doubleData[2], radix: 16)
|
||||
String(doubleData[3], radix: 16)
|
||||
String(doubleData[4], radix: 16)
|
||||
String(doubleData[5], radix: 16)
|
||||
var n: Int?
|
||||
try encoder.encode(n)
|
||||
|
||||
struct Position: Encodable {
|
||||
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