Closed
Description
It seems that NSData
is the Foundation type to represent immutable byte arrays, which means it corresponds to ByteString
in purpose. It would be great to have these conversions in the kotlinx-io-bytestring
lib by default.
Example implementation:
/**
* Creates a new [NSData] containing the data copied from this [ByteString].
*/
fun ByteString.toNSData(): NSData = getBackingArrayReference().toNSData()
/**
* Creates a new [NSData] containing the data copied from this [ByteArray].
*/
@OptIn(ExperimentalForeignApi::class, UnsafeNumber::class, BetaInteropApi::class)
private fun ByteArray.toNSData(): NSData = memScoped {
NSData.create(bytes = allocArrayOf(this@toNSData), length = this@toNSData.size.convert())
}
/**
* Creates a new [ByteString] containing the data copied from this [NSData].
*/
fun NSData.toByteString(): ByteString = ByteString.wrap(toByteArray())
/**
* Creates a new [ByteArray] containing the data copied from this [NSData].
*/
@OptIn(ExperimentalForeignApi::class, UnsafeNumber::class)
private fun NSData.toByteArray(): ByteArray {
// length=0 breaks memcpy for some reason (ArrayIndexOutOfBoundsException)
// and it doesn't hurt to skip memcpy anyway if the array is empty
if (length.toInt() == 0) return ByteArray(0)
val nsData = this
return ByteArray(nsData.length.toInt()).apply {
usePinned { pinned ->
memcpy(pinned.addressOf(0), nsData.bytes, nsData.length)
}
}
}
Arguably, the ByteArray
conversions could be part of the stdlib instead, and kotlinx-io-bytestring
could just build on top.