Skip to content

Commit

Permalink
Merge pull request #586 from rusterlium/serde
Browse files Browse the repository at this point in the history
Import of serde_rustler
  • Loading branch information
filmor committed Mar 20, 2024
2 parents 763f391 + 057227e commit 3e39581
Show file tree
Hide file tree
Showing 41 changed files with 127,914 additions and 19 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ versions.
- `Env::is_process_alive` and `LocalPid::is_alive` (#599)
- Encoding and decoding of 128 bit integers (#600)
- Optional codec for `num_bigint::BigInt` using the `big_integer` feature (#601)
- Add experimental `serde` support derived from `serde_rustler`

### Fixed

Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ members = [
"rustler_tests/native/binary_example",
"rustler_tests/native/rustler_test",
"rustler_tests/native/rustler_bigint_test",
"rustler_tests/native/rustler_serde_test",
"rustler_tests/native/deprecated_macros",
"rustler_tests/native/dynamic_load",
"rustler_tests/native/rustler_compile_tests",
Expand Down
3 changes: 3 additions & 0 deletions LICENSE-MIT
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
Copyright (c) 2016 hansihe
Copyright (c) 2016-2024 The Contributors of the Rustler Project
Serde support derived from serde_rustler:
Copyright (c) 2019-2021 Sunny Gonnabathula

Permission is hereby granted, free of charge, to any
person obtaining a copy of this software and associated
Expand Down
44 changes: 28 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,34 @@ they unwind into C.
The library provides functionality for both Erlang and Elixir, however Elixir
is favored as of now.

#### Features:
#### Features

- Safety - The code you write in a Rust NIF should never be able to crash the BEAM.
- Interop - Decoding and encoding rust values into Erlang terms is as easy as a function call.
- Type composition - Making a Rust struct encodable and decodable to Erlang or Elixir can be done with a single attribute.
- Resource objects - Enables you to safely pass a reference to a Rust struct into Erlang code. The struct will be automatically dropped when it's no longer referenced.
Safety
: The code you write in a Rust NIF should never be able to crash the BEAM.

#### Getting started
Interop
: Decoding and encoding rust values into Erlang terms is as easy as a function
: call.

Type composition
: Making a Rust struct encodable and decodable to Erlang or Elixir can be done
: with a single attribute.

The easiest way of getting started is the [rustler elixir library](https://hex.pm/packages/rustler).
Resource objects
: Enables you to safely pass a reference to a Rust struct into Erlang code. The
: struct will be automatically dropped when it's no longer referenced.

#### Getting started

- Add the [rustler elixir library](https://hex.pm/packages/rustler) as a dependency of your project.
- Run `mix rustler.new` to generate a new NIF in your project. Follow the instructions.
- If you're already using [`serde`](https://serde.rs), consider using [`serde_rustler`](https://github.com/sunny-g/serde_rustler/tree/master/serde_rustler) to easily encode and decode your data types into and from Elixir terms.
The easiest way of getting started is the [rustler Elixir library](https://hex.pm/packages/rustler).

NOTE: If you have previously used Rustler, you need to run `mix archive.uninstall rustler_installer.ez` to remove it before generating the NIF.
- Add the [rustler Elixir library](https://hex.pm/packages/rustler) as a
dependency of your project.
- Run `mix rustler.new` to generate a new NIF in your project. Follow the
instructions.
- If you are already using [`serde`](https://serde.rs) and/or have been using
`serde_rustler` before, please enable the `serde` feature in your NIF crate's
`Cargo.toml` on the `rustler` dependency.

#### What it looks like

Expand All @@ -58,9 +70,9 @@ Rustler aims to support the newest three major OTP versions as well as newest th
#### Supported NIF version

The minimal supported NIF version for a library should be defined via Cargo
features. The default is currently `2.14` (Erlang/OTP 21). To use features from
NIF version `2.16` (Erlang/OTP 24), the respective feature flag has to be
enabled on the dependency:
features. The default is currently `2.15` (Erlang/OTP 21). To use features from
NIF version `2.16` (Erlang/OTP 24) or `2.17` (Erlang/OTP 26), the respective
feature flag has to be enabled on the dependency:

```toml
[dependencies]
Expand All @@ -84,5 +96,5 @@ at your option.
##### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
additional terms or conditions.
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
dual licensed as above, without any additional terms or conditions.
4 changes: 4 additions & 0 deletions UPGRADE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ This document is intended to simplify upgrading to newer versions by extending t
wrapper. For most codebases, it will be enough to activate the feature and
replace all `rustler_bigint::BigInt` usages by `rustler::BigInt` (or
`num_bigint::BigInt`).
2. `serde_rustler` has been integrated into `rustler` behind the feature flag
`serde`. Arbitrary, `serde`-compatible objects (i.e. with `Deserialize` or
`Serialize` `impl`s) can be wrapped in `SerdeTerm` to use them in place of
`Encoder` or `Decoder`. The API is for now considered experimental.

## 0.29 -> 0.30

Expand Down
2 changes: 2 additions & 0 deletions rustler/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ nif_version_2_14 = ["rustler_sys/nif_version_2_14"]
nif_version_2_15 = ["nif_version_2_14", "rustler_sys/nif_version_2_15"]
nif_version_2_16 = ["nif_version_2_15", "rustler_sys/nif_version_2_16"]
nif_version_2_17 = ["nif_version_2_16", "rustler_sys/nif_version_2_17"]
serde = ["dep:serde"]

[dependencies]
lazy_static = "1.4"
rustler_codegen = { path = "../rustler_codegen", version = "0.31.0", optional = true}
rustler_sys = { path = "../rustler_sys", version = "~2.4.0" }
num-bigint = { version = "0.4", optional = true }
serde = { version = "1", optional = true }

[package.metadata.release]

Expand Down
Empty file added rustler/src/convert/mod.rs
Empty file.
6 changes: 6 additions & 0 deletions rustler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,9 @@ pub use rustler_codegen::{
init, nif, NifException, NifMap, NifRecord, NifStruct, NifTaggedEnum, NifTuple, NifUnitEnum,
NifUntaggedEnum,
};

#[cfg(feature = "serde")]
pub mod serde;

#[cfg(feature = "serde")]
pub use crate::serde::SerdeTerm;
56 changes: 56 additions & 0 deletions rustler/src/serde/atoms.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
//! Constants and utilities for conversion between Rust string-likes and Elixir atoms.

use crate::serde::Error;
use crate::{types::atom::Atom, Encoder, Env, Term};

use lazy_static::lazy_static;

lazy_static! {
pub static ref OK: String = String::from("Ok");
pub static ref ERROR: String = String::from("Err");
}

atoms! {
nil,
ok,
error,
true_ = "true",
false_ = "false",
undefined,
nan,
inf,
neg_inf,
__struct__,
}

/**
* Attempts to create an atom term from the provided string (if the atom already exists in the atom table). If not, returns a string term.
*/
pub fn str_to_term<'a>(env: &Env<'a>, string: &str) -> Result<Term<'a>, Error> {
if string == "Ok" {
Ok(ok().encode(*env))
} else if string == "Err" {
Ok(error().encode(*env))
} else {
match Atom::try_from_bytes(*env, string.as_bytes()) {
Ok(Some(term)) => Ok(term.encode(*env)),
Ok(None) => Err(Error::InvalidStringable),
_ => Err(Error::InvalidStringable),
}
}
}

/**
* Attempts to create a `String` from the term.
*/
pub fn term_to_string(term: &Term) -> Result<String, Error> {
if ok().eq(term) {
Ok(OK.to_string())
} else if error().eq(term) {
Ok(ERROR.to_string())
} else if term.is_atom() {
term.atom_to_string().or(Err(Error::InvalidAtom))
} else {
Err(Error::InvalidStringable)
}
}
Loading

0 comments on commit 3e39581

Please sign in to comment.