# Inputs and Outputs

> USearch for Rust

### Arenas

Every output whose length only the call knows, such as matches, rows, products, monoliths and cursor or stream batches, lands in an `Arena` you pass, and the verb answers a view over it without copying.
`Arena::new_in(&executor)` places it where that executor computes, decided once, and `Arena::new()` makes host pages for the calling thread.
Each call rewinds its arena, so the previous call's views die and a steady loop allocates once.
To keep a result past the next call, or to read one while making the next, pass that call another arena.
An arena serves one call at a time, so each deferred call needs its own.
Every call, blocking or deferred, borrows the arena as `&mut Arena` and its result borrows it in turn, so the borrow checker refuses a stale view at compile time and keeps a call's inputs out of the arena it rewinds.
An arena from a VRAM executor holds device memory, which host accessors refuse with `Status::Device`.
It grows, fills and frees on that executor's first stream, so it serves only calls on that executor, any other refused with `Status::Device`, and holds the executor until it drops.

```rust
let mut arena = Arena::new_in(&executor)?;                           // Arena::new() is host pages for the calling thread
for batch in &batches {
    let matches = index.on(&executor).search(batch, 10, &mut arena)?; // rewinds: the last batch's matches are gone
    total += matches.query(0)?.distances.iter().sum::<f64>();
}

let (mut found, mut fetched) = (Arena::new()?, Arena::new()?);       // two live results, two arenas
for &key in index.search(&query, 10, &mut found)?.query(0)?.keys {
    rerank(key, index.get::<f32>(key, &mut fetched)?.view()?);       // rewinds fetched, never found
}

let (mut executors, mut arenas) = (Vec::new(), Vec::new());          // one executor and one arena per submitted call
for _ in &shards {
    executors.push(Executor::for_ram(&[], None, 8)?);
}
for executor in &executors {
    arenas.push(Arena::new_in(executor)?);
}
let mut calls = Vec::new();
for ((shard, executor), arena) in shards.iter().zip(&executors).zip(&mut arenas) {
    calls.push(shard.deferred(executor).search(queries.clone().expect("room for a copy"), 10, arena)?);
}
for call in calls {
    consume(call.await?);                                            // or: call.wait()?
}
```

The library never frees an arena under a call: dropping one waits for the calls writing into it, and a call naming an arena that serves another call finishes with `Status::Contended` and rewinds nothing, so even a leaked `Deferred` leaves it safe.
An arena's `describe()` says where it lives, and on which device.
Fixed-size reports, such as stats, descriptions and `required`, stay plain values, and so does state you carry between calls, like the attention `carry`.

### Rows & Scalars

`rows` borrows a packed slab; a dataset whose rows are padded to a wider pitch passes `MatrixView::from_raw_parts` instead, which takes the byte stride directly.
The scalar type of the input is independent of the stored quantization, so the `f32` slab of the Quickstart lands in an `i8` index with nothing converted beforehand.
The scalar types are NumKong's, so nothing needs re-wrapping to move between the two crates, `f16` and `bf16` included, emulated where the CPU has no native support.

| Rust type                      | `Scalar`                       |
| :----------------------------- | :----------------------------- |
| `f64`, `f32`                   | `F64`, `F32`                   |
| `bf16`, `f16`                  | `BF16`, `F16`                  |
| `e5m2`, `e4m3`, `e3m2`, `e2m3` | `E5M2`, `E4M3`, `E3M2`, `E2M3` |
| `i8`, `i4x2`                   | `I8`, `I4x2`                   |
| `u8`, `u4x2`, `u1x8`           | `U8`, `U4x2`, `U1x8`           |

Initializing an index with a packed quantization and inserting floating-point vectors quantizes on ingest; the `u1x8` type also lets you pass packed bit-vectors directly.

```rust
use numkong::u1x8;

let options = DenseOptions {
    dimensions: 8,
    metric: DenseMetric::Hamming,
    quantization: Scalar::U1x8,
    ..DenseOptions::default()
};
let index = DenseIndex::init_ram(&options, &[])?;
let slab = [u1x8(0b0000_1111), u1x8(0b1111_0000)];
index.insert(&keys, &rows(&slab, 8)?)?;
```

An `insert` batch is all-or-nothing and becomes visible at once, and it overlaps safely with concurrent searches on the same handle.

### Search

