# Array module

This document describes the overall design of this module.

## Notation:

- "array" in this module denotes any struct that implements the trait `Array`.
- "mutable array" in this module denotes any struct that implements the trait `MutableArray`.
- words in `code` denote existing terms on this implementation.

## Arrays:

- Every arrow array with a different physical representation MUST be implemented as a struct or
  generic struct.

- An array MAY have its own module. E.g. `primitive/mod.rs`

- An array with a null bitmap MUST implement it as `Option<Bitmap>`

- An array MUST be `#[derive(Clone)]`

- The trait `Array` MUST only be implemented by structs in this module.

- Every child array on the struct MUST be `Box<dyn Array>`.

- An array MUST implement `try_new(...) -> Self`. This method MUST error iff the data does not
  follow the arrow specification, including any sentinel types such as utf8.

- An array MAY implement `unsafe try_new_unchecked` that skips validation steps that are `O(N)`.

- An array MUST implement either `new_empty()` or `new_empty(DataType)` that returns a zero-len of
  `Self`.

- An array MUST implement either `new_null(length: usize)` or `new_null(DataType, length: usize)`
  that returns a valid array of length `length` whose all elements are null.

- An array MAY implement `value(i: usize)` that returns the value at slot `i` ignoring the validity
  bitmap.

- functions to create new arrays from native Rust SHOULD be named as follows:
  - `from`: from a slice of optional values (e.g. `AsRef<[Option<bool>]` for `BooleanArray`)
  - `from_slice`: from a slice of values (e.g. `AsRef<[bool]>` for `BooleanArray`)
  - `from_trusted_len_iter` from an iterator of trusted len of optional values
  - `from_trusted_len_values_iter` from an iterator of trusted len of values
  - `try_from_trusted_len_iter` from an fallible iterator of trusted len of optional values

### Slot offsets

- An array MUST have a `offset: usize` measuring the number of slots that the array is currently
  offsetted by if the specification requires.

- An array MUST implement `fn slice(&self, offset: usize, length: usize) -> Self` that returns an
  offsetted and/or truncated clone of the array. This function MUST increase the array's offset if
  it exists.

- Conversely, `offset` MUST only be changed by `slice`.

The rational of the above is that it enable us to be fully interoperable with the offset logic
supported by the C data interface, while at the same time easily perform array slices within Rust's
type safety mechanism.

### Mutable Arrays

- An array MAY have a mutable counterpart. E.g. `MutablePrimitiveArray<T>` is the mutable
  counterpart of `PrimitiveArray<T>`.

- Arrays with mutable counterparts MUST have its own module, and have the mutable counterpart
  declared in `{module}/mutable.rs`.

- The trait `MutableArray` MUST only be implemented by mutable arrays in this module.

- A mutable array MUST be `#[derive(Debug)]`

- A mutable array with a null bitmap MUST implement it as `Option<MutableBitmap>`

- Converting a `MutableArray` to its immutable counterpart MUST be `O(1)`. Specifically:
  - it must not allocate
  - it must not cause `O(N)` data transformations

  This is achieved by converting mutable versions to immutable counterparts (e.g.
  `MutableBitmap -> Bitmap`).

  The rational is that `MutableArray`s can be used to perform in-place operations under the arrow
  spec.
