README.md

# Bincode

<p>
  <a href="https://hex.pm/packages/bincode">
    <img alt="Hex Version" src="https://img.shields.io/hexpm/v/bincode.svg">
  </a>
  <a href="https://hexdocs.pm/bincode">
    <img alt="Hex Docs" src="http://img.shields.io/badge/hex.pm-docs-green.svg?style=flat">
  </a>
</p>
<p>
  <a href="https://github.com/LeonardBesson/bincode/actions">
    <img alt="CI" src="https://github.com/LeonardBesson/bincode/workflows/ci/badge.svg">
  </a>
  <a href="https://opensource.org/licenses/MIT">
    <img alt="MIT License" src="https://img.shields.io/hexpm/l/bincode">
  </a>
</p>

  Bincode allows you to share data between Elixir and Rust using
  Rust's [Bincode](https://github.com/servo/bincode) binary format.

  You can implement your custom serialization manually, but for most use cases
  you can simply declare the Rust structs and enums using `Bincode.declare_struct/3` and
  `Bincode.declare_enum/3`

  ## Supported types

  Most Rust types are supported, plus user defined structs and enums.

  | Rust                   | Bincode notation          | Elixir typespec                  |
  |------------------------|---------------------------|----------------------------------|
  | `u8`                   | `:u8`                     | `non_neg_integer`                |
  | ...                    | ...                       | ...                              |
  | `u128`                 | `:u128`                   | `non_neg_integer`                |
  | `i8`                   | `:i8`                     | `integer`                        |
  | ...                    | ...                       | ...                              |
  | `i128`                 | `:i128`                   | `integer`                        |
  | `f32`                  | `:f32`                    | `float`                          |
  | `f64`                  | `:f64`                    | `float`                          |
  | `bool`                 | `:bool`                   | `boolean`                        |
  | `String`               | `:string`                 | `binary`                         |
  | `(u32, String)`        | `{:u32, :string}`         | `{non_neg_integer, binary}`      |
  | `Option<f32>`          | `{:option, :f32}`         | `float \| nil`                   |
  | `Vec<String>`          | `{:list, :string}`        | `[binary]`                       |
  | `HashMap<i64, String>` | `{:map, {:i64, :string}}` | `%{required(integer) => binary}` |
  | `HashSet<u8>`          | `{:set, :u8}`             | `MapSet.t(non_neg_integer)`      |

  User defined types such as structs and enums can be nested, in this case the type is
  the fully qualified module name. See documentation for `Bincode.declare_struct/3`.

  The endianness is little since that's the default used by Bincode.
  Tuples are implemented for a max size of 12 by default. That should be enough for
  most practical cases but if you need to serialize tuples with more elements you can
  set `max_tuple_size` in the mix config, like so: 
  ```elixir
  config :bincode, max_tuple_size: 23
  ```

  ## Examples

  Consider the typical example where we want to send data structures across the network.
  Here with a Rust client and Elixir server:

  ```rust
  #[derive(Serialize, Deserialize)]
  pub struct PacketSendMessage {
    pub from: u64,
    pub to: u64,
    pub content: String,
  }

  pub fn send_message(sender_id: u64, receiver_id: u64) {
    let message = PacketSendMessage {
        from: sender_id,
        to: receiver_id,
        content: "hello!".to_owned()
    };
    let encoded: Vec<u8> = bincode::serialize(&message).unwrap();

    // now send "encoded" to Elixir app
  }
  ```

  On the Elixir side you can simply declare the same packet struct and deserialize the received bytes:

  ```elixir
  defmodule Packets do
    import Bincode

    declare_struct(PacketSendMessage,
      from: :u64,
      to: :u64,
      content: :string
    )
  end

  alias Packets.PacketSendMessage

  # Receive "data" from the network
  {:ok, {%PacketSendMessage{} = message, rest}} = PacketSendMessage.deserialize(data)
  Logger.info("Received message packet #{inspect(message)}")
  ```
  


## Installation

Add `bincode` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:bincode, "~> 0.2.0"}
  ]
end
```

## Documentation

[https://hexdocs.pm/bincode](https://hexdocs.pm/bincode).