UPDATE: otter has been released on crates.io as otter-nif! Scroll to the most recent post for details.
I’ve been working on otter, a Rust library for writing Erlang NIFs. It’s at https://github.com/cubelio/otter and I’d like some feedback before cutting a real release.
The motivation: rustler is excellent but it does a lot of magic under the covers that imposes some opinionated decisions that favor Elixir and Mix; there’s no first-class Erlang story. Otter is built for Erlang from the ground up. The design principle is to be as close to using the native NIF API as possible; “if an Erlang programmer wouldn’t recognise a concept, it doesn’t belong.” So no Elixir struct or exception mapping, no NifUntaggedEnum, no Error enum, no inventory/linker magic. Lists are cons cells. NIF registration is explicit. A full comparison is in docs/RUSTLER.md; a side-by-side rustler-to-otter migration guide is in docs/MIGRATION.md.
Three components:
-
otter- core Rust library: all 12 Erlang term types, two-level term resolution (RawTerm→Term→ data),Env<'a>lifetime safety, resource types with panic-safe callbacks,OwnedEnvfor cross-thread sends,select/select_x, time, system info -
otter_codegen- proc macros for#[otter::nif]andotter::init! -
rebar3_otter- a rebar3 plugin that drives cargo build (no Mix needed)
Status is 0.1, pre-release. Everything is implemented and exercised end-to-end by an in-tree demo (test_apps/otter_demo), which runs as a rebar3 eunit smoke test covering 26 NIFs across all the term types. The library has not yet been used in production. Requires OTP 26+ (NIF version 2.17), Rust edition 2024, Unix only.
What I’d particularly like feedback on:
-
API shape: does writing a NIF with it feel like working with Erlang?
-
The Erlang-first philosophy: anything missing that you’d expect, or anything included that doesn’t belong?
-
The safety model:
Env<'a>is invariant-lifetime so terms can’t escape; panics are caught at the FFI boundary including in resource destructors anddowncallbacks -
Anything from rustler you actively miss
GitHub issues or replies here both work.
Thanks,
Lynn