From 43dff2cc5be1172d75b76792b430fd8fce94bd58 Mon Sep 17 00:00:00 2001 From: Damiaan Dufaux Date: Mon, 31 Jul 2017 20:31:37 +0200 Subject: [PATCH] Encode strings --- MsgPack/Encoder.swift | 28 +++++++++++++--- MsgPack/Format.swift | 49 +++++++++++++++++++--------- Playground.playground/Contents.swift | 17 ++++------ 3 files changed, 64 insertions(+), 30 deletions(-) diff --git a/MsgPack/Encoder.swift b/MsgPack/Encoder.swift index 61c9c75..5976806 100644 --- a/MsgPack/Encoder.swift +++ b/MsgPack/Encoder.swift @@ -16,7 +16,7 @@ public class Encoder { public func encode(_ value: T) throws -> Data { try value.encode(to: serialiser) var data = Data() - serialiser.storage?.appendTo(data: &data) + try serialiser.storage?.appendTo(data: &data) return data } } @@ -42,7 +42,7 @@ class Serialiser: Swift.Encoder { extension MsgPack.Serialiser: SingleValueEncodingContainer { enum Error: Swift.Error { - case notImplemented + case notImplemented, stringNotConvertibleToUTF8 } func encodeNil() throws { @@ -54,7 +54,11 @@ extension MsgPack.Serialiser: SingleValueEncodingContainer { } func encode(_ value: Int) throws { - storage = .int(value) + #if arch(arm) || arch(i386) + storage = .int32(Int32(value)) + #else + storage = .int64(Int64(value)) + #endif } func encode(_ value: Int8) throws { @@ -74,7 +78,11 @@ extension MsgPack.Serialiser: SingleValueEncodingContainer { } func encode(_ value: UInt) throws { - storage = .uInt(value) + #if arch(arm) || arch(i386) + storage = .uInt32(UInt32(value)) + #else + storage = .uInt64(UInt64(value)) + #endif } func encode(_ value: UInt8) throws { @@ -102,7 +110,17 @@ extension MsgPack.Serialiser: SingleValueEncodingContainer { } func encode(_ value: String) throws { - throw Error.notImplemented + 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) + } } func encode(_ value: T) throws { diff --git a/MsgPack/Format.swift b/MsgPack/Format.swift index 2230f90..1d61b1e 100644 --- a/MsgPack/Format.swift +++ b/MsgPack/Format.swift @@ -10,7 +10,7 @@ import Foundation import Foundation -enum Format { +enum Format { case `nil` case boolean(Bool) @@ -18,13 +18,11 @@ enum Format { case positiveInt7(UInt8) case negativeInt5(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) @@ -32,6 +30,11 @@ enum Format { case float32(Float) case float64(Double) + + case fixString(Data) + case string8(Data) + case string16(Data) + case string32(Data) func appendTo(data: inout Data) { switch self { @@ -81,12 +84,6 @@ enum Format { } }) data.append(newData) - case .uInt(let value): - #if arch(arm) || arch(i386) - Format.uInt32(UInt32(value)).appendTo(data: &data) - #else - Format.uInt64(UInt64(value)).appendTo(data: &data) - #endif // MARK: Signed integers case .int8(let value): @@ -125,12 +122,6 @@ enum Format { } }) 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 // MARK: Floats case .float32(let value): @@ -151,6 +142,34 @@ enum Format { } }) 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): + var prefix = Data(count: 3) + prefix.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer) -> Void in + byteContainer.pointee = 0xDA + byteContainer.advanced(by: 1).withMemoryRebound(to: UInt16.self, capacity: 1) { + $0.pointee = UInt16(value.count).bigEndian + } + }) + data.append(prefix) + data.append(value) + case .string32(let value): + var prefix = Data(count: 5) + prefix.withUnsafeMutableBytes({ (byteContainer: UnsafeMutablePointer) -> Void in + byteContainer.pointee = 0xDB + byteContainer.advanced(by: 1).withMemoryRebound(to: UInt32.self, capacity: 1) { + $0.pointee = UInt32(value.count).bigEndian + } + }) + data.append(prefix) + data.append(value) } } } diff --git a/Playground.playground/Contents.swift b/Playground.playground/Contents.swift index 2fedf46..bae2cb5 100644 --- a/Playground.playground/Contents.swift +++ b/Playground.playground/Contents.swift @@ -6,7 +6,6 @@ import Foundation let encoder = Encoder() let integerData = try encoder.encode(0x0102030405060708) - String(integerData[0], radix: 16) integerData[1] @@ -18,13 +17,11 @@ integerData[6] integerData[7] integerData[8] -let doubleData = try encoder.encode(2.5) +let doubleData = try encoder.encode("Hello there 123456789012345678901") String(doubleData[0], radix: 16) -doubleData[1] -doubleData[2] -doubleData[3] -doubleData[4] -doubleData[5] -doubleData[6] -doubleData[7] -doubleData[8] + +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)