Revision control
Copy as Markdown
Other Tools
// This is a helper for safely working with byte buffers returned from the Rust code.
// A rust-owned buffer is represented by its capacity, its current length, and a
// pointer to the underlying data.
/**
* @suppress
*/
@Structure.FieldOrder("capacity", "len", "data")
open class RustBuffer : Structure() {
// Note: `capacity` and `len` are actually `ULong` values, but JVM only supports signed values.
// When dealing with these fields, make sure to call `toULong()`.
@JvmField var capacity: Long = 0
@JvmField var len: Long = 0
@JvmField var data: Pointer? = null
class ByValue: RustBuffer(), Structure.ByValue
class ByReference: RustBuffer(), Structure.ByReference
internal fun setValue(other: RustBuffer) {
capacity = other.capacity
len = other.len
data = other.data
}
companion object {
internal fun alloc(size: ULong = 0UL) = uniffiRustCall() { status ->
// Note: need to convert the size to a `Long` value to make this work with JVM.
UniffiLib.INSTANCE.{{ ci.ffi_rustbuffer_alloc().name() }}(size.toLong(), status)
}.also {
if(it.data == null) {
throw RuntimeException("RustBuffer.alloc() returned null data pointer (size=${size})")
}
}
internal fun create(capacity: ULong, len: ULong, data: Pointer?): RustBuffer.ByValue {
var buf = RustBuffer.ByValue()
buf.capacity = capacity.toLong()
buf.len = len.toLong()
buf.data = data
return buf
}
internal fun free(buf: RustBuffer.ByValue) = uniffiRustCall() { status ->
UniffiLib.INSTANCE.{{ ci.ffi_rustbuffer_free().name() }}(buf, status)
}
}
@Suppress("TooGenericExceptionThrown")
fun asByteBuffer() =
this.data?.getByteBuffer(0, this.len.toLong())?.also {
it.order(ByteOrder.BIG_ENDIAN)
}
}
/**
* The equivalent of the `*mut RustBuffer` type.
* Required for callbacks taking in an out pointer.
*
* Size is the sum of all values in the struct.
*
* @suppress
*/
class RustBufferByReference : ByReference(16) {
/**
* Set the pointed-to `RustBuffer` to the given value.
*/
fun setValue(value: RustBuffer.ByValue) {
// NOTE: The offsets are as they are in the C-like struct.
val pointer = getPointer()
pointer.setLong(0, value.capacity)
pointer.setLong(8, value.len)
pointer.setPointer(16, value.data)
}
/**
* Get a `RustBuffer.ByValue` from this reference.
*/
fun getValue(): RustBuffer.ByValue {
val pointer = getPointer()
val value = RustBuffer.ByValue()
value.writeField("capacity", pointer.getLong(0))
value.writeField("len", pointer.getLong(8))
value.writeField("data", pointer.getLong(16))
return value
}
}
// This is a helper for safely passing byte references into the rust code.
// It's not actually used at the moment, because there aren't many things that you
// can take a direct pointer to in the JVM, and if we're going to copy something
// then we might as well copy it into a `RustBuffer`. But it's here for API
// completeness.
@Structure.FieldOrder("len", "data")
internal open class ForeignBytes : Structure() {
@JvmField var len: Int = 0
@JvmField var data: Pointer? = null
class ByValue : ForeignBytes(), Structure.ByValue
}