diff --git a/Sources/CDRCodable/Encoder/CDREncoder.swift b/Sources/CDRCodable/Encoder/CDREncoder.swift index 6342f63..ad22d14 100644 --- a/Sources/CDRCodable/Encoder/CDREncoder.swift +++ b/Sources/CDRCodable/Encoder/CDREncoder.swift @@ -23,7 +23,25 @@ final public class CDREncoder { var encoder: _CDREncoder? = _CDREncoder(data: dataBlock) encoder!.userInfo = self.userInfo - try value.encode(to: encoder!) + switch value { + case let value as [Int]: try encoder!.encodeNumericArray(count: value.count, size: MemoryLayout.size, pointer: value.withUnsafeBytes{ $0 }) + case let value as [Int8]: try encoder!.encodeNumericArray(count: value.count, size: MemoryLayout.size, pointer: value.withUnsafeBytes{ $0 }) + case let value as [Int16]: try encoder!.encodeNumericArray(count: value.count, size: MemoryLayout.size, pointer: value.withUnsafeBytes{ $0 }) + case let value as [Int32]: try encoder!.encodeNumericArray(count: value.count, size: MemoryLayout.size, pointer: value.withUnsafeBytes{ $0 }) + case let value as [Int64]: try encoder!.encodeNumericArray(count: value.count, size: MemoryLayout.size, pointer: value.withUnsafeBytes{ $0 }) + case let value as [UInt]: try encoder!.encodeNumericArray(count: value.count, size: MemoryLayout.size, pointer: value.withUnsafeBytes{ $0 }) + case let value as [UInt8]: try encoder!.encodeNumericArray(count: value.count, size: MemoryLayout.size, pointer: value.withUnsafeBytes{ $0 }) + case let value as [UInt16]: try encoder!.encodeNumericArray(count: value.count, size: MemoryLayout.size, pointer: value.withUnsafeBytes{ $0 }) + case let value as [UInt32]: try encoder!.encodeNumericArray(count: value.count, size: MemoryLayout.size, pointer: value.withUnsafeBytes{ $0 }) + case let value as [UInt64]: try encoder!.encodeNumericArray(count: value.count, size: MemoryLayout.size, pointer: value.withUnsafeBytes{ $0 }) + case let value as [Float]: try encoder!.encodeNumericArray(count: value.count, size: MemoryLayout.size, pointer: value.withUnsafeBytes{ $0 }) + case let value as [Double]: try encoder!.encodeNumericArray(count: value.count, size: MemoryLayout.size, pointer: value.withUnsafeBytes{ $0 }) + case let value as Data: + try encoder!.dataStore.write(count: value.count) + encoder!.dataStore.write(data: value) + default: + try value.encode(to: encoder!) + } encoder = nil // call deinit and finalize dataBlock changes. // Final data aligment @@ -61,6 +79,15 @@ final class _CDREncoder { init(data: DataStore) { self.dataStore = data } + @inline(__always) + func encodeNumericArray(count: Int, size: Int, pointer: UnsafeRawBufferPointer) throws { + guard let uint32 = UInt32(exactly: count) else { + let context = EncodingError.Context(codingPath: [], debugDescription: "Cannot encode data of length \(count).") + throw EncodingError.invalidValue(count, context) + } + dataStore.write(value: uint32) + dataStore.data.append(pointer.baseAddress!.assumingMemoryBound(to: UInt8.self), count: count * size) + } } extension _CDREncoder: Encoder { @@ -116,6 +143,14 @@ extension _CDREncoder.DataStore { } self.data.append(contentsOf: value.bytes) } + + func write(count: Int) throws { + guard let uint32 = UInt32(exactly: count) else { + let context = EncodingError.Context(codingPath: [], debugDescription: "Cannot encode data of length \(count).") + throw EncodingError.invalidValue(count, context) + } + write(value: uint32) + } } extension _CDREncodingContainer { diff --git a/Sources/CDRCodable/Encoder/KeyedEncodingContainer.swift b/Sources/CDRCodable/Encoder/KeyedEncodingContainer.swift index debb597..36610a0 100644 --- a/Sources/CDRCodable/Encoder/KeyedEncodingContainer.swift +++ b/Sources/CDRCodable/Encoder/KeyedEncodingContainer.swift @@ -22,7 +22,7 @@ extension _CDREncoder.KeyedContainer: KeyedEncodingContainerProtocol { @inline(__always) private func encodeNumericArray(count: Int, size: Int, pointer: UnsafeRawBufferPointer) throws { try write(count: count) - self.dataStore.data.append(pointer.baseAddress!.assumingMemoryBound(to: UInt8.self), count: count * size) + dataStore.data.append(pointer.baseAddress!.assumingMemoryBound(to: UInt8.self), count: count * size) } // Ignoring optionals as having no analog in the CDR protocol diff --git a/Sources/CDRCodable/Encoder/UnkeyedEncodingContainer.swift b/Sources/CDRCodable/Encoder/UnkeyedEncodingContainer.swift index aec995c..9dcabd7 100644 --- a/Sources/CDRCodable/Encoder/UnkeyedEncodingContainer.swift +++ b/Sources/CDRCodable/Encoder/UnkeyedEncodingContainer.swift @@ -15,12 +15,11 @@ extension _CDREncoder { let count: UInt32 = 0 self.index = dataStore.data.endIndex dataStore.write(value: count) - self.index = dataStore.data.endIndex } deinit { if let count32 = UInt32(exactly: count) { - let range = index-4...size self.dataStore.data.replaceSubrange(range, with: count32.bytes) } }