# `RTMP.AMF0`
[🔗](https://github.com/Adeyeye93/rtmp/blob/v0.1.0/lib/rtmp/amf0.ex#L1)

AMF0 encoding and decoding.

RTMP command messages (`connect`, `publish`, ...) and data messages
(`onMetaData`) are sequences of AMF0 values.

## Value mapping

| AMF0 type     | Elixir (decoded)                         | Encoded from                      |
|---------------|------------------------------------------|-----------------------------------|
| Number        | float, or `:nan` / `:infinity` / `:neg_infinity` | integer, float, those atoms |
| Boolean       | `true` / `false`                         | `true` / `false`                  |
| String        | binary                                   | binary shorter than 64 KiB        |
| Long String   | binary                                   | binary of 64 KiB or more          |
| Object        | map with binary keys                     | map (atom or binary keys)         |
| ECMA Array    | map with binary keys                     | `{:ecma_array, map}`              |
| Strict Array  | list                                     | list                              |
| Null          | `nil`                                    | `nil`                             |
| Undefined     | `:undefined`                             | `:undefined`                      |
| Date          | `DateTime` (millisecond precision, UTC)  | `DateTime`                        |
| Typed Object  | `{:typed_object, class, map}`            | same                              |
| XML Document  | `{:xml, binary}`                         | same                              |
| Reference     | `{:reference, index}`                    | same                              |
| Unsupported   | `:unsupported`                           | `:unsupported`                    |

Objects and ECMA arrays both decode to plain maps, so the distinction is
lost on a round trip; encode a map as `{:ecma_array, map}` when the
receiver needs an ECMA array (FLV `onMetaData`, for example).

NaN and the infinities can't be represented as BEAM floats, so they decode
to atoms instead of failing — some encoders really do send them in
metadata.

## Robustness

Decoding never raises on malformed input; it returns `{:error, reason}`.
Nesting deeper than 64 levels is rejected, so hostile input can't drive
unbounded recursion. AMF3 values (the AVM+ switch marker) are not
supported and decode to an error.

# `value`

```elixir
@type value() ::
  float()
  | :nan
  | :infinity
  | :neg_infinity
  | boolean()
  | binary()
  | map()
  | list()
  | nil
  | :undefined
  | :unsupported
  | DateTime.t()
  | {:ecma_array, map()}
  | {:typed_object, binary(), map()}
  | {:xml, binary()}
  | {:reference, non_neg_integer()}
```

# `decode`

```elixir
@spec decode(binary()) :: {:ok, value(), binary()} | {:error, term()}
```

Decodes one AMF0 value from the front of `binary`.

Returns `{:ok, value, rest}` or `{:error, reason}`.

# `decode_all`

```elixir
@spec decode_all(binary()) :: {:ok, [value()]} | {:error, term()}
```

Decodes every AMF0 value in `binary`, which must contain nothing else.

# `encode`

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

Encodes one value. Raises `ArgumentError` for terms with no AMF0 mapping —
encoding is only ever done on your own data, never on network input.

# `encode_all`

```elixir
@spec encode_all([value()]) :: binary()
```

Encodes a list of values back to back, the way command messages are laid out.

# `max_depth`

```elixir
@spec max_depth() :: pos_integer()
```

Maximum nesting depth accepted when decoding.

---

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