Skip to content

Commit 3e39581

Browse files
authored
Merge pull request #586 from rusterlium/serde
Import of serde_rustler
2 parents 763f391 + 057227e commit 3e39581

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+127914
-19
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ versions.
1717
- `Env::is_process_alive` and `LocalPid::is_alive` (#599)
1818
- Encoding and decoding of 128 bit integers (#600)
1919
- Optional codec for `num_bigint::BigInt` using the `big_integer` feature (#601)
20+
- Add experimental `serde` support derived from `serde_rustler`
2021

2122
### Fixed
2223

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ members = [
77
"rustler_tests/native/binary_example",
88
"rustler_tests/native/rustler_test",
99
"rustler_tests/native/rustler_bigint_test",
10+
"rustler_tests/native/rustler_serde_test",
1011
"rustler_tests/native/deprecated_macros",
1112
"rustler_tests/native/dynamic_load",
1213
"rustler_tests/native/rustler_compile_tests",

LICENSE-MIT

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
Copyright (c) 2016 hansihe
2+
Copyright (c) 2016-2024 The Contributors of the Rustler Project
3+
Serde support derived from serde_rustler:
4+
Copyright (c) 2019-2021 Sunny Gonnabathula
25

36
Permission is hereby granted, free of charge, to any
47
person obtaining a copy of this software and associated

README.md

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,34 @@ they unwind into C.
1616
The library provides functionality for both Erlang and Elixir, however Elixir
1717
is favored as of now.
1818

19-
#### Features:
19+
#### Features
2020

21-
- Safety - The code you write in a Rust NIF should never be able to crash the BEAM.
22-
- Interop - Decoding and encoding rust values into Erlang terms is as easy as a function call.
23-
- Type composition - Making a Rust struct encodable and decodable to Erlang or Elixir can be done with a single attribute.
24-
- 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.
21+
Safety
22+
: The code you write in a Rust NIF should never be able to crash the BEAM.
2523

26-
#### Getting started
24+
Interop
25+
: Decoding and encoding rust values into Erlang terms is as easy as a function
26+
: call.
27+
28+
Type composition
29+
: Making a Rust struct encodable and decodable to Erlang or Elixir can be done
30+
: with a single attribute.
2731

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

30-
- Add the [rustler elixir library](https://hex.pm/packages/rustler) as a dependency of your project.
31-
- Run `mix rustler.new` to generate a new NIF in your project. Follow the instructions.
32-
- 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.
38+
The easiest way of getting started is the [rustler Elixir library](https://hex.pm/packages/rustler).
3339

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

3648
#### What it looks like
3749

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

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

6577
```toml
6678
[dependencies]
@@ -84,5 +96,5 @@ at your option.
8496
##### Contribution
8597

8698
Unless you explicitly state otherwise, any contribution intentionally submitted
87-
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
88-
additional terms or conditions.
99+
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be
100+
dual licensed as above, without any additional terms or conditions.

UPGRADE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ This document is intended to simplify upgrading to newer versions by extending t
1111
wrapper. For most codebases, it will be enough to activate the feature and
1212
replace all `rustler_bigint::BigInt` usages by `rustler::BigInt` (or
1313
`num_bigint::BigInt`).
14+
2. `serde_rustler` has been integrated into `rustler` behind the feature flag
15+
`serde`. Arbitrary, `serde`-compatible objects (i.e. with `Deserialize` or
16+
`Serialize` `impl`s) can be wrapped in `SerdeTerm` to use them in place of
17+
`Encoder` or `Decoder`. The API is for now considered experimental.
1418

1519
## 0.29 -> 0.30
1620

rustler/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ nif_version_2_14 = ["rustler_sys/nif_version_2_14"]
1717
nif_version_2_15 = ["nif_version_2_14", "rustler_sys/nif_version_2_15"]
1818
nif_version_2_16 = ["nif_version_2_15", "rustler_sys/nif_version_2_16"]
1919
nif_version_2_17 = ["nif_version_2_16", "rustler_sys/nif_version_2_17"]
20+
serde = ["dep:serde"]
2021

2122
[dependencies]
2223
lazy_static = "1.4"
2324
rustler_codegen = { path = "../rustler_codegen", version = "0.31.0", optional = true}
2425
rustler_sys = { path = "../rustler_sys", version = "~2.4.0" }
2526
num-bigint = { version = "0.4", optional = true }
27+
serde = { version = "1", optional = true }
2628

2729
[package.metadata.release]
2830

rustler/src/convert/mod.rs

Whitespace-only changes.

rustler/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,9 @@ pub use rustler_codegen::{
7777
init, nif, NifException, NifMap, NifRecord, NifStruct, NifTaggedEnum, NifTuple, NifUnitEnum,
7878
NifUntaggedEnum,
7979
};
80+
81+
#[cfg(feature = "serde")]
82+
pub mod serde;
83+
84+
#[cfg(feature = "serde")]
85+
pub use crate::serde::SerdeTerm;

rustler/src/serde/atoms.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
//! Constants and utilities for conversion between Rust string-likes and Elixir atoms.
2+
3+
use crate::serde::Error;
4+
use crate::{types::atom::Atom, Encoder, Env, Term};
5+
6+
use lazy_static::lazy_static;
7+
8+
lazy_static! {
9+
pub static ref OK: String = String::from("Ok");
10+
pub static ref ERROR: String = String::from("Err");
11+
}
12+
13+
atoms! {
14+
nil,
15+
ok,
16+
error,
17+
true_ = "true",
18+
false_ = "false",
19+
undefined,
20+
nan,
21+
inf,
22+
neg_inf,
23+
__struct__,
24+
}
25+
26+
/**
27+
* 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.
28+
*/
29+
pub fn str_to_term<'a>(env: &Env<'a>, string: &str) -> Result<Term<'a>, Error> {
30+
if string == "Ok" {
31+
Ok(ok().encode(*env))
32+
} else if string == "Err" {
33+
Ok(error().encode(*env))
34+
} else {
35+
match Atom::try_from_bytes(*env, string.as_bytes()) {
36+
Ok(Some(term)) => Ok(term.encode(*env)),
37+
Ok(None) => Err(Error::InvalidStringable),
38+
_ => Err(Error::InvalidStringable),
39+
}
40+
}
41+
}
42+
43+
/**
44+
* Attempts to create a `String` from the term.
45+
*/
46+
pub fn term_to_string(term: &Term) -> Result<String, Error> {
47+
if ok().eq(term) {
48+
Ok(OK.to_string())
49+
} else if error().eq(term) {
50+
Ok(ERROR.to_string())
51+
} else if term.is_atom() {
52+
term.atom_to_string().or(Err(Error::InvalidAtom))
53+
} else {
54+
Err(Error::InvalidStringable)
55+
}
56+
}

0 commit comments

Comments
 (0)