# `Minga.Buffer.SaveState`
[🔗](https://github.com/jsmestad/minga/blob/main/lib/minga/buffer/save_state.ex#L1)

Tracks whether a buffer has diverged from its last saved baseline.

This module owns the pure save-point model: mutation versions, the saved version, dirty calculation, and the saved file fingerprint used by persistence conflict checks. It does not read or write files; `Minga.Buffer.Persistence` still owns storage I/O.

# `metadata`

```elixir
@type metadata() :: {mtime :: integer() | nil, size :: non_neg_integer() | nil}
```

# `saved_content_status`

```elixir
@type saved_content_status() :: :same | :changed | :unknown
```

# `t`

```elixir
@opaque t()
```

# `accept_saved_content`

```elixir
@spec accept_saved_content(t(), metadata(), String.t()) :: t()
```

Accepts replacement content as a new saved baseline and advances the mutation version once.

# `acknowledge_disk_metadata`

```elixir
@spec acknowledge_disk_metadata(t(), metadata()) :: t()
```

Acknowledges the latest disk metadata while preserving the saved content fingerprint.

# `changed_since_saved?`

```elixir
@spec changed_since_saved?(
  t(),
  integer() | nil,
  non_neg_integer() | nil,
  saved_content_status()
) :: boolean()
```

Returns true when the backing file differs from the saved baseline.

# `content_fingerprint`

```elixir
@spec content_fingerprint(String.t()) :: binary()
```

Fingerprints content with the algorithm used to track saved file baselines.

# `dirty?`

```elixir
@spec dirty?(t()) :: boolean()
```

Returns whether the buffer differs from its saved version.

# `file_hash`

```elixir
@spec file_hash(t()) :: binary() | nil
```

Returns the saved content fingerprint, if one is known.

# `file_size`

```elixir
@spec file_size(t()) :: non_neg_integer() | nil
```

Returns the saved file size.

# `loaded`

```elixir
@spec loaded(String.t() | nil, metadata(), String.t()) :: t()
```

Returns a clean save state for content loaded from storage.

# `mark_changed`

```elixir
@spec mark_changed(t()) :: t()
```

Marks the buffer as changed and advances the mutation version.

# `mark_saved`

```elixir
@spec mark_saved(t(), metadata(), String.t()) :: t()
```

Records the current version as the saved baseline.

# `mtime`

```elixir
@spec mtime(t()) :: integer() | nil
```

Returns the saved file mtime.

# `new`

```elixir
@spec new() :: t()
```

Returns a clean save state for a new buffer with no saved file baseline.

# `record_clean_change`

```elixir
@spec record_clean_change(t()) :: t()
```

Records a content change that should not by itself make a clean buffer dirty.

# `restore_version`

```elixir
@spec restore_version(t(), non_neg_integer()) :: t()
```

Restores the mutation version and recalculates dirty state from the saved version.

# `saved_content_fingerprint`

```elixir
@spec saved_content_fingerprint(String.t() | nil, integer() | nil, String.t()) ::
  binary() | nil
```

Returns a saved-content fingerprint only when a path and concrete mtime make the baseline meaningful.

# `saved_version`

```elixir
@spec saved_version(t()) :: non_neg_integer()
```

Returns the saved baseline version.

# `version`

```elixir
@spec version(t()) :: non_neg_integer()
```

Returns the current mutation version.

---

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