Skip to content

Commit

Permalink
Add UPGRADE.md
Browse files Browse the repository at this point in the history
  • Loading branch information
evnu committed Jun 18, 2021
1 parent 8cd520e commit be57cdc
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

See `UPGRADE.md` for additional help when upgrading to newer versions.

## [Unreleased]

### Added
Expand Down
50 changes: 50 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Upgrade

This document here is intended to simplify upgrading to newer versions by extending the changelog.

## 0.21 -> 0.22

0.22 changes how to define NIFs. Users upgrading to 0.22 should to do two things:

1. Replace `rustler::rustler_export_nifs!` with `rustler::init!`
2. Use the new `rustler::nif` proc_macro to declare NIFs

0.22 introduces a new `proc_macro` allowing to spell out the parameter of a NIF
directly instead of using an `args: &[Term<'a>]`. Lets consider an example `add()`,
where the Elixir function looks like this:

```elixir
def add(left, right), do: :erlang.nif_error(:not_loaded)
```

Previously, the signature of the corresponding NIF might have looked like this:

```rust
fn add<'a>(env: Env<'a>, args: &[Term<'a>]) -> Result<Term<'a>, Error>
```

When calling the NIF from Elixir as `add(1, 2)`, `args` would then contain two
`Term`, one for 1, and one for 2. With 0.22, this becomes more obvious, as the
NIFs signature resembles the Elixir function's signature:

```rust
#[rustler::nif]
fn add(a: i64, b: i64) -> i64
```

Under the hood, this is implemented by the `rustler::nif` proc_macro. For the
new form to work, the parameters' types need to implement `Decoder`, and the
return type needs to implement `Decoder`.
### What if `Env` is required in the function?
Sometimes, we still need the environment `Env` for the NIF. For example, if
work with `Binary` and `OwnedBinary`, the environment would be needed to create a `Binary`
from an `OwnedBinary`. To allow this, `env: Env<'a>` can be added explicitly as well:

```rust
#[rustler::nif]
pub fn map_entries_sorted<'a>(env: Env<'a>, iter: MapIterator<'a>) -> NifResult<Vec<Term<'a>>>
```

`env` can then be used the same way as before.

0 comments on commit be57cdc

Please sign in to comment.