Skip to content

Commit

Permalink
Refactoring: rename, @inline optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
DimaRU committed Jan 29, 2024
1 parent 9112d6f commit 9ca9fca
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 56 deletions.
33 changes: 18 additions & 15 deletions Sources/CDRCodable/Encoder/CDREncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ final public class CDREncoder {
public func encode(_ value: Encodable) throws -> Data {
var capacity = MemoryLayout.size(ofValue: value)
capacity = capacity + capacity / 10 + 8
let dataBlock = _CDREncoder.DataBlock(capacity: capacity)
let dataBlock = _CDREncoder.DataStore(capacity: capacity)
var encoder: _CDREncoder? = _CDREncoder(data: dataBlock)
encoder!.userInfo = self.userInfo

Expand All @@ -44,11 +44,11 @@ final public class CDREncoder {
// MARK: -

protocol _CDREncodingContainer {
var data: _CDREncoder.DataBlock { get }
var dataStore: _CDREncoder.DataStore { get }
}

final class _CDREncoder {
final class DataBlock {
final class DataStore {
var data: Data
init(capacity: Int) {
data = Data(capacity: capacity)
Expand All @@ -58,10 +58,10 @@ final class _CDREncoder {
var codingPath: [CodingKey] = []
var userInfo: [CodingUserInfoKey : Any] = [:]
fileprivate var container: _CDREncodingContainer?
var data: DataBlock
var dataStore: DataStore

init(data: DataBlock) {
self.data = data
init(data: DataStore) {
self.dataStore = data
}
}

Expand All @@ -73,7 +73,7 @@ extension _CDREncoder: Encoder {
func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key : CodingKey {
assertCanCreateContainer()

let container = KeyedContainer<Key>(data: self.data, codingPath: self.codingPath, userInfo: self.userInfo)
let container = KeyedContainer<Key>(data: self.dataStore, codingPath: self.codingPath, userInfo: self.userInfo)
self.container = container

return KeyedEncodingContainer(container)
Expand All @@ -82,7 +82,7 @@ extension _CDREncoder: Encoder {
func unkeyedContainer() -> UnkeyedEncodingContainer {
assertCanCreateContainer()

let container = UnkeyedContainer(data: self.data, codingPath: self.codingPath, userInfo: self.userInfo)
let container = UnkeyedContainer(dataStore: self.dataStore, codingPath: self.codingPath, userInfo: self.userInfo)
self.container = container

return container
Expand All @@ -91,28 +91,31 @@ extension _CDREncoder: Encoder {
func singleValueContainer() -> SingleValueEncodingContainer {
assertCanCreateContainer()

let container = SingleValueContainer(data: self.data, codingPath: self.codingPath, userInfo: self.userInfo)
let container = SingleValueContainer(dataStore: self.dataStore, codingPath: self.codingPath, userInfo: self.userInfo)
self.container = container

return container
}
}

extension _CDREncodingContainer {
extension _CDREncoder.DataStore {
@inline(__always)
func write(data: Data) {
self.data.data.append(data)
self.data.append(data)
}

@inline(__always)
func writeByte(_ byte: UInt8) {
self.data.data.append(byte)
self.data.append(byte)
}

@inline(__always)
func write<T>(value: T) where T: FixedWidthInteger {
let aligment = MemoryLayout<T>.alignment
let offset = self.data.data.count % aligment
let offset = self.data.count % aligment
if offset != 0 {
self.data.data.append(contentsOf: Array(repeating: UInt8(0), count: aligment - offset))
self.data.append(contentsOf: Array(repeating: UInt8(0), count: aligment - offset))
}
self.data.data.append(contentsOf: value.bytes)
self.data.append(contentsOf: value.bytes)
}
}
38 changes: 19 additions & 19 deletions Sources/CDRCodable/Encoder/KeyedEncodingContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ extension _CDREncoder {
final class KeyedContainer<Key> where Key: CodingKey {
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey: Any]
var data: DataBlock
var dataStore: DataStore

func nestedCodingPath(forKey key: CodingKey) -> [CodingKey] {
return self.codingPath + [key]
}

init(data: DataBlock, codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
init(data: DataStore, codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
self.data = data
self.dataStore = data
}
}
}
Expand All @@ -25,8 +25,8 @@ extension _CDREncoder.KeyedContainer: KeyedEncodingContainerProtocol {
let context = EncodingError.Context(codingPath: self.codingPath, debugDescription: "Cannot encode data of length \(count).")
throw EncodingError.invalidValue(count, context)
}
write(value: uint32)
self.data.data.append(pointer.baseAddress!.assumingMemoryBound(to: UInt8.self), count: count * size)
dataStore.write(value: uint32)
self.dataStore.data.append(pointer.baseAddress!.assumingMemoryBound(to: UInt8.self), count: count * size)
}

func encodeNil(forKey key: Key) throws {
Expand All @@ -35,9 +35,9 @@ extension _CDREncoder.KeyedContainer: KeyedEncodingContainerProtocol {
func encode(_ value: Bool, forKey key: Key) throws {
switch value {
case false:
writeByte(0)
dataStore.writeByte(0)
case true:
writeByte(1)
dataStore.writeByte(1)
}
}

Expand All @@ -49,25 +49,25 @@ extension _CDREncoder.KeyedContainer: KeyedEncodingContainerProtocol {
let length = data.count + 1

if let uint32 = UInt32(exactly: length) {
write(value: uint32)
dataStore.write(value: uint32)
} else {
let context = EncodingError.Context(codingPath: self.codingPath, debugDescription: "Cannot encode string with length \(length).")
throw EncodingError.invalidValue(value, context)
}
write(data: data)
writeByte(0)
dataStore.write(data: data)
dataStore.writeByte(0)
}

func encode(_ value: Double, forKey key: Key) throws {
write(value: value.bitPattern)
dataStore.write(value: value.bitPattern)
}

func encode(_ value: Float, forKey key: Key) throws {
write(value: value.bitPattern)
dataStore.write(value: value.bitPattern)
}

func encode<T>(_ value: T, forKey key: Key) throws where T : FixedWidthInteger & Encodable {
write(value: value)
dataStore.write(value: value)
}

func encode<T>(_ value: T, forKey key: Key) throws where T : Encodable {
Expand All @@ -89,26 +89,26 @@ extension _CDREncoder.KeyedContainer: KeyedEncodingContainerProtocol {
let context = EncodingError.Context(codingPath: self.codingPath, debugDescription: "Cannot encode data of length \(value.count).")
throw EncodingError.invalidValue(value.count, context)
}
write(value: uint32)
write(data: value)
dataStore.write(value: uint32)
dataStore.write(data: value)
default:
let encoder = _CDREncoder(data: self.data)
let encoder = _CDREncoder(data: self.dataStore)
try value.encode(to: encoder)
}
}

private func nestedSingleValueContainer(forKey key: Key) -> SingleValueEncodingContainer {
let container = _CDREncoder.SingleValueContainer(data: self.data, codingPath: self.nestedCodingPath(forKey: key), userInfo: self.userInfo)
let container = _CDREncoder.SingleValueContainer(dataStore: self.dataStore, codingPath: self.nestedCodingPath(forKey: key), userInfo: self.userInfo)
return container
}

func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {
let container = _CDREncoder.UnkeyedContainer(data: self.data, codingPath: self.nestedCodingPath(forKey: key), userInfo: self.userInfo)
let container = _CDREncoder.UnkeyedContainer(dataStore: self.dataStore, codingPath: self.nestedCodingPath(forKey: key), userInfo: self.userInfo)
return container
}

func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey : CodingKey {
let container = _CDREncoder.KeyedContainer<NestedKey>(data: self.data, codingPath: self.nestedCodingPath(forKey: key), userInfo: self.userInfo)
let container = _CDREncoder.KeyedContainer<NestedKey>(data: self.dataStore, codingPath: self.nestedCodingPath(forKey: key), userInfo: self.userInfo)
return KeyedEncodingContainer(container)
}

Expand Down
28 changes: 14 additions & 14 deletions Sources/CDRCodable/Encoder/SingleValueEncodingContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ extension _CDREncoder {
final class SingleValueContainer {
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey: Any]
var data: DataBlock
var dataStore: DataStore

init(data: DataBlock, codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
init(dataStore: DataStore, codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
self.data = data
self.dataStore = dataStore
}
}
}
Expand All @@ -21,9 +21,9 @@ extension _CDREncoder.SingleValueContainer: SingleValueEncodingContainer {
func encode(_ value: Bool) throws {
switch value {
case false:
writeByte(0)
dataStore.writeByte(0)
case true:
writeByte(1)
dataStore.writeByte(1)
}
}

Expand All @@ -35,32 +35,32 @@ extension _CDREncoder.SingleValueContainer: SingleValueEncodingContainer {
let length = data.count + 1

if let uint32 = UInt32(exactly: length) {
write(value: uint32)
dataStore.write(value: uint32)
} else {
let context = EncodingError.Context(codingPath: self.codingPath, debugDescription: "Cannot encode string with length \(length).")
throw EncodingError.invalidValue(value, context)
}
write(data: data)
writeByte(0)
dataStore.write(data: data)
dataStore.writeByte(0)
}

func encode(_ value: Double) throws {
write(value: value.bitPattern)
dataStore.write(value: value.bitPattern)
}

func encode(_ value: Float) throws {
write(value: value.bitPattern)
dataStore.write(value: value.bitPattern)
}

func encode<T>(_ value: T) throws where T : FixedWidthInteger & Encodable {
write(value: value)
dataStore.write(value: value)
}

func encode(_ value: Data) throws {
let length = value.count
if let uint32 = UInt32(exactly: length) {
write(value: uint32)
write(data: value)
dataStore.write(value: uint32)
dataStore.write(data: value)
} else {
let context = EncodingError.Context(codingPath: self.codingPath, debugDescription: "Cannot encode data of length \(value.count).")
throw EncodingError.invalidValue(value, context)
Expand All @@ -72,7 +72,7 @@ extension _CDREncoder.SingleValueContainer: SingleValueEncodingContainer {
case let data as Data:
try self.encode(data)
default:
let encoder = _CDREncoder(data: self.data)
let encoder = _CDREncoder(data: self.dataStore)
try value.encode(to: encoder)
}
}
Expand Down
16 changes: 8 additions & 8 deletions Sources/CDRCodable/Encoder/UnkeyedEncodingContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ extension _CDREncoder {
private var index: Data.Index
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey: Any]
var data: DataBlock
var dataStore: DataStore

init(data: DataBlock, codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
init(dataStore: DataStore, codingPath: [CodingKey], userInfo: [CodingUserInfoKey : Any]) {
self.codingPath = codingPath
self.userInfo = userInfo
self.data = data
self.dataStore = dataStore
let count: UInt32 = 0
self.index = data.data.endIndex
write(value: count)
self.index = data.data.endIndex
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..<index
self.data.data.replaceSubrange(range, with: count32.bytes)
self.dataStore.data.replaceSubrange(range, with: count32.bytes)
}
}
}
Expand All @@ -33,7 +33,7 @@ extension _CDREncoder.UnkeyedContainer: UnkeyedEncodingContainer {

func encode<T>(_ value: T) throws where T : Encodable {
defer { count += 1 }
let encoder = _CDREncoder(data: self.data)
let encoder = _CDREncoder(data: self.dataStore)
try value.encode(to: encoder)
}

Expand Down

0 comments on commit 9ca9fca

Please sign in to comment.