# `Monty.Frameworks.Models.Buffer.BufferEncoder`
[🔗](https://github.com/d-led/ex.tbp.monty/blob/v0.1.0/packages/ex_tbp_monty_core/lib/monty/frameworks/models/buffer/buffer_encoder.ex#L1)

Turns a buffer's contents into data a JSON encoder accepts.

Mirrors `tbp/monty/frameworks/models/buffer.py::BufferEncoder`: a registry of
encoders by type, and a default encoding for the shapes Monty stores — so that
a learning module's state can be written to a log or an episode file without
every caller knowing what a pose vector is.

Python resolves an encoder through the type hierarchy (`isinstance` would let
a parent's encoder shadow a child's, so it walks the MRO instead). Elixir has
no inheritance: a struct knows only its own module, so the lookup is exact and
the fallback is the default encoding. That is a difference in mechanism with
the same guarantee — a type that has its own encoder always uses it.

An unknown struct is an error, not a string: silently logging `#Inspect<...>`
makes a missing encoder look like data.

# `encode`

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

Encodes one value.

A registered encoder wins over the defaults and is applied once: what it
returns is expected to be JSON-safe data, the same contract `Jason.Encoder`
has. Lists and maps below it are walked, so a registered type nested inside a
default-shaped value is still encoded by its own encoder.

# `register`

```elixir
@spec register(module(), (term() -&gt; term()) | module()) :: :ok
```

Registers an encoder for a type.

`encoder` is a function of one argument, or a module exporting `encode/1`.

# `unregister`

```elixir
@spec unregister(module()) :: :ok
```

Forgets the encoder registered for a type.

---

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