# Batches and Arenas

> UStore for C++

### Arenas

Shorthand and verbs trade convenience for reuse, as in every binding:

- __Shorthand makes a one-off arena.__
  `blobs[key].value()` calls `ustore_arena_init`, reads into that arena, and hands it to its answer, which frees it on destruction, so nothing is copied and no handle keeps state.
  A scalar answer, such as a presence or a degree, is copied out and the arena freed at once.
  The price is one arena per call, so a loop reads through a verb instead.
- __Verbs reuse a caller's arena.__
  `arena_t::make(executor)` places one where its executor computes, or on host pages for calls on the calling thread, and a loop passing it to every call allocates once.
  Every call rewinds it, so its views last until the next call given that arena; to keep them longer, pass that call another arena.

```cpp
auto [arena, arena_status] = arena_t::make(executor);
for (std::span<ustore_key_t const> batch : batches) {
    auto [values, read_status] = db.on(executor).find("blobs")->read(batch, arena);
    if (read_status.failed()) break;
    consume(values); // valid until the next call given `arena`
}
```

An `owned_value_t` derives from the `value_view_t` it holds, so it compares and converts like one, and `view()` slices that plain view off.
Collections, transactions and snapshots hold no arena, so threads share one handle, each passing its own arena.

Walks split the same way: the `keys`, `pairs` and `prefixed` streams own one arena each, while `blobs_cursor_t` and `strings_cursor_t` take the caller's on every pull, so a loop reuses one arena it keeps:

```cpp
auto [cursor, cursor_status] = blobs_cursor_t::make(db.receiver(), blobs);
std::size_t const wanted = 256;
for (std::size_t pulled = wanted; cursor_status.succeeded() && pulled == wanted;) {
    auto [page, page_status] = cursor.next_pairs(wanted, arena);
    if (page_status.failed()) break;
    consume(page.values); // valid until the next call given `arena`
    pulled = page.keys.size();
}
```

`make` opens the walk at the view its receiver reads and from an optional start key, `next` pulls keys alone and `next_pairs` keys with their values, and a page shorter than `wanted` exhausts the walk for good.
`strings_cursor_t::make` takes a prefix and an optional start string, and its `next` pulls strings in the order of their text.

### Receivers and Deferred Calls

The receiver chooses where a call runs, and the verb stays.
`db.on(executor)`, `transaction->on(executor)` and `snapshot->on(executor)` hand out the same collections, proxies and operators, whose calls block on the executor:

```cpp
auto [executor, executor_status] = executor_handle_t::for_ram({.threads = 4});
blobs_collection_t on_executor = *db.on(executor).find("blobs");
status = on_executor[key_from_integer(42)].assign("purpose of life");
```

`deferred(executor)` hands out the deferred twin of every collection, whose verbs mirror [the C calls](/docs/ustore/c/) and answer a `deferred<verb>` once submitted.
`find<graph_collection_t>(name)` picks the twin by modality, read-only at a snapshot, while the deferred database's `[]` takes a binary collection by the identifier `create` or `find` resolved, so addressing it never blocks.
`status()` polls without blocking, `std::move(call).wait()` answers what the call produced, and a `deferred` dropped unwaited waits in its destructor:

```cpp
deferred_database_t later = db.deferred(executor);
auto [arena, arena_status] = arena_t::make(executor);
std::array<ustore_key_t, 2> const keys {key_from_integer(1), key_from_integer(2)};
std::array<sz::string_view_t, 2> const texts {R"({"person": "Alice"})", R"({"person": "Bob"})"};

sz::expected<values_tape_t> values = sz::strings_view_t(texts).gather();
if (!values) return;
deferred<blobs_write_t> writing = later[blobs].write(keys, std::move(values.value));
status = std::move(writing).wait();
deferred<blobs_read_t> reading = later[blobs].read(keys, arena);
expected<values_view_t> read = std::move(reading).wait();
for (value_view_t found : *read)
    std::printf("%zu bytes\n", found.size());
```

Documents are written and read whole or by field, under any modification, and a gather answers a table together with the rows and columns it views outside the arena:

