# `Portals.TermExtensions`
[🔗](https://github.com/Ziinc/portals/blob/v0.1.0/lib/portals/term_extensions.ex#L1)

Erlang-specific value extensions layered on top of core MessagePack.

Each extension is a MessagePack `ext` payload tagged with one of the type
codes below. Encoding is always safe. Decoding never creates atoms and
never fabricates PIDs/references from arbitrary bytes: it delegates to
`:erlang.binary_to_term/2` with the `:safe` option (which refuses to
create new atoms and refuses function values) and then re-validates the
resulting term's shape before accepting it.

# `ext_type`

```elixir
@type ext_type() :: :tuple | :atom | :pid | :reference | :bigint | :improper_list
```

# `decode_atom`

```elixir
@spec decode_atom(binary()) :: {:ok, atom()} | {:error, {:unsafe_atom, binary()}}
```

Decode atom bytes to an existing atom only. Never creates a new atom.
Returns `{:error, {:unsafe_atom, text}}` if the atom does not already exist.

# `decode_bigint`

```elixir
@spec decode_bigint(binary()) ::
  {:ok, integer()} | {:error, {:invalid_extension, :bigint}}
```

# `decode_pid`

```elixir
@spec decode_pid(binary()) :: {:ok, pid()} | {:error, {:invalid_extension, :pid}}
```

Decode PID bytes safely: only ever accepts input that `:erlang.binary_to_term/2`
with `:safe` decodes to an actual `pid()`. Any other shape is rejected without
raising and without creating atoms.

# `decode_reference`

```elixir
@spec decode_reference(binary()) ::
  {:ok, reference()} | {:error, {:invalid_extension, :reference}}
```

# `encode_atom`

```elixir
@spec encode_atom(atom()) :: binary()
```

Encode an atom as its UTF-8 text. Any atom, including unicode atoms, is representable.

# `encode_bigint`

```elixir
@spec encode_bigint(integer()) :: binary()
```

Encode an arbitrary-size integer as its big-endian two's complement representation.

# `encode_pid`

```elixir
@spec encode_pid(pid()) :: binary()
```

Encode a local or distributed PID using `:erlang.term_to_binary/1`.

# `encode_reference`

```elixir
@spec encode_reference(reference()) :: binary()
```

# `ext_type_code`

```elixir
@spec ext_type_code(ext_type()) :: non_neg_integer()
```

# `ext_type_name`

```elixir
@spec ext_type_name(non_neg_integer()) :: {:ok, ext_type()} | :error
```

---

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