Bincode allows you to share data between Elixir and Rust using Rust's 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.Structs.declare_struct/3
and
Bincode.Structs.declare_enum/3
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.Structs.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:
config :bincode, max_tuple_size: 23
Consider the typical example where we want to send data structures across the network. Here with a Rust client and Elixir server:
#[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:
defmodule Packets do
import Bincode.Structs
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)}")
Add bincode
to your list of dependencies in mix.exs
:
def deps do
[
{:bincode, "~> 0.3.0"}
]
end