# `Mead.Session.Record`
[🔗](https://github.com/albertosca/mead/blob/main/lib/mead/session/record.ex#L1)

The record framing shared by the session files and the ledger journal, and the few file operations both need.

A record is `[4-byte length][4-byte CRC32 of the length][4-byte CRC32 of the payload][term_to_binary payload]`. `scan/1` reads a whole file: a last record that is cut short or fails its payload checksum is what a crash during a write leaves, so it is a `:torn` tail and the valid size stops before it; the length has a checksum of its own, so damage anywhere else, or a payload that does not decode, is `{:error, :corrupt}`.

Payloads are decoded without `:safe`, for the reasons given in `Mead.Session.Store`.

# `create_private`

```elixir
@spec create_private(Path.t()) :: :ok | {:error, term()}
```

Creates an empty file readable only by its owner, unless the path exists, so the content is never readable by anyone else, not even between a write and a later chmod.

# `encode`

```elixir
@spec encode(term()) :: binary()
```

Frames `term` as one record.

# `remove_leftover`

```elixir
@spec remove_leftover(Path.t()) :: :ok | {:error, term()}
```

Removes a file; one that is already missing is not an error.

# `scan`

```elixir
@spec scan(binary()) ::
  {:ok, [term()], non_neg_integer(), :clean | :torn} | {:error, :corrupt}
```

Reads every record of `binary` and returns the terms, the size of the valid prefix, and whether the file ended cleanly or in a torn tail.

# `sync_directory`

```elixir
@spec sync_directory(Path.t()) :: :ok
```

Syncs the directory so a rename is durable. Not every platform lets Erlang open a directory, so a refusal is not a failure: the rename has already happened.

# `truncate`

```elixir
@spec truncate(Path.t(), non_neg_integer()) :: :ok | {:error, term()}
```

Cuts the file at `path` back to `size` bytes.

# `write_synced`

```elixir
@spec write_synced(Path.t(), binary()) :: :ok | {:error, term()}
```

Replaces the content of `path` with `binary` and syncs it.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
