// The Swift Programming Language // https://docs.swift.org/swift-book import Foundation public func serializeV1(msg: Message) throws -> Data { let MESSAGE_CAPACITY: Int = try countBytes(msg: msg) var serializedData: Data = Data(count: MESSAGE_CAPACITY) // Serialize Header // UGLY: extrapolate in functions serializedData[0] = msg.version serializedData[1] = msg.messageType.rawValue serializedData[2] = msg.devType.rawValue serializedData[3] = msg.RESERVED serializedData[4...7] = msg.signType.rawValue.data // First 8 bytes serializedData[8...15] = msg.timestamp.data // 8 Bytes serializedData[16...31] = msg.devID.data // 16 bytes serializedData[32...39] = msg.location.x.data // 8 Bytes serializedData[40...47] = msg.location.y.data // 8 Bytes serializedData[48...55] = msg.location.z.data // 8 Bytes var index = 56 for field in msg.fields { serializedData[index...(index + 3)] = UInt32(field.key.count).data serializedData[(index + 4)...(index + 7)] = UInt32(field.key.count).data index += 8 serializedData[index..<(index + field.key.count)] = Data(field.key) index += field.key.count serializedData[index..<(index + field.value.count)] = Data(field.value) index += field.value.count } let paddingBytes = (8 - (index % 8)) % 8 serializedData[index..<(index + paddingBytes)] = Data(count: paddingBytes) index += paddingBytes // Add STOP FIELDS serializedData[index..<(index + 8)] = UInt64(0).data print(UInt64(0).data.base64EncodedString()) index += 8 serializedData[index.. Message { // Serialize Header // UGLY: extrapolate in functions let version: UInt8 = serializedData[0] let messageType: MessageType = MessageType(rawValue: serializedData[1])! let devType: DeviceType = DeviceType(rawValue: serializedData[2])! let RESERVED: UInt8 = serializedData[3] let signType: SignType = SignType(rawValue: serializedData[4...7].uint32)! // First 8 bytes let signBytes = try signatureBytes(signature: signType) let timestamp = serializedData[8...15].timestamp // 8 Bytes let devID = serializedData[16...31].uint128 // 16 bytes let locationX = serializedData[32...39].uint64 // 8 Bytes let locationY = serializedData[40...47].uint64 // 8 Bytes let locationZ = serializedData[48...55].uint64 // 8 Bytes var index = 56 // Deserializing Fields var MORE_FIELDS = true var fields: [Field] = [] while MORE_FIELDS { let nextChunk = serializedData[index..<(index + 8)] let fieldKeyCount = serializedData[index...(index + 4)].uint32 let fieldValueCount = serializedData[(index + 4)..<(index + 8)].uint32 index += 8 let a = nextChunk.uint64 if nextChunk.uint64 == 0 { MORE_FIELDS = false continue } let key = serializedData[index..<(index + Int(fieldKeyCount))].map { value in return value } index += Int(fieldKeyCount) let value = serializedData[index..<(index + Int(fieldValueCount))].map { value in return value } index += Int(fieldValueCount) fields.append(Field(key: key, value: value)) } let paddingBytes = (8 - (index % 8)) % 8 // Skip padding bytes index += paddingBytes let signature = serializedData[index.. Int { /// /// Author: Christian Risi /// /// This is computed as all the bits for the fixed fields /// /// In this case we have: /// - 4 B --> Generic Info /// - 4 B --> Timestamp /// - 8 B --> Device ID /// - 12 B --> Device Location /// - 8 B --> FIELDS STOP let INITIAL_CAPACITY_BYTES: Int = 36 let FIELD_HEADER_CAPACITY_BYTES: Int = 4 var fieldReveservedCapacity: Int = 0 for field in msg.fields { fieldReveservedCapacity += FIELD_HEADER_CAPACITY_BYTES + field.key.count + field.value.count } // UGLY: We are assuming P521 signature let SIGNATURE_CAPACITY_BYTES: Int = try signatureBytes(signature: msg.signType) return (INITIAL_CAPACITY_BYTES + fieldReveservedCapacity + SIGNATURE_CAPACITY_BYTES) } public func signatureBytes(signature: SignType) throws -> Int { switch signature { case .P521: return 132 default: throw CommonError.SIGNATURE_NOT_SUPPORTED } }