Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add NSData.toByteString() and ByteString.toNSData() for Apple targets #266

Open
joffrey-bion opened this issue Feb 26, 2024 · 0 comments
Open
Labels
Design enhancement integration An issue related to the integration with other libraries or platform-specific APIs

Comments

@joffrey-bion
Copy link

joffrey-bion commented Feb 26, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design enhancement integration An issue related to the integration with other libraries or platform-specific APIs
Projects
None yet
Development

No branches or pull requests

2 participants