Each configurable verb's config converts into its `Dense*Config` struct, whose other fields are named and default to what the C interface derives.
So the bare value is the whole call, as in `search(&queries, 10, &mut arena)`, `insert(&keys, &vectors)` or `save(path)`, and `..DenseSearchConfig::from(10)` reaches every knob.

```rust
let mut arena = Arena::new_in(&executor)?;
let mut stats = DenseTraversalStats::default();
let matches = index.on(&executor).search(&rows(&queries, 768)?, DenseSearchConfig {
    expansion_factor: 128,
    stats: Some(&mut stats),
    ..DenseSearchConfig::from(10)
}, &mut arena)?;
println!("{} distances computed", stats.computed_distances);
```

`query` pairs one query's keys with its distances, nearest first and trimmed to the cells the call wrote, and `iter` walks every query in order.

```rust
for query in matches.iter()? {
    for (key, distance) in query.keys.iter().zip(query.distances) {
        println!("{key} at {distance}");
}
}
```

The breadth of the candidates rides the call rather than the handle, as `expansion_factor` on every config that walks the graph, so a recall sweep is a loop over `ef` values against one immutable index, with no mutation and no synchronization between points.
`traversal: Traversal::Scan` scores every entry instead of walking, on RAM and NVMe handles, which gives that sweep its exact ground truth; a VRAM handle refuses it with `Status::Unsupported`.
`DenseTraversalStats` reports the members visited, the distances computed and the starvation `restarts`, a graph-connectivity signal rather than a cost, overwritten by every call it is passed to.

`use usearch::DenseInsertConfig;`

`use usearch::DenseSearchConfig;`

`use usearch::DenseTraversalStats;`

`use usearch::Arena;`

`use usearch::ArrowArray;`

`use usearch::ArrowColumn;`

`use usearch::ArrowDeviceArray;`

`use usearch::ArrowExport;`

`use usearch::ArrowRows;`

`use usearch::ArrowSchema;`

`use usearch::Element;`

`use usearch::Matches;`

`use usearch::QueryMatches;`

`use usearch::Scalar;`

`use usearch::Traversal;`

`use usearch::*;`

## DenseInsertConfig