```cpp
deferred_docs_collection_t people = *later.find<docs_collection_t>("people");
sz::expected<values_tape_t> documents = sz::strings_view_t(texts).gather();
if (!documents) return;
status = people.write(keys, std::move(documents.value), {}, ustore_docs_modify_merge_k).wait();

std::array<sz::string_view_t, 1> const columns {"person"};
sz::expected<values_tape_t> fields = sz::strings_view_t(columns).gather();
if (!fields) return;
auto gathered = people.gather(keys, std::move(fields.value), std::array {ustore_docs_field_type_string_k}, arena).wait();
auto names = gathered->table.column(0).as<std::string_view>();
```

Graphs read edges and degrees for one role of every vertex, and write and remove edges and vertices:

```cpp
deferred_graph_collection_t graph = *later.find<graph_collection_t>("graph");
std::array<edge_t, 2> const chain {edge_t {key_from_integer(1), key_from_integer(2)}, edge_t {key_from_integer(2), key_from_integer(3)}};
status = graph.write_edges(chain).wait();
expected<edges_view_t> leaving = graph.read_edges(keys, arena, ustore_vertex_role_source_k).wait();
expected<std::span<ustore_vertex_degree_t const>> degrees = graph.degrees(keys, arena).wait();
```

Strings are written and read in batches, and a scan answers a page of strings for every prefix:

```cpp
deferred_strings_collection_t words = *later.find<strings_collection_t>("words");
std::array<sz::string_view_t, 2> const spellings {"apple", "apricot"};
sz::expected<values_tape_t> strings = sz::strings_view_t(spellings).gather();
sz::expected<values_tape_t> meanings = sz::strings_view_t(texts).gather();
sz::expected<values_tape_t> prefixes = sz::strings_view_t(std::span {spellings}.first(1)).gather();
if (!strings || !meanings || !prefixes) return;
status = words.write(std::move(strings.value), std::move(meanings.value)).wait();
expected<strings_scan_t::finished_t> scanned = words.scan(std::move(prefixes.value), 16, arena).wait();
```

A transaction defers its own verbs too, `reset` among them:

```cpp
deferred_transaction_t deferred_transaction = transaction->deferred(executor);
status = deferred_transaction.find("blobs")->remove(keys).wait();
expected<read_stamp_t> staged = deferred_transaction.stage().wait();
expected<commit_stamp_t> stamp = deferred_transaction.commit().wait();
```

The deferred database also creates, drops and lists collections, and describes, clears and compacts itself, while the deferred snapshot saves itself through `save`.
Opening blocks instead, as every constructor does: `init_ram`, `open_ram`, `open_rocksdb`, `view_rocksdb` and `open_leveldb` take the executor to block on as their last argument, while `open_nvme` blocks on the executor its options name and reads how to move bytes from it once:

```cpp
expected<database_t> opened = database_t::open_rocksdb({.directory = bytes_of("/var/lib/ustore")}, executor);
```

Either way the database runs its own calls on the calling thread until a receiver names an executor.

- __Deferred inputs are owned, arenas borrowed.__
  Keys, vertices, edges and column types come as a `std::array` or an `st::vector`, and values, strings and fields as a `values_tape_t`, StringZilla's `sz::strings_t` that `sz::strings_view_t::gather` fills, so a borrowed span or view does not compile.
  The arena comes as an `arena_t&`, borrowed until the call is final, which is safe because freeing an arena waits for the deferred calls naming it, while a temporary arena does not compile.
- __Submission copies the arguments.__
  A `deferred<verb>` keeps one heap block that never moves, holding the outcome, the owned inputs and the outputs the call writes through, while the C argument structure dies on the stack it was filled on.
  `status()` polls through `ustore_outcome_status`, and `wait()` and the destructor wait.
- __Answers view the arena.__
  A finished read answers the views a blocking one does, valid until the next call given that arena, and a finished gather owns its rows, columns and field names beside a table whose cells stay in the arena.
- __A transaction serves one call at a time.__
  Wait on one deferred call through it before submitting the next, which otherwise finishes at once with `status_code_t::contended_k`.
- __The wrappers have no life of their own.__
  They start no threads, keep no counts and hold no hidden arena: freeing a database, transaction or snapshot waits in C for the deferred calls naming it.

`#include <ustore/status.hpp>`

`#include <ustore/db.hpp>`

`#include <ustore/docs_collection.hpp>`

`#include <ustore/graph_collection.hpp>`

`#include <ustore/types.hpp>`

`#include <ustore/blobs_collection.hpp>`

`#include <ustore/ranges.hpp>`

`#include <ustore/strings_collection.hpp>`

## deferred_blobs_read_collection_t

