Encode strings

This commit is contained in:
Damiaan Dufaux 2017-07-31 20:31:37 +02:00
parent 112d35f359
commit 43dff2cc5b
3 changed files with 64 additions and 30 deletions

View file

@ -16,7 +16,7 @@ public class Encoder {
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: serialiser)
var data = Data() var data = Data()
serialiser.storage?.appendTo(data: &data) try serialiser.storage?.appendTo(data: &data)
return data return data
} }
} }
@ -42,7 +42,7 @@ class Serialiser: Swift.Encoder {
extension MsgPack.Serialiser: SingleValueEncodingContainer { extension MsgPack.Serialiser: SingleValueEncodingContainer {
enum Error: Swift.Error { enum Error: Swift.Error {
case notImplemented case notImplemented, stringNotConvertibleToUTF8
} }
func encodeNil() throws { func encodeNil() throws {
@ -54,7 +54,11 @@ extension MsgPack.Serialiser: SingleValueEncodingContainer {
} }
func encode(_ value: Int) throws { 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 { func encode(_ value: Int8) throws {
@ -74,7 +78,11 @@ extension MsgPack.Serialiser: SingleValueEncodingContainer {
} }
func encode(_ value: UInt) throws { 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 { func encode(_ value: UInt8) throws {
@ -102,7 +110,17 @@ extension MsgPack.Serialiser: SingleValueEncodingContainer {
} }
func encode(_ value: String) throws { 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<T : Encodable>(_ value: T) throws { func encode<T : Encodable>(_ value: T) throws {

View file

@ -18,13 +18,11 @@ enum Format {
case positiveInt7(UInt8) case positiveInt7(UInt8)
case negativeInt5(UInt8) case negativeInt5(UInt8)
case uInt (UInt)
case uInt8 (UInt8) case uInt8 (UInt8)
case uInt16(UInt16) case uInt16(UInt16)
case uInt32(UInt32) case uInt32(UInt32)
case uInt64(UInt64) case uInt64(UInt64)
case int (Int)
case int8 (Int8) case int8 (Int8)
case int16(Int16) case int16(Int16)
case int32(Int32) case int32(Int32)
@ -33,6 +31,11 @@ enum Format {
case float32(Float) case float32(Float)
case float64(Double) case float64(Double)
case fixString(Data)
case string8(Data)
case string16(Data)
case string32(Data)
func appendTo(data: inout Data) { func appendTo(data: inout Data) {
switch self { switch self {
@ -81,12 +84,6 @@ enum Format {
} }
}) })
data.append(newData) 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 // MARK: Signed integers
case .int8(let value): case .int8(let value):
@ -125,12 +122,6 @@ enum Format {
} }
}) })
data.append(newData) 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 // MARK: Floats
case .float32(let value): case .float32(let value):
@ -151,6 +142,34 @@ enum Format {
} }
}) })
data.append(newData) 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<UInt8>) -> 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<UInt8>) -> 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)
} }
} }
} }

View file

@ -6,7 +6,6 @@ import Foundation
let encoder = Encoder() let encoder = Encoder()
let integerData = try encoder.encode(0x0102030405060708) let integerData = try encoder.encode(0x0102030405060708)
String(integerData[0], radix: 16) String(integerData[0], radix: 16)
integerData[1] integerData[1]
@ -18,13 +17,11 @@ integerData[6]
integerData[7] integerData[7]
integerData[8] integerData[8]
let doubleData = try encoder.encode(2.5) let doubleData = try encoder.encode("Hello there 123456789012345678901")
String(doubleData[0], radix: 16) String(doubleData[0], radix: 16)
doubleData[1]
doubleData[2] String(doubleData[1], radix: 16)
doubleData[3] String(doubleData[2], radix: 16)
doubleData[4] String(doubleData[3], radix: 16)
doubleData[5] String(doubleData[4], radix: 16)
doubleData[6] String(doubleData[5], radix: 16)
doubleData[7]
doubleData[8]