# `Dave`
[🔗](https://github.com/BrandtHill/Dave/blob/master/lib/dave.ex#L1)

Functions for using the DAVE Protocol

[Discord Audio & Video End-to-End Encryption (DAVE) Protocol Whitepaper](https://daveprotocol.com/)

[The Rust crate `davey`](https://github.com/Snazzah/davey)

RustlerPrecompiled will fetch the required files at compile time.

The following OS's have binaries available:
- `aarch64-apple-darwin`
- `aarch64-unknown-linux-gnu`
- `aarch64-unknown-linux-musl`
- `arm-unknown-linux-gnueabihf`
- `riscv64gc-unknown-linux-gnu`
- `x86_64-apple-darwin`
- `x86_64-pc-windows-gnu`
- `x86_64-pc-windows-msvc`
- `x86_64-unknown-freebsd`
- `x86_64-unknown-linux-gnu`
- `x86_64-unknown-linux-musl`

If you have some wackadoo OS or you prefer to build from source with your installed Rust toolchain,
you can add Rustler to your project dependencies and set `FORCE_DAVE_BUILD=true`.

```elixir
defp deps do
  [
    ...
    {:rustler, "~> 0.37", optional: true, runtime: false}
  ]
end
```

Minimum set of functions required to get Discord Voice working are implemented. `davey` has some other
functionality that may be added later. Docs here are limited, so I would recommend looking at the DAVE whitepaper
or nostrum source code for integration and usage details.

# `codec`

```elixir
@type codec() :: :unknown | :opus | :av1 | :vp8 | :vp9 | :h264 | :h265
```

# `commit_welcome`

```elixir
@type commit_welcome() :: {binary() | nil, binary() | nil}
```

# `media_type`

```elixir
@type media_type() :: :audio | :video
```

# `proposals_operation_type`

```elixir
@type proposals_operation_type() :: :append | :revoke
```

# `protocol_version`

```elixir
@type protocol_version() :: pos_integer()
```

# `session`

```elixir
@type session() :: reference()
```

# `session_status`

```elixir
@type session_status() :: :inactive | :pending | :awaiting_response | :active
```

# `can_passthrough?`

```elixir
@spec can_passthrough?(session(), non_neg_integer()) :: boolean()
```

# `decrypt`

```elixir
@spec decrypt(session(), non_neg_integer(), media_type(), binary()) ::
  binary() | :error
```

# `encrypt`

```elixir
@spec encrypt(session(), media_type(), codec(), binary()) :: binary() | :error
```

# `epoch`

```elixir
@spec epoch(session()) :: non_neg_integer()
```

# `get_serialized_key_package`

```elixir
@spec get_serialized_key_package(session()) :: binary()
```

# `max_protocol_version`

```elixir
@spec max_protocol_version() :: protocol_version()
```

# `new_session`

```elixir
@spec new_session(protocol_version(), non_neg_integer(), non_neg_integer()) ::
  session()
```

# `process_commit`

```elixir
@spec process_commit(session(), binary()) :: :ok | :error
```

# `process_proposals`

```elixir
@spec process_proposals(
  session(),
  proposals_operation_type(),
  binary(),
  [non_neg_integer()] | nil
) :: commit_welcome() | :error
```

# `process_welcome`

```elixir
@spec process_welcome(session(), binary()) :: :ok | :error
```

# `protocol_version`

```elixir
@spec protocol_version(session()) :: protocol_version()
```

# `ready?`

```elixir
@spec ready?(session()) :: boolean()
```

# `reinit`

```elixir
@spec reinit(session(), protocol_version(), non_neg_integer(), non_neg_integer()) ::
  :ok
```

# `reset`

```elixir
@spec reset(session()) :: :ok | :error
```

# `set_external_sender`

```elixir
@spec set_external_sender(session(), binary()) :: :ok
```

# `set_passthrough_mode`

```elixir
@spec set_passthrough_mode(session(), boolean()) :: :ok
```

# `status`

```elixir
@spec status(session()) :: session_status()
```

---

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