The rows of an insertion and the knobs of its walk; see [`DenseVerbs::insert`](https://www.unum.cloud/docs/usearch/rust/metrics.md#insert).

```rust
pub struct DenseInsertConfig<'config, Rows>
```

- `vectors` `Rows`: One row per key, borrowed or owned.
- `expansion_factor` `usize`: The breadth of the candidates the walk explores; zero derives it from the geometry.
- `progress` `Option<&'config mut ProgressCallback<'config>>`: Reports the entries inserted; every entry is claimed before the first report, so a `Break` is
ignored.
- `progress_steps` `usize`: Reports the call makes at most, the last at completion; zero derives to ten.
- `stats` `Option<&'config mut DenseTraversalStats>`: Where the traversal telemetry lands, overwritten by the call.

Implements: `From<Rows>`

## DenseSearchConfig

The matches a search keeps and the knobs of its walk; see [`DenseVerbs::search`](https://www.unum.cloud/docs/usearch/rust/metrics.md#search).

```rust
pub struct DenseSearchConfig<'config>
```

- `wanted` `usize`: Matches kept per query, the "k" in "kANN".
- `expansion_factor` `usize`: The breadth of the candidates the walk explores; zero derives it from the geometry.
- `traversal` `Traversal`: Walks the graph by default; [`Traversal::Scan`](#Scan) scores every entry exactly, on RAM and NVMe
handles, and a VRAM handle refuses it with [`Status::Unsupported`](https://www.unum.cloud/docs/usearch/rust/errors.md#Unsupported).
- `predicate` `Option<&'config Predicate<'config>>`: Admits only the keys it approves; the rest still route the walk, so recall does not
collapse at low selectivity. A VRAM handle refuses one with [`Status::Device`](https://www.unum.cloud/docs/usearch/rust/errors.md#Device).
- `progress` `Option<&'config mut ProgressCallback<'config>>`: Reports the queries resolved and stops wherever it says to; a stopped search reports
[`Status::Cancelled`](https://www.unum.cloud/docs/usearch/rust/errors.md#Cancelled) and leaves no matches.
- `progress_steps` `usize`: Reports the call makes at most, the last at completion; zero derives to ten.
- `stats` `Option<&'config mut DenseTraversalStats>`: Where the traversal telemetry lands, overwritten by the call.

Implements: `From<usize>`

## DenseTraversalStats

Traversal telemetry, fully overwritten by the call it is passed to.

```rust
pub struct DenseTraversalStats
```

- `visited_members` `usize`: Graph members visited by the call.
- `computed_distances` `usize`: Distances computed by the call, diversity re-selections included.
- `restarts` `usize`: Starvation restarts - a graph-connectivity health signal, not a cost counter.
- `missing_hints` `usize`: Hint keys no shard held an entry under; zero unless a search was handed hints.

Implements: `Clone`, `Copy`, `StructuralPartialEq`, `PartialEq`, `Eq`, `Debug`, `Default`

## Arena

Memory the library writes every output whose length scales with a call into, reused across calls.

```rust
pub struct Arena
```

An executor places it where it computes, host pages or its GPU's memory, decided once, and
nothing is allocated until a call writes into it. Every call rewinds and refills it,
invalidating the previous call's outputs, so a steady loop allocates once.
Every verb, blocking or deferred, borrows it as `&mut Arena` and answers outputs that borrow it in turn.
A [`Residency::Vram`](https://www.unum.cloud/docs/usearch/rust/residency.md#Vram) arena holds device memory, so the host accessors of its outputs refuse
with [`Status::Device`](https://www.unum.cloud/docs/usearch/rust/errors.md#Device). It grows, fills and frees on the first stream of the executor that made
it, so it serves only calls on that executor, any other refused with [`Status::Device`](https://www.unum.cloud/docs/usearch/rust/errors.md#Device), and
holds the executor until it drops.

Dropping it waits for the calls still writing into it.

Implements: `From<&'arena mut [Arena](#Arena)>`, `Debug`, `Send`, `Sync`, `Drop`

## new

Makes an arena of host pages for calls on the calling thread.

```rust
pub fn new() -> Result<Self>
```

## new_in

Makes an arena where `executor` computes, serving the calls of its residency, or only those on `executor` itself for a GPU arena.

```rust
pub fn new_in(executor: &Executor) -> Result<Self>
```

## residency

The residency of the executor that made it, whose memory it keeps.

```rust
pub fn residency(&self) -> Residency
```

## ArrowArray

A column's buffers in Apache Arrow's C data interface, laid out as `arrow::ffi::FFI_ArrowArray` and released when dropped.

```rust
pub struct ArrowArray
```

Implements: `Default`, `Drop`, `Send`

## length

Rows the column holds.

```rust
pub fn length(&self) -> i64
```

## ArrowColumn

One Arrow column a producer handed over through the C data interface, which `arrow::ffi` pairs as `FFI_ArrowSchema` and `FFI_ArrowArray`.

```rust
pub unsafe trait ArrowColumn
```

Safety: Both pointers must address live structures laid out as [`ArrowSchema`](#ArrowSchema) and [`ArrowArray`](#ArrowArray) and
following Arrow's C data interface, whose host buffers stay valid and unwritten for as long as
`self` stays borrowed.

## *

The column's type.

```rust
fn schema(&self) -> *const ArrowSchema
```

## array

The column's buffers.

```rust
fn array(&self) -> *const ArrowArray
```

## ArrowDeviceArray

An [`ArrowArray`](#ArrowArray) and the device holding its buffers, as Arrow's C device data interface lays them out.

```rust
pub struct ArrowDeviceArray
```

Implements: `Default`, `Send`

## array

The column itself.

```rust
pub fn array(&self) -> &ArrowArray
```

## ArrowExport

Matches exported as Arrow in place, pinning the arena they sit in until released.

```rust
pub struct ArrowExport<'arena>
```

Rust-only.

## array

The column's buffers and the device holding them.

```rust
pub fn array(&self) -> &ArrowDeviceArray
```

## into_parts

Hands the column over past the arena's borrow, for a consumer that takes the structures by value, refused with [`Status::Device`](https://www.unum.cloud/docs/usearch/rust/errors.md#Device) over device memory, which must be released before its executor drops.

```rust
pub fn into_parts(self) -> Result<(ArrowSchema, ArrowArray)>
```

The arena stays pinned, so a verb naming it fails with
[`Status::Contended`](https://www.unum.cloud/docs/usearch/rust/errors.md#Contended) until the last release, and a dropped arena waits for that release.

## ArrowRows

The rows of one Arrow fixed-size list column, read in place through its buffers, which a verb takes wherever it takes a matrix.

```rust
pub struct ArrowRows<'column, Value>
```

Rust-only.

## new

Views `column`'s rows, refused with [`Status::UnsupportedLayout`](https://www.unum.cloud/docs/usearch/rust/errors.md#UnsupportedLayout) for another Arrow type, [`Status::InvalidArgument`](https://www.unum.cloud/docs/usearch/rust/errors.md#InvalidArgument) for a null, and [`Status::UnknownKind`](https://www.unum.cloud/docs/usearch/rust/errors.md#UnknownKind) for rows of another scalar than `Value`.

```rust
pub fn new<Column: ArrowColumn + ?Sized>(column: &'column Column) -> Result<Self>
```

## ArrowSchema

A column's type in Apache Arrow's C data interface, laid out as `arrow::ffi::FFI_ArrowSchema` and released when dropped.

```rust
pub struct ArrowSchema
```

Implements: `Default`, `Drop`, `Send`

## format

The column's format string, or none once released.

```rust
pub fn format(&self) -> Option<&CStr>
```

## Element

Ties a NumKong storage type to the [`Scalar`](#Scalar) the library tags its buffers with.

```rust
pub unsafe trait Element: StorageElement + 'static
```

The stored quantization is chosen separately in the index options, so an `f32` query may
search an `i8` index - the library converts on the way in.

Rust-only.

Safety: The associated scalar must describe the type's in-memory encoding exactly; the library reads
raw buffers under that tag.

Implementors: - `impl [Element](#Element) for f64`
- `impl [Element](#Element) for f32`
- `impl [Element](#Element) for bf16`
- `impl [Element](#Element) for f16`
- `impl [Element](#Element) for e5m2`
- `impl [Element](#Element) for e4m3`
- `impl [Element](#Element) for e3m2`
- `impl [Element](#Element) for e2m3`
- `impl [Element](#Element) for i8`
- `impl [Element](#Element) for i4x2`
- `impl [Element](#Element) for u8`
- `impl [Element](#Element) for u4x2`
- `impl [Element](#Element) for u1x8`

## SCALAR

The tag the library knows this type by.

```rust
const SCALAR: Scalar;
```

## Matches

The ranked matches a search or a stream pull wrote into the arena it borrows; see [`DenseVerbs::search`](https://www.unum.cloud/docs/usearch/rust/metrics.md#search).

```rust
pub struct Matches<'arena>
```

## queries

Queries the call resolved.

```rust
pub fn queries(&self) -> usize
```

## query

Matches written for one query, refused with [`Status::InvalidArgument`](https://www.unum.cloud/docs/usearch/rust/errors.md#InvalidArgument) when [`query`](https://www.unum.cloud/docs/usearch/rust/linear-algebra.md#query) is not below [`Matches::queries`](https://www.unum.cloud/docs/usearch/rust/linear-algebra.md#queries) and with [`Status::Device`](https://www.unum.cloud/docs/usearch/rust/errors.md#Device) over device memory.

```rust
pub fn query(&self, query: usize) -> Result<QueryMatches<'arena>>
```

## iter

Every query's matches, in query order, refused with [`Status::Device`](https://www.unum.cloud/docs/usearch/rust/errors.md#Device) over device memory.

```rust
pub fn iter(&self) -> Result<impl Iterator<Item = QueryMatches<'arena>>>
```

## to_arrow

Exports every query's matches as one Arrow `LargeListView` of `Struct<key, distance>` in place, refused with [`Status::Contended`](https://www.unum.cloud/docs/usearch/rust/errors.md#Contended) while another call fills the arena.

```rust
pub fn to_arrow(&self) -> Result<ArrowExport<'arena>>
```

The export borrows the arena, so no verb reaches it while the export lives:

```
use usearch::*;
let options = DenseOptions { dimensions: 2, ..DenseOptions::default() };
let index = DenseIndex::init_ram(&#x26;options, &#x26;[])?;
let slab = [1.0f32, 0.0];
let mut arena = Arena::new()?;
let matches = index.search(&#x26;rows(&#x26;slab, 2)?, 1, &#x26;mut arena)?;
let export = matches.to_arrow()?;
index.search(&#x26;rows(&#x26;slab, 2)?, 1, &#x26;mut arena)?;
drop(export);
```

## QueryMatches

One query's matches, or one left row's pairs, trimmed to the cells the call wrote.

```rust
pub struct QueryMatches<'matches>
```

Rust-only.

- `keys` `&'matches [Key]`: The keys written for this query: nearest first for a search, largest score first for a
[`maxsim`](https://www.unum.cloud/docs/usearch/rust/metrics.md#maxsim), and in traversal order for a [`multiply`](https://www.unum.cloud/docs/usearch/rust/metrics.md#multiply).
- `distances` `&'matches [Distance]`: Positionally paired with the keys: distances for a search, summed similarities for a
[`maxsim`](https://www.unum.cloud/docs/usearch/rust/metrics.md#maxsim), and similarities for a [`multiply`](https://www.unum.cloud/docs/usearch/rust/metrics.md#multiply).

Implements: `Clone`, `Copy`, `StructuralPartialEq`, `PartialEq`, `Debug`

## Scalar

Scalar types the indexes store and exchange, named by width and encoding.

```rust
pub enum Scalar
```

Sub-byte kinds pack several dimensions per byte, as their `xN` suffixes spell. The library
reserves the numbering gaps for kinds not yet implemented, so this enum is open.

- `F64` = `1`: IEEE-754 binary64: ±1.80e308, epsilon 2.22e-16, subnormals to 4.94e-324, with infinities and NaNs.
- `F32` = `2`: IEEE-754 binary32: ±3.40e38, epsilon 1.19e-7, subnormals to 1.40e-45, with infinities and NaNs.
- `BF16` = `3`: Truncated f32 - 8-bit exponent, 7-bit mantissa: f32's range at ±3.39e38 and epsilon 7.81e-3, with
infinities and NaNs.
- `F16` = `4`: IEEE-754 binary16: ±65504, epsilon 9.77e-4, subnormals to 5.96e-8, with infinities and NaNs.
- `E5M2` = `5`: FP8 with a 5-bit exponent: ±57344, epsilon 0.25, with infinities and NaNs - f16's dynamic range carried
on two mantissa bits.
- `E4M3` = `6`: FP8 with a 4-bit exponent: ±448, epsilon 0.125, no infinities, and two NaN codes at 0x7F and 0xFF.
- `E3M2` = `7`: FP6 with a 3-bit exponent, byte-aligned with two padding bits: ±28, no infinities or NaNs, so every one
of its 64 codes is a number.
- `E2M3` = `8`: FP6 with a 2-bit exponent, byte-aligned with two padding bits: ±7.5, no infinities or NaNs, and 72% of
its codes outside [-1, 1].
- `I8` = `10`: 8-bit signed integer spanning -128 to 127, every code a number.
- `I4x2` = `11`: Two signed nibbles per byte spanning -8 to 7, even dimensions in the low nibble and odd ones in the high.
- `I32` = `12`: 32-bit signed integer spanning ±2.15e9, every code a number.
- `U8` = `20`: 8-bit unsigned integer spanning 0 to 255, every code a number.
- `U4x2` = `21`: Two unsigned nibbles per byte spanning 0 to 15, even dimensions in the low nibble and odd ones in the high.
- `U1x8` = `22`: Eight single-bit dimensions per byte - the form the Hamming & Jaccard metrics score, where only the
set-bit count of a XOR or AND carries meaning.

Implements: `Clone`, `Copy`, `StructuralPartialEq`, `PartialEq`, `Eq`, `Debug`, `Hash`, `Display`, `FromStr`

## Traversal

How a search reaches the indexed entries it scores.

```rust
pub enum Traversal
```

- `Walk` = `1`: Walks the graph, scoring the entries the expansion reaches - approximate.
- `Scan` = `2`: Scores every entry published when the query's scan starts - exact, on RAM and NVMe handles.

Implements: `Clone`, `Copy`, `StructuralPartialEq`, `PartialEq`, `Eq`, `Debug`, `Default`, `Hash`, `Display`, `FromStr`

## rows

Borrows a packed slab as a row-major matrix of `dimensions`-wide rows.

```rust
pub fn rows<Value: StorageElement>(
    data: &[Value],
    dimensions: usize,
) -> Result<MatrixView<'_, Value>>
```

Slabs whose rows are padded to a wider pitch - memory-mapped datasets, cache-line-aligned
arenas - go through `MatrixView::from_raw_parts` instead, which takes the byte stride.

Rust-only.

## keys_from_arrow

Views the keys of one Arrow `fixed_size_binary(16)` column in place, tagged `arrow.uuid` or not, refused as [`ArrowRows::new`](#new) refuses.

```rust
pub fn keys_from_arrow<Column: ArrowColumn + ?Sized>(column: &Column) -> Result<&[Key]>
```

