In various cases I need to perform byte manipulation operations on Data and I would like to verify if my solutions to some patterns are valid and if there are simpler approaches.
Append from another Data, given an offset and size
extension Data {
mutating func append(data: Data, offset: Int, size: Int) {
// guard offset and size are valid ...
data.withUnsafeBytes { buf in
self.append(buf.bindMemory(to: UInt8.self).baseAddress!.advanced(by: offset), count: size)
}
}
}
Perform an operation on a portion of Data (e.g. SHA1 or compress)
func process(data: Data, offset: Int, size: Int) -> String {
// guard offset and size are valid ...
let segment: Data = data.withUnsafeBytes { buf in
let mbuf = UnsafeMutablePointer(mutating: buf.bindMemory(to: UInt8.self).baseAddress!)
return Data(bytesNoCopy: mbuf.advanced(by: offset), count: size, deallocator: .none)
}
return segment.sha1()
}
Copy from another Data
extension Data {
mutating func copy(data: Data, size: Int) {
self.withUnsafeMutableBytes { dstBuf in
data.withUnsafeBytes { srcBuf in
memcpy(dstBuf.baseAddress!, srcBuf.baseAddress!, size)
}
}
}
}
Truncate to size
extension Data {
func truncate(size: Int) {
// guard size is valid ...
self.removeLast(self.count - size)
}
}
Move bytes to the front
extension Data {
mutating func move(offset: Int) {
// guard offset is valid ...
let size = self.count - offset
self.withUnsafeMutableBytes { buf in
memmove(buf.baseAddress!, buf.baseAddress!.advanced(by: offset), size)
}
self.truncate(size: size)
}
}
Ideally I'd like to do these things without using unsafe that much, but without doing unnecessary allocations. Thanks for any feedback!