Skip to content

Commit

Permalink
uuid no array allocation for little endianness
Browse files Browse the repository at this point in the history
  • Loading branch information
patrick-zippenfenig committed Dec 8, 2020
1 parent 8f3331b commit 772371e
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 17 deletions.
46 changes: 46 additions & 0 deletions Sources/ClickHouseNIO/ByteBufferExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,23 @@ extension ByteBuffer {
return array
}

mutating func readUuidArray(numRows: Int, endianness: Endianness = .big) -> [UUID]? {
guard readableBytes >= MemoryLayout<UUID>.size * numRows else {
return nil
}
return [UUID](unsafeUninitializedCapacity: numRows) { (buffer, initializedCount) in
let numBytes = readableBytesView.withUnsafeBytes({ $0.copyBytes(to: buffer)})
assert(numBytes / MemoryLayout<UUID>.size == numRows)
moveReaderIndex(forwardBy: numBytes)
if endianness == .little {
for (i,e) in buffer.enumerated() {
buffer[i] = e.swapBytes()
}
}
initializedCount = numRows
}
}

/**
Read bytes as a specific array type. The data type should be continuously stored in memory. E.g. Does not work with strings
TODO: Ensure that this works for all types... endians might also be an issue
Expand All @@ -167,4 +184,33 @@ extension ByteBuffer {
writeInteger(element, endianness: .little)
}
}

/// Write UUID array for clickhouse
mutating func writeUuidArray(_ array: [UUID], endianness: Endianness = .big) {
reserveCapacity(array.count * MemoryLayout<UUID>.size + writableBytes)
for element in array {
switch endianness {
case .big:
let _ = withUnsafeBytes(of: element) {
writeBytes($0)
}
case .little:
let _ = withUnsafeBytes(of: element.swapBytes()) {
writeBytes($0)
}
}


}
}
}

extension UUID {
/// Swap bytes before sending to clickhouse and after retrieval
fileprivate func swapBytes() -> UUID {
let bytes = self.uuid
let b = (bytes.7, bytes.6, bytes.5, bytes.4, bytes.3, bytes.2, bytes.1, bytes.0,
bytes.15, bytes.14, bytes.13, bytes.12, bytes.11, bytes.10, bytes.9, bytes.8)
return UUID(uuid: b)
}
}
20 changes: 3 additions & 17 deletions Sources/ClickHouseNIO/ClickHouseArray.swift
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,7 @@ extension ByteBuffer {
writeBytes($0)
}
} else if let array = array as? [UUID] {
let swaped = array.map { $0.swapBytes() }
let _ = swaped.withUnsafeBytes {
writeBytes($0)
}
writeUuidArray(array, endianness: .little)
} else if let length = fixedLength, let array = array as? [String] {
writeClickHouseFixedStrings(array, length: length)
} else if let array = array as? [String] {
Expand Down Expand Up @@ -254,11 +251,10 @@ extension ByteBuffer {
}
return array
case .uuid:
guard let array: [UUID] = readUnsafeGenericArray(numRows: numRows) else {
guard let array = readUuidArray(numRows: numRows, endianness: .little) else {
return nil
}
let swapped = array.map { $0.swapBytes() }
return swapped
return array
case .fixedString(let fixedStringLength):
var strings = [String]()
strings.reserveCapacity(numRows)
Expand Down Expand Up @@ -302,13 +298,3 @@ extension ByteBuffer {
}
}
}

extension UUID {
/// Swap bytes before sending to clickhouse and after retrieval
fileprivate func swapBytes() -> UUID {
let bytes = self.uuid
let b = ( bytes.7, bytes.6, bytes.5, bytes.4, bytes.3, bytes.2, bytes.1, bytes.0,
bytes.15, bytes.14, bytes.13, bytes.12, bytes.11, bytes.10, bytes.9, bytes.8)
return UUID(uuid: b)
}
}

0 comments on commit 772371e

Please sign in to comment.