# mozz.corpus

> A module of mozz_mlake's API.

Corpus management for fuzzing.

Manages the set of seed inputs fed to the mutators.  Deduplication is
performed via FNV-1a 64-bit hashing so duplicate inputs are never stored
twice.  When the corpus exceeds ``MAX_CORPUS_SIZE`` seeds the oldest
entry is evicted (FIFO order).

Example:
    ```mojo
    var corpus = Corpus.default()
    var seed_bytes: List[UInt8] = [0x01, 0x02, 0x03]
    corpus.add(seed_bytes)
    var seed = corpus.pick(rng)   # Span[UInt8, _] borrow
    print(corpus.size())
    ```

## Structs

### `Corpus`

```mojo
struct Corpus
```

A deduplicated, bounded set of fuzzing seed inputs.

Seeds are stored as ``List[UInt8]``.  At most ``MAX_CORPUS_SIZE`` seeds
are kept; inserting beyond the limit evicts the oldest entry (index 0).

Fields:
    _seeds:  Ordered list of seed byte buffers.
    _hashes: FNV-1a 64-bit hash of each seed for O(n) dedup.

Implements: `Movable`

#### `__init__`

```mojo
def __init__(out self, seeds: List[List[UInt8]])
```

Create a corpus pre-populated with ``seeds``.

Duplicate seeds (by content hash) are silently dropped.

Args:

- `seeds`: Initial seed list.

#### `default`

```mojo
def default() -> Self
```

Return a corpus with the four minimal default seeds.

Default seeds: ``[]``, ``[0x00]``, ``[0xFF]``, ``[0x00, 0x00]``.

#### `add`

```mojo
def add(mut self, input: List[UInt8])
```

Add ``input`` to the corpus (deduplication applied).

Args:

- `input`: The bytes to add.

#### `pick`

```mojo
def pick(self, mut rng: Xoshiro256) -> List[UInt8]
```

Return a randomly selected seed (uniform over the corpus).

Biases slightly toward recently added seeds (last 20%) with 40%
probability when the corpus has more than 10 entries.

Args:

- `rng`: PRNG state (advanced in-place).

#### `size`

```mojo
def size(self) -> Int
```

Return the current number of seeds in the corpus.

#### `get`

```mojo
def get(self, i: Int) -> List[UInt8]
```

Return a copy of the seed at index ``i``.

Args:

- `i`: Zero-based seed index; must be in ``[0, size())``.

#### `load`

```mojo
def load(dir: String) -> Self
```

Load all ``*.bin`` files from ``dir`` as seeds.

Files are read in arbitrary order.  Invalid or empty files are
skipped silently.

Args:

- `dir`: Path to the directory containing ``.bin`` seed files.

Raises: Error: If ``dir`` cannot be opened or listed.

#### `list_crashes`

```mojo
def list_crashes(crash_dir: String) -> List[String]
```

Return sorted paths of all crash inputs in ``crash_dir``.

Args:

- `crash_dir`: Directory written by ``fuzz()``'s ``crash_dir`` option.

Raises: Error: If the directory cannot be listed.

#### `load_crash`

```mojo
def load_crash(path: String) -> List[UInt8]
```

Read a single crash input from ``path``.

Convenience wrapper around file I/O for use in replay harnesses.

Args:

- `path`: Path to a ``crash_NNNN.bin`` file produced by ``fuzz()``.

Raises: Error: If the file cannot be opened or read.

#### `save`

```mojo
def save(self, dir: String)
```

Save all corpus seeds to ``dir`` as ``seed_NNNN.bin`` files.

Existing files are not overwritten (new files get the next
available index).

Args:

- `dir`: Destination directory (created if absent).

Raises: Error: If the directory cannot be created or a file cannot be
written.

## Aliases

### `MAX_CORPUS_SIZE`

```mojo
comptime MAX_CORPUS_SIZE = Int(10000)
```