A binary collection that only reads, whose verbs submit to an executor and answer deferred calls, as a snapshot offers it.

```cpp
class deferred_blobs_read_collection_t
```

Every plain input a verb reads moves into the call, so nothing it borrowed can go before the call is final, while an arena is borrowed, since freeing it waits for the call.

## deferred_blobs_collection_t

A binary collection whose verbs submit to an executor and answer deferred calls, reading and writing the head or a transaction.

```cpp
class deferred_blobs_collection_t
```

## deferred_docs_collection_t

A collection of JSON documents whose verbs submit to an executor and answer deferred calls, reading and writing the head or a transaction.

```cpp
class deferred_docs_collection_t
```

## deferred_graph_read_collection_t

A graph collection that only reads, whose verbs submit to an executor and answer deferred calls, as a snapshot offers it.

```cpp
class deferred_graph_read_collection_t
```

Every plain input a verb reads moves into the call, so nothing it borrowed can go before the call is final, while an arena is borrowed, since freeing it waits for the call.

## deferred_strings_read_collection_t

A collection keyed by strings that only reads, whose verbs submit to an executor and answer deferred calls, as a snapshot offers it.

```cpp
class deferred_strings_read_collection_t
```

Every plain input a verb reads moves into the call, so nothing it borrowed can go before the call is final, while an arena is borrowed, since freeing it waits for the call.

## deferred_strings_collection_t

A collection keyed by strings whose verbs submit to an executor and answer deferred calls, reading and writing the head or a transaction.

```cpp
class deferred_strings_collection_t
```

## arena_t

Owns an arena made where an executor computes, which the C ABI fills with results, freeing it on destruction.

```cpp
class arena_t
```

## owned

A view of what one call wrote into an arena made for that call alone, which it frees on destruction, as shorthand with no place for an arena answers.

```cpp
template <typename view_type_>
class owned
```

It moves but never copies, and `view` slices off the plain view.

## receiver_t

What every call made through one receiver names before its inputs: the database, the executor that runs it, and the transaction or snapshot its reads see and its writes go through.

```cpp
struct receiver_t
```

- `database` `ustore_database_t`: An open database.
- `executor` `ustore_executor_t`: Executor that runs the calls, where `nullptr` runs them on the calling thread.
- `transaction` `ustore_transaction_t`: Transaction the writes go through and the reads see, or `nullptr` for the head.
- `snapshot` `ustore_snapshot_t`: Snapshot the reads see when no transaction is named, or `nullptr` for the head.

## progress_arg_t

A callable lent to a long call as the C ABI receives it, a callback and the state it reads, or neither for a call nothing watches.

```cpp
class progress_arg_t
```

The call borrows the callable until it is final.

- `callback` `ustore_progress_callback_t`: Reports the advance of the call, or `nullptr` for a call nothing watches.
- `state` `void *`: The callable that `callback` calls.

## deferred

A call submitted to an executor, owning the one heap block that holds its outcome, every plain input it reads and every output it writes through, which never moves until the call is final.

```cpp
template <typename verb_type_>
class deferred
```

