A Native Implemented Function is implemented in C (or Rust when using Rustler) and can be called from Elixir or Erlang just like any other function. It’s the simplest and fastest way to run native code from Erlang but it does come with a caveat: a crash in a NIF can bring down the whole BEAM. This makes Rust a safer option than C for implementing NIFs as its type system and ownership model guarantee memory and thread-safety.
Rustler is a fantastic project built to make writing Rust NIFs a simple process; and the upcoming v0.22 release will provide a much cleaner syntax to do so. The library handles encoding and decoding Rust values into Erlang terms, catches Rust panics before they unwind to C and should make it impossible to crash the BEAM from a Rust NIF.
One of my first forays into Rust-implemented NIFs was while building a micro-library providing Base64 encoding and decoding, creatively named base64. It’s utterly pointless as that functionality comes built-in to Elixir but I wanted to start with something simple. On the plus side, this meant I could easily compare the performance of the NIF version to the Elixir implementation which can be found in the Base
module.
The library consists of two functions: encode/2
and decode/2
and it’s using rust-base64 to do the heavy lifting in the NIFs. Let’s walk through how this all works.
To get started, we need a new mix project with rustler installed as a dependency.
mix new base64
## add {:rustler, "~> 0.22-rc"} to mix.exs deps
mix deps.get
mix rustler.new
## follow rustler instructions
#rust #web-development #developer