Skip to content

Commit

Permalink
Fix array encode with alignment. More tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
DimaRU committed Mar 5, 2024
1 parent ffef86c commit b1faa02
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 40 deletions.
2 changes: 1 addition & 1 deletion Sources/CDRCodable/Decoder/CDRDecoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ final class DataStore {
final class _CDRDecoder {
var codingPath: [CodingKey] = []
let userInfo: [CodingUserInfoKey : Any]
var container: _CDRDecodingContainer?
fileprivate var container: _CDRDecodingContainer?
var dataStore: DataStore

init(dataStore: DataStore, userInfo: [CodingUserInfoKey : Any]) {
Expand Down
27 changes: 14 additions & 13 deletions Sources/CDRCodable/Encoder/CDREncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,18 @@ final public class CDREncoder {
let dataStore = _CDREncoder.DataStore(capacity: capacity)

switch value {
case let value as [Int]: try dataStore.encodeNumericArray(count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [Int8]: try dataStore.encodeNumericArray(count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [Int16]: try dataStore.encodeNumericArray(count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [Int32]: try dataStore.encodeNumericArray(count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [Int64]: try dataStore.encodeNumericArray(count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [UInt]: try dataStore.encodeNumericArray(count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [UInt8]: try dataStore.encodeNumericArray(count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [UInt16]: try dataStore.encodeNumericArray(count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [UInt32]: try dataStore.encodeNumericArray(count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [UInt64]: try dataStore.encodeNumericArray(count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [Float]: try dataStore.encodeNumericArray(count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [Double]: try dataStore.encodeNumericArray(count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [Int]: try dataStore.encodeNumericArray(alignment: MemoryLayout<Int>.alignment, count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [Int8]: try dataStore.encodeNumericArray(alignment: MemoryLayout<Int8>.alignment, count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [Int16]: try dataStore.encodeNumericArray(alignment: MemoryLayout<Int16>.alignment, count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [Int32]: try dataStore.encodeNumericArray(alignment: MemoryLayout<Int32>.alignment, count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [Int64]: try dataStore.encodeNumericArray(alignment: MemoryLayout<Int64>.alignment, count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [UInt]: try dataStore.encodeNumericArray(alignment: MemoryLayout<UInt>.alignment, count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [UInt8]: try dataStore.encodeNumericArray(alignment: MemoryLayout<UInt8>.alignment, count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [UInt16]: try dataStore.encodeNumericArray(alignment: MemoryLayout<UInt16>.alignment, count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [UInt32]: try dataStore.encodeNumericArray(alignment: MemoryLayout<UInt32>.alignment, count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [UInt64]: try dataStore.encodeNumericArray(alignment: MemoryLayout<UInt64>.alignment, count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [Float]: try dataStore.encodeNumericArray(alignment: MemoryLayout<Float>.alignment, count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as [Double]: try dataStore.encodeNumericArray(alignment: MemoryLayout<Double>.alignment, count: value.count, pointer: value.withUnsafeBytes{ $0 })
case let value as Data:
try dataStore.write(count: value.count)
dataStore.write(data: value)
Expand Down Expand Up @@ -151,12 +151,13 @@ extension _CDREncoder.DataStore {
}

@inline(__always)
func encodeNumericArray(count: Int, pointer: UnsafeRawBufferPointer) throws {
func encodeNumericArray(alignment: Int, count: 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)
}
write(value: uint32)
align(alignment)
data.append(pointer.baseAddress!.assumingMemoryBound(to: UInt8.self), count: pointer.count)
}
}
Expand Down
1 change: 0 additions & 1 deletion Sources/CDRCodable/Encoder/KeyedEncodingContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,5 +161,4 @@ extension _CDREncoder.KeyedContainer: KeyedEncodingContainerProtocol {
}

extension _CDREncoder.KeyedContainer: _CDREncodingContainer {
func closeContainer() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ extension _CDREncoder {
self.userInfo = userInfo
self.dataStore = dataStore
}
func closeContainer() {}
}
}

Expand Down
68 changes: 68 additions & 0 deletions Tests/CDRCodableTests/CDRCodableDecodingArrayTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/////
//// CDRCodableDecodingArrayTests.swift
/// Copyright © 2024 Dmitriy Borovikov. All rights reserved.
//

import XCTest
@testable import CDRCodable

class CDRCodableDecodingArrayTests: XCTestCase {
var decoder: CDRDecoder!

override func setUp() {
self.decoder = CDRDecoder()
}

func testDecodeData() {
let data = Data([5, 0, 0, 0, 0x68, 0x65, 0x6C, 0x6C, 0x6F])
let value = try! decoder.decode(Data.self, from: data)
XCTAssertEqual(value, "hello".data(using: .utf8))
}

func testDecodeArray8() {
let data = Data([3, 0, 0, 0, 0xff, 2, 3, 0])
let value = try! decoder.decode([Int8].self, from: data)
XCTAssertEqual(value, [-1, 2, 3])
}

func testDecodeArray16() {
let data = Data([3, 0, 0, 0, 0xff, 0xff, 2, 0, 3, 0, 0, 0])
let value = try! decoder.decode([Int16].self, from: data)
XCTAssertEqual(value, [-1, 2, 3])
}

func testDecodeArray32() {
let data = Data([3, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 2, 0, 0, 0, 3, 0, 0, 0])
let value = try! decoder.decode([Int32].self, from: data)
XCTAssertEqual(value, [-1, 2, 3])
}

func testDecodeArray64() {
let data = Data([3, 0, 0, 0,
0, 0, 0, 0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2, 0, 0, 0, 0, 0, 0, 0,
3, 0, 0, 0, 0, 0, 0, 0])
let value = try! decoder.decode([Int64].self, from: data)
XCTAssertEqual(value, [-1, 2, 3])
}

func testDecodeArrayFloat() {
let data = Data([3, 0, 0, 0,
0, 0, 0x80, 0x3f,
0, 0, 0, 0x40,
0, 0, 0x40, 0x40])
let value = try! decoder.decode([Float].self, from: data)
XCTAssertEqual(value, [1, 2, 3])
}

func testDecodeArrayDoble() {
let data = Data([3, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0xf0, 0x3f,
0, 0, 0, 0, 0, 0, 0, 0x40,
0, 0, 0, 0, 0, 0, 8, 0x40])
let value = try! decoder.decode([Double].self, from: data)
XCTAssertEqual(value, [1, 2, 3])
}
}
12 changes: 0 additions & 12 deletions Tests/CDRCodableTests/CDRCodableDecodingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,21 +49,9 @@ class CDRCodableDecodingTests: XCTestCase {
XCTAssertEqual(value, 3.14159)
}

func testDecodeArray() {
let data = Data([3, 0, 0, 0, 1, 0, 2, 0, 3, 0])
let value = try! decoder.decode([Int16].self, from: data)
XCTAssertEqual(value, [1, 2, 3])
}

func testDecodeString() {
let data = Data([6, 0, 0, 0, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0])
let value = try! decoder.decode(String.self, from: data)
XCTAssertEqual(value, "hello")
}

func testDecodeData() {
let data = Data([5, 0, 0, 0, 0x68, 0x65, 0x6C, 0x6C, 0x6F])
let value = try! decoder.decode(Data.self, from: data)
XCTAssertEqual(value, "hello".data(using: .utf8))
}
}
68 changes: 68 additions & 0 deletions Tests/CDRCodableTests/CDRCodableEncodingArrayTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/////
//// CDRCodableEncodingArrayTests.swift
/// Copyright © 2024 Dmitriy Borovikov. All rights reserved.
//

import XCTest
@testable import CDRCodable

class CDRCodableEncodingArrayTests: XCTestCase {
var encoder: CDREncoder!

override func setUp() {
self.encoder = CDREncoder()
}

func testEncodeData() {
let data = "hello".data(using: .utf8)
let value = try! encoder.encode(data)
XCTAssertEqual(value, Data([5, 0, 0, 0, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0, 0, 0]))
}

func testEncodeArray8() {
let array: [Int8] = [-1, 2, 3]
let value = try! encoder.encode(array)
XCTAssertEqual(value, Data([3, 0, 0, 0, 0xff, 2, 3, 0]))
}

func testEncodeArray16() {
let array: [Int16] = [-1, 2, 3]
let value = try! encoder.encode(array)
XCTAssertEqual(value, Data([3, 0, 0, 0, 0xff, 0xff, 2, 0, 3, 0, 0, 0]))
}

func testEncodeArray32() {
let array: [Int32] = [-1, 2, 3]
let value = try! encoder.encode(array)
XCTAssertEqual(value, Data([3, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 2, 0, 0, 0, 3, 0, 0, 0]))
}

func testEncodeArray64() {
let array: [Int64] = [-1, 2, 3]
let value = try! encoder.encode(array)
XCTAssertEqual(value, Data([3, 0, 0, 0,
0, 0, 0, 0,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
2, 0, 0, 0, 0, 0, 0, 0,
3, 0, 0, 0, 0, 0, 0, 0]))
}

func testEncodeArrayFloat() {
let array: [Float] = [1, 2, 3]
let value = try! encoder.encode(array)
XCTAssertEqual(value, Data([3, 0, 0, 0,
0, 0, 0x80, 0x3f,
0, 0, 0, 0x40,
0, 0, 0x40, 0x40]))
}

func testEncodeArrayDouble() {
let array: [Double] = [1, 2, 3]
let value = try! encoder.encode(array)
XCTAssertEqual(value, Data([3, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0xf0, 0x3f,
0, 0, 0, 0, 0, 0, 0, 0x40,
0, 0, 0, 0, 0, 0, 8, 0x40]))
}
}
12 changes: 0 additions & 12 deletions Tests/CDRCodableTests/CDRCodableEncodingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,6 @@ class CDRCodableEncodingTests: XCTestCase {
XCTAssertEqual(value, Data([6, 0, 0, 0, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0, 0, 0]))
}

func testEncodeArray() {
let array: [Int16] = [1, 2, 3]
let value = try! encoder.encode(array)
XCTAssertEqual(value, Data([3, 0, 0, 0, 1, 0, 2, 0, 3, 0, 0, 0]))
}

func testEncodeData() {
let data = "hello".data(using: .utf8)
let value = try! encoder.encode(data)
XCTAssertEqual(value, Data([5, 0, 0, 0, 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0, 0, 0]))
}

func testEncodeStruct() {
struct TestStruct: Codable {
let i: Int16
Expand Down

0 comments on commit b1faa02

Please sign in to comment.