From afae5bb0bc7f9086d9fb8de2cad959d0c281233d Mon Sep 17 00:00:00 2001 From: Damiaan Dufaux Date: Mon, 31 Jul 2017 18:50:39 +0200 Subject: [PATCH] Encode signed Integers --- MsgPack.xcodeproj/project.pbxproj | 2 +- ...7E3EBF3D-EFD5-47DC-AE25-0C416BB7DA25.plist | 22 +++++++ MsgPack/Encoder.swift | 12 ++-- MsgPack/Format.swift | 64 ++++++++++++++++++- MsgPackTests/MsgPackTests.swift | 17 +++-- Playground.playground/Contents.swift | 18 ++++-- 6 files changed, 110 insertions(+), 25 deletions(-) diff --git a/MsgPack.xcodeproj/project.pbxproj b/MsgPack.xcodeproj/project.pbxproj index 41fa478..7060283 100644 --- a/MsgPack.xcodeproj/project.pbxproj +++ b/MsgPack.xcodeproj/project.pbxproj @@ -353,7 +353,7 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; FRAMEWORK_VERSION = A; - GCC_OPTIMIZATION_LEVEL = 0; + GCC_OPTIMIZATION_LEVEL = fast; INFOPLIST_FILE = MsgPack/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; diff --git a/MsgPack.xcodeproj/xcshareddata/xcbaselines/74FA3B4E1F2C9060005CE521.xcbaseline/7E3EBF3D-EFD5-47DC-AE25-0C416BB7DA25.plist b/MsgPack.xcodeproj/xcshareddata/xcbaselines/74FA3B4E1F2C9060005CE521.xcbaseline/7E3EBF3D-EFD5-47DC-AE25-0C416BB7DA25.plist index 4433778..37fd4ed 100644 --- a/MsgPack.xcodeproj/xcshareddata/xcbaselines/74FA3B4E1F2C9060005CE521.xcbaseline/7E3EBF3D-EFD5-47DC-AE25-0C416BB7DA25.plist +++ b/MsgPack.xcodeproj/xcshareddata/xcbaselines/74FA3B4E1F2C9060005CE521.xcbaseline/7E3EBF3D-EFD5-47DC-AE25-0C416BB7DA25.plist @@ -16,6 +16,28 @@ Local Baseline + testPerformanceOf1MilionUInt32Encodings() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 3.075 + baselineIntegrationDisplayName + Local Baseline + + + testPerformanceOf1MilionUInt32EncodingsUsingClass() + + com.apple.XCTPerformanceMetric_WallClockTime + + baselineAverage + 4.2 + baselineIntegrationDisplayName + Local Baseline + maxPercentRelativeStandardDeviation + 100 + + diff --git a/MsgPack/Encoder.swift b/MsgPack/Encoder.swift index e05c173..a437e6c 100644 --- a/MsgPack/Encoder.swift +++ b/MsgPack/Encoder.swift @@ -54,27 +54,27 @@ extension MsgPack.Serialiser: SingleValueEncodingContainer { } func encode(_ value: Int) throws { - throw Error.notImplemented + storage = .int(value) } func encode(_ value: Int8) throws { - throw Error.notImplemented + storage = .int8(value) } func encode(_ value: Int16) throws { - throw Error.notImplemented + storage = .int16(value) } func encode(_ value: Int32) throws { - throw Error.notImplemented + storage = .int32(value) } func encode(_ value: Int64) throws { - throw Error.notImplemented + storage = .int64(value) } func encode(_ value: UInt) throws { - throw Error.notImplemented + storage = .uInt(value) } func encode(_ value: UInt8) throws { diff --git a/MsgPack/Format.swift b/MsgPack/Format.swift index a5690e8..0f4385c 100644 --- a/MsgPack/Format.swift +++ b/MsgPack/Format.swift @@ -12,26 +12,42 @@ import Foundation enum Format { case `nil` + case boolean(Bool) + case positiveInt7(UInt8) case negativeInt5(UInt8) - case uInt(UInt) - case uInt8(UInt8) + + case uInt (UInt) + case uInt8 (UInt8) case uInt16(UInt16) case uInt32(UInt32) case uInt64(UInt64) + + case int (Int) + case int8 (Int8) + case int16(Int16) + case int32(Int32) + case int64(Int64) func appendTo(data: inout Data) { switch self { + // MARK: Optional case .nil: data.append(0xC0) + + // MARK: Boolean case .boolean(let boolean): data.append(boolean ? 0xC3 : 0xC2) + + // MARK: Small integers (< 8 bit) case .positiveInt7(let value): data.append(value | 0b10000000) case .negativeInt5(let value): data.append(value | 0b11100000) + + // MARK: Unsigned integers case .uInt8(let value): data.append(0xCC) data.append(value) @@ -68,6 +84,50 @@ enum Format { #else Format.uInt64(UInt64(value)).appendTo(data: &data) #endif + + // MARK: Signed integers + case .int8(let value): + var newData = Data(count: 2) + newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer) -> Void in + byteContainer.pointee = 0xD1 + byteContainer.advanced(by: 1).withMemoryRebound(to: Int8.self, capacity: 1) { + $0.pointee = value.bigEndian + } + }) + data.append(newData) + case .int16(let value): + var newData = Data(count: 3) + newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer) -> Void in + byteContainer.pointee = 0xD2 + byteContainer.advanced(by: 1).withMemoryRebound(to: Int16.self, capacity: 1) { + $0.pointee = value.bigEndian + } + }) + data.append(newData) + case .int32(let value): + var newData = Data(count: 5) + newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer) -> Void in + byteContainer.pointee = 0xD2 + byteContainer.advanced(by: 1).withMemoryRebound(to: Int32.self, capacity: 1) { + $0.pointee = value.bigEndian + } + }) + data.append(newData) + case .int64(let value): + var newData = Data(count: 9) + newData.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer) -> Void in + byteContainer.pointee = 0xD3 + byteContainer.advanced(by: 1).withMemoryRebound(to: Int64.self, capacity: 1) { + $0.pointee = value.bigEndian + } + }) + data.append(newData) + case .int(let value): + #if arch(arm) || arch(i386) + Format.int32(Int32(value)).appendTo(data: &data) + #else + Format.int64(Int64(value)).appendTo(data: &data) + #endif } } } diff --git a/MsgPackTests/MsgPackTests.swift b/MsgPackTests/MsgPackTests.swift index 0716113..f81d99f 100644 --- a/MsgPackTests/MsgPackTests.swift +++ b/MsgPackTests/MsgPackTests.swift @@ -33,7 +33,7 @@ class MsgPackTests: XCTestCase { XCTFail(error.localizedDescription) } } - + func testEncodeFalse() { do { let data = try encoder.encode(false) @@ -43,7 +43,7 @@ class MsgPackTests: XCTestCase { XCTFail(error.localizedDescription) } } - + func testEncodeUInt8() { do { let number: UInt8 = 5 @@ -55,7 +55,7 @@ class MsgPackTests: XCTestCase { XCTFail(error.localizedDescription) } } - + func testEncodeUInt16() { do { let data = try encoder.encode(UInt16(0x0506)) @@ -67,7 +67,7 @@ class MsgPackTests: XCTestCase { XCTFail(error.localizedDescription) } } - + func testEncodeUInt32() { do { let data = try encoder.encode(UInt32(0x05060708)) @@ -81,7 +81,7 @@ class MsgPackTests: XCTestCase { XCTFail(error.localizedDescription) } } - + func testEncodeUInt64() { do { let data = try encoder.encode(UInt64(0x0506070809101112)) @@ -100,11 +100,10 @@ class MsgPackTests: XCTestCase { } } - func testPerformanceOf1MilionUInt32Encodings() { - var d = Data() + func testPerformanceOf2MilionUInt32Encodings() { self.measure { - for _ in 0 ..< 1000000 { - Format.uInt32(136315908).appendTo(data: &d) + for _ in 0 ..< 2000000 { + try! encoder.encode(UInt32(136315908)) } } } diff --git a/Playground.playground/Contents.swift b/Playground.playground/Contents.swift index c140377..1a2e7dc 100644 --- a/Playground.playground/Contents.swift +++ b/Playground.playground/Contents.swift @@ -3,15 +3,19 @@ import MsgPack import Foundation -var number: UInt16? = 0x0906 - let encoder = Encoder() -let data = try encoder.encode(number) +let data = try encoder.encode(0x0102030405060708) + +String(data[0], radix: 16) + data[1] data[2] +data[3] +data[4] +data[5] +data[6] +data[7] +data[8] -number = nil - -let data2 = try encoder.encode(number) -data2[0] +try encoder.encode(Int8(6))[1]