Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Borrowed arguments and text adapters

Foreign borrowing is call-scoped. An extern def parameter &T or &mut T, where T is a supported scalar or opaque pointer, becomes C const T * or T * to initialized storage. Borrowing an opaque pointer passes a pointer to the pointer, suitable for an output parameter.

Native code must not retain these addresses or write through a shared borrow. Mutable arguments obey exclusive borrowing; native code may access exactly the declared scalar’s bytes, with no assumptions about Plenty slot padding.

Text representations

extern def inspect(text: &str as utf8) -> u64 = "inspect_bytes"
extern def length(text: &str as c_string) -> Result[u64, CStrError] = "strlen"
AdapterActual C argumentsConstruction
&str as utf8const uint8_t *data, size_t byte_lenNo allocation; existing bytes including NUL
&str as c_stringconst char *dataOne temporary terminated copy; rejects embedded NUL

Both buffers are read-only and call-scoped: C cannot mutate, retain, or return an address into them. Empty UTF-8 views have length zero and must not be dereferenced. Ordinary strings retain their counted UTF-8 representation.

Any declaration with c_string must return Result[T, CStrError], with T a supported C scalar/pointer or unit. The actual C return type is T; the adapter wraps it in Ok. Conversion runs left to right before native entry. Embedded NUL or allocation failure skips the call, releases earlier buffers, and returns Err; normal return also releases all temporary buffers.

CStrError has allocation-free EmbeddedNul and Allocation(AllocError) variants. It reports conversion failure rather than native status: wrappers must interpret native errors separately.

Returned native strings are not implicitly decoded. Returned pointers need an independent lifetime. Retained/returned buffer loans and copying arbitrary C bytes directly into str are unsupported.

Strided numeric lists and byte views

&list[T] as strided and &mut list[T] as strided, for primitive numeric T, pass three C arguments: a data pointer, size_t len, and size_t stride_bytes. Element i lives at data + i * stride_bytes. The pointer may be null for an empty list and must then not be dereferenced. The stride describes Plenty storage; it is not necessarily sizeof(T).

The adapter does not allocate or pack a temporary collection. Native code may read only each declared scalar’s bytes and may write those bytes only through a mutable loan. It must preserve padding and runtime metadata, cannot resize the list, and cannot retain or return the pointer. Use memcpy or unaligned scalar accesses if the native type requires alignment. No booleans, strings, objects, nested lists or nullable elements are admitted. Exclusive borrowing rules still apply. Current numeric lists store naturally sized elements; generated and runtime reads sign-extend narrow signed values directly, so mutable views need no post-call normalization pass. The optional dataframe engine uses this adapter for bulk transfer.

&[u8] as strided uses the same three C arguments with a byte stride of 1. It borrows a literal, a Bytes buffer, a list[u8], or a subview without allocation or copying. The native call may read exactly len bytes and must not retain the pointer. Empty views must not be dereferenced. Mutable byte views and views of other element types are not admitted by this adapter; mutable numeric lists retain the contract above.