Submission copies the C arguments, so they live only on the stack of [`submit`](#submit), while everything they point to lives in the block. An arena is a handle the call borrows, since freeing it waits for the call. [`status`](#status) polls without blocking, and [`wait`](#wait) blocks until the call is final and hands over what it produced. The destructor waits too, so nothing the call reads goes away under it, and a block that could not be allocated reads as a call that finished with `status_code_t::out_of_memory_k`.

## deferred

```cpp
deferred(deferred && other) noexcept;
```

```cpp
deferred(deferred const &)=delete;
```

## operator=

```cpp
deferred & operator=(deferred && other) noexcept;
```

```cpp
deferred & operator=(deferred const &)=delete;
```

## ~deferred

```cpp
~deferred() noexcept;
```

## status

The status of the call, polled through `ustore_outcome_status:` `status_code_t::deferred_k` until final.

```cpp
status_code_t status() const noexcept;
```

## wait

Blocks until the call is final, then answers what it produced, or the status explaining why it did not.

```cpp
answer_t wait() &&noexcept;
```

## submit

Moves `inputs` into a new block, lets `prepare` fill the C arguments from them, and submits a copy.

```cpp
template <typename prepare_type_, typename... inputs_types_>
deferred submit(
    prepare_type_ && prepare,
    inputs_types_... inputs) noexcept;
```

- `prepare` (in): Fills the C arguments from the verb and the owned inputs, pointing them only into the block, and answers a status that becomes the final one, with nothing submitted, when it fails.
- `inputs` (in): Everything the call reads, which the block owns until the call is final.

## deferred_database_t

The head of a database, whose verbs submit to an executor and answer deferred calls, as `[database_ref_t::deferred](https://www.unum.cloud/docs/ustore/cpp/snapshots.md#deferred)` hands it out.

```cpp
class deferred_database_t
```

## deferred_database_t

```cpp
deferred_database_t(receiver_t receiver) noexcept;
```

## find

The collection named `name` at the head, as the deferred twin of `collection_type_`.

```cpp
template <typename collection_type_ = blobs_collection_t>
expected<typename collection_type_::deferred_t> find(
    std::string_view name) const noexcept;
```

## operator[]

The binary collection `collection` identifies, resolved beforehand, so addressing it never blocks.

```cpp
deferred_blobs_collection_t operator[](
    ustore_collection_id_t collection) const noexcept;
```

## create

Creates a collection holding the modality of `collection_type_` under `name`, which the call copies and no other collection may carry, answering its identifier.

```cpp
template <typename collection_type_ = blobs_collection_t>
deferred<create_t> create(std::string_view name) const noexcept;
```

## drop

Drops what `mode` names of the collection `collection` identifies.

```cpp
deferred<drop_t> drop(
    ustore_collection_id_t collection,
    ustore_drop_mode_t mode = ustore_drop_collection_k) const noexcept;
```

## collections

Lists the collections at the head, with their identifiers in `arena`, borrowed until the call is final.

```cpp
deferred<list_t> collections(arena_t & arena) const noexcept;
```

## describe

Reports the engine of the database, what it supports and how much it holds.

```cpp
deferred<describe_t> describe() const noexcept;
```

## clear

Empties every collection at once, as `mode` names.

```cpp
deferred<clear_t> clear(ustore_drop_mode_t mode) const noexcept;
```

## compact

Reclaims the space overwritten and removed data still takes, reporting its advance to `progress`, borrowed until the call is final.

```cpp
deferred<compact_t> compact(
    progress_arg_t progress = {}) const noexcept;
```

## deferred_docs_read_collection_t

A collection of JSON documents that only reads, whose verbs submit to an executor and answer deferred calls, as a snapshot offers it.

```cpp
class deferred_docs_read_collection_t
```

Every plain input a verb reads moves into the call, so nothing it borrowed can go before the call is final, while an arena is borrowed, since freeing it waits for the call.

## deferred_docs_read_collection_t

```cpp
deferred_docs_read_collection_t() noexcept=default;
```

```cpp
deferred_docs_read_collection_t(
    receiver_t receiver,
    ustore_collection_id_t collection) noexcept;
```

## read

Reads the documents of [`keys`](https://www.unum.cloud/docs/ustore/cpp/reads-and-writes.md#keys), or the fields `fields` name inside them, into `arena`.

```cpp
template <owned_array_concept<ustore_key_t> keys_type_>
deferred<docs_read_t> read(
    keys_type_ keys,
    arena_t & arena,
    values_tape_t fields = {},
    ustore_docs_field_type_t type = ustore_docs_field_type_json_k,
    ustore_watch_t watch = ustore_watch_keys_k) const noexcept;
```

- `keys` (in): Keys to read, owned by the call until it is final.
- `arena` (in): Memory the values land in, borrowed until the call is final, which the answer views.
- `fields` (in): None for whole documents, one field for every key, or one per key.
- `type` (in): Format the values are exported in.
- `watch` (in): Whether a read inside a transaction records the keys for conflicts.

Statuses: - `status_code_t::invalid_argument_k` The `fields` are neither none, one, nor one per key.

## gist

Lists the unique paths to the leaves of the documents of [`keys`](https://www.unum.cloud/docs/ustore/cpp/reads-and-writes.md#keys) into `arena`.

```cpp
template <owned_array_concept<ustore_key_t> keys_type_>
deferred<docs_gist_t> gist(
    keys_type_ keys,
    arena_t & arena,
    ustore_watch_t watch = ustore_watch_keys_k) const noexcept;
```

- `keys` (in): Keys of the documents, owned by the call until it is final.
- `arena` (in): Memory the paths land in, borrowed until the call is final, which the answer views.
- `watch` (in): Whether a read inside a transaction records the keys for conflicts.

## gather

Gathers the fields `fields` name from the documents of [`keys`](https://www.unum.cloud/docs/ustore/cpp/reads-and-writes.md#keys) into `arena`, as a table typed at runtime.

```cpp
template <owned_array_concept<ustore_key_t> keys_type_, owned_array_concept<ustore_docs_field_type_t> types_type_>
deferred<docs_gather_t> gather(
    keys_type_ keys,
    values_tape_t fields,
    types_type_ types,
    arena_t & arena,
    ustore_watch_t watch = ustore_watch_keys_k) const noexcept;
```

- `keys` (in): Keys of the documents, one per row.
- `fields` (in): Fields to gather, one per column, which the finished gather hands back.
- `types` (in): Type every column converts its field into, one per field.
- `arena` (in): Memory the columns land in, borrowed until the call is final, which the table views.
- `watch` (in): Whether a read inside a transaction records the keys for conflicts.

Statuses: - `status_code_t::invalid_argument_k` The `types` and `fields` differ in count.

## deferred_graph_collection_t

A graph collection whose verbs submit to an executor and answer deferred calls, reading and writing the head or a transaction.

```cpp
class deferred_graph_collection_t
```

## write_edges

Writes [`edges`](https://www.unum.cloud/docs/ustore/cpp/graphs.md#edges) between existing or new vertices.

```cpp
template <owned_array_concept<edge_t> edges_type_>
deferred<graph_write_edges_t> write_edges(
    edges_type_ edges,
    ustore_durability_t durability = ustore_durability_buffered_k) const noexcept;
```

- `edges` (in): Edges to write, owned by the call until it is final.
- `durability` (in): Whether the call finishes only after the data reaches the disk.

## remove_edges

Removes [`edges`](https://www.unum.cloud/docs/ustore/cpp/graphs.md#edges), keeping their vertices.

```cpp
template <owned_array_concept<edge_t> edges_type_>
deferred<graph_remove_edges_t> remove_edges(
    edges_type_ edges,
    ustore_durability_t durability = ustore_durability_buffered_k) const noexcept;
```

- `edges` (in): Edges to remove, owned by the call until it is final.
- `durability` (in): Whether the call finishes only after the data reaches the disk.

## write_vertices

Writes `vertices` without edges, keeping those already present.

```cpp
template <owned_array_concept<ustore_key_t> vertices_type_>
deferred<graph_write_vertices_t> write_vertices(
    vertices_type_ vertices,
    ustore_durability_t durability = ustore_durability_buffered_k) const noexcept;
```

- `vertices` (in): Vertices to write, owned by the call until it is final.
- `durability` (in): Whether the call finishes only after the data reaches the disk.

## remove_vertices

Removes `vertices` together with every edge they belong to.

```cpp
template <owned_array_concept<ustore_key_t> vertices_type_>
deferred<graph_remove_vertices_t> remove_vertices(
    vertices_type_ vertices,
    ustore_vertex_role_t role = ustore_vertex_role_any_k,
    ustore_durability_t durability = ustore_durability_buffered_k) const noexcept;
```

- `vertices` (in): Vertices to remove, owned by the call until it is final.
- `role` (in): Role every vertex plays, which only joining graphs need.
- `durability` (in): Whether the call finishes only after the data reaches the disk.

## deferred_snapshot_t

A snapshot whose verbs submit to an executor and answer deferred calls, reading only, as `[snapshot_ref_t::deferred](https://www.unum.cloud/docs/ustore/cpp/snapshots.md#deferred)` hands it out.

```cpp
class deferred_snapshot_t
```

## deferred_snapshot_t

```cpp
deferred_snapshot_t(receiver_t receiver) noexcept;
```

## find

The collection named `name` at the snapshot, as the deferred twin of the read-only twin of `collection_type_`.

```cpp
template <typename collection_type_ = blobs_collection_t>
expected<typename collection_type_::read_only_t::deferred_t> find(
    std::string_view name) const noexcept;
```

## save

Saves the snapshot as a new database at `path`, which the call copies, reporting the bytes saved to `progress`, borrowed until the call is final.

```cpp
deferred<save_t> save(
    std::string_view path,
    progress_arg_t progress = {}) const noexcept;
```

## flush

Makes every commit that returned before this call durable.

```cpp
deferred<flush_t> flush() const noexcept;
```

## deferred_transaction_t

A transaction whose verbs submit to an executor and answer deferred calls, as `[transaction_ref_t::deferred](https://www.unum.cloud/docs/ustore/cpp/snapshots.md#deferred)` hands it out.

```cpp
class deferred_transaction_t
```

A transaction serves one call at a time, so a caller waits on one deferred call before submitting the next.

## deferred_transaction_t

```cpp
deferred_transaction_t(receiver_t receiver) noexcept;
```

## find

The collection named `name`, read and written through the transaction, as the deferred twin of the read-only twin of `collection_type_`.

```cpp
template <typename collection_type_ = blobs_collection_t>
expected<typename collection_type_::deferred_t> find(
    std::string_view name) const noexcept;
```

## reset

Clears the transaction for reuse, keeping its memory and starting a new generation.

```cpp
deferred<reset_t> reset() const noexcept;
```

## stage

Stages the transaction as the first phase of a two-phase commit, answering the stamp it reads at.

```cpp
deferred<stage_t> stage() const noexcept;
```

## commit

Commits every update of the transaction, or none of them, answering the commit's stamp.

```cpp
deferred<commit_t> commit(
    ustore_durability_t durability = ustore_durability_buffered_k) const noexcept;
```

## rollback

Withdraws a stage, keeping the reads and writes.

```cpp
deferred<rollback_t> rollback() const noexcept;
```

## executor_handle_t

Owns an executor, the threads or I/O rings that run calls on any number of databases, and frees it once drained.

```cpp
class executor_handle_t
```

It never copies, and outlives every call submitted to it.

## executor_handle_t

```cpp
executor_handle_t() noexcept=default;
```

```cpp
executor_handle_t(executor_handle_t const &)=delete;
```

```cpp
executor_handle_t(executor_handle_t && other) noexcept;
```

## operator=

```cpp
executor_handle_t & operator=(executor_handle_t const &)=delete;
```

```cpp
executor_handle_t & operator=(executor_handle_t && other) noexcept;
```

## ~executor_handle_t

```cpp
~executor_handle_t() noexcept;
```

## drain

Waits for every call submitted before the drain, leaving the threads in `mood` whenever they go idle.

```cpp
status_t drain(ustore_mood_t mood = ustore_mood_parked_k) noexcept;
```

## for_ram

Spawns host threads for the RAM, RocksDB and LevelDB engines.

```cpp
expected<executor_handle_t> for_ram(
    ustore_executor_for_ram_t options = {}) noexcept;
```

## on_pool

Borrows the ForkUnion pool `options` name for the RAM, RocksDB and LevelDB engines.

```cpp
expected<executor_handle_t> on_pool(
    ustore_executor_on_pool_t options) noexcept;
```

## for_nvme

Spawns threads for the NVMe engine, each owning its own I/O ring, which tell the databases opened on them how to move bytes and borrow the VRAM executor `options` name for compactions.

```cpp
expected<executor_handle_t> for_nvme(
    ustore_executor_for_nvme_t options = {}) noexcept;
```

## for_vram

Spawns one host thread driving the NVIDIA or AMD device `options` name by its UStore ordinal, on which an NVMe database compacts when the device is NVIDIA.

```cpp
expected<executor_handle_t> for_vram(
    ustore_executor_for_vram_t options = {}) noexcept;
```

## transform_n

Writes the first `count` transformed elements into `output`.

```cpp
template <typename output_iterator_type_, typename iterator_type_, typename transform_type_ = std::identity>
void transform_n(
    iterator_type_ begin,
    std::size_t count,
    output_iterator_type_ output,
    transform_type_ transform = {});
```

## all_ascending

Whether the first `count` elements strictly ascend.

```cpp
template <typename iterator_type_>
bool all_ascending(iterator_type_ begin, std::size_t count);
```

## sort_and_deduplicate

Sorts the elements, gathers the distinct ones at the front, and returns how many there are.

```cpp
template <std::random_access_iterator iterator_type_>
requires std::sortable<iterator_type_>
std::size_t sort_and_deduplicate(
    iterator_type_ begin,
    iterator_type_ end);
```

## in_one_off_arena

Runs `verb` on an arena made for it alone where `executor` computes, as shorthand with no place for an arena does, answering a scalar copied out of that arena or a view that owns it.

```cpp
template <typename verb_type_>
auto in_one_off_arena(
    ustore_executor_t executor,
    verb_type_ && verb) noexcept;
```

