This is a set of Rust libraries that implement the Erlang External Term Format and the Erlang Distribution Protocol, and provides a higher-level API for Rust/Erlang (or Rust/Elixir) interoperability based on the ETF.
This project was heavily inspired by a set of Go libraries.
- Extensive test coverage, including unit, integration, and property-based tests
crates/erltfimplements supports for fragmented messages (a.k.a.DFLAG_FRAGMENTS), a feature almost always skipped by other implementations due to its complexity and imperfect documentation- Serde support in
erltfvia a feature plus two Serde-specific crates (covered below) crates/edp_clientandcrates/edp_nodeprovide higher-level abstractions- (Some) Support for Elixir interop
This set of libraries is very young. Breaking API changes are fairly likely.
This set of libraries target Erlang/OTP 26 and 27. It should be compatible with Erlang 28.
crates/edp_client: an Erlang Distribution Protocol client using Tokiocrates/erltf: an Erlang Term Format implementationcrates/erltf_serde: Serde glue forerltfcrates/erltf_serde_derive:derive-oriented Serde glue forerltfcrates/edp_elixir: Elixir data type supportcrates/edp_examples: examples that use Erlangcrates/edp_examples_elixir: examples that use Elixir
ets-browserimplements an ETS table browserkhepri-browseris a Khepri tree and projection browser- A number of integration examples can be found under
crates/edp_examplesandcrates/edp_examples_elixir
These libraries were developed with efficiency in mind, both in terms of memory allocations and binary parser performance.
The Erlang Term Format encoder and decoder can achive throughput ranging from hundreds of MiBs to tens of GiBs
per second, see CONTRIBUTING.md to learn how to run the benchmarks.
Actual throughput will vary from workload to workload.
Elixir may be a BEAM-based language just like Erlang but it uses a lot of conventions that are not true for the rest of the BEAM ecosystem. This library suite provides some support for Elixir interop, including:
- Elixir struct mapping to Rust structs with
derive(ElixirStruct) - The
elixir-interopfeature that mapsOption::Nonetonilinstead ofundefined - The
edp_elixircrate provides Rust representations of common Elixir types (Range, MapSet, Date/Time, exceptions) and GenServer message helpers
This family of crates provides the following optional Cargo features:
| Crate | Feature | Description |
|---|---|---|
erltf |
serde |
Implements serde::Serialize and serde::Deserialize for OwnedTerm |
erltf |
elixir-interop |
Adjusts encoding, decoding behavior to match Elixir conventions (e.g., Option::None becomes the nil atom instead of undefined) |
erltf_serde |
elixir-interop |
Same as elixir-interop in erltf but in the Serde extensions |
Contributions to this project are very welcome. Please refer to the CONTRIBUTING.md to learn more.
This software is dual-licensed under the MIT License and the Apache License, Version 2.0.
(c) 2025-2026 Michael S. Klishin and Contributors.