Skip to content

Commit

Permalink
Merge pull request #676 from tessi/atom-record-fields
Browse files Browse the repository at this point in the history
record fields as atoms
  • Loading branch information
superchris authored Dec 3, 2024
2 parents 8e86e1f + c178ce7 commit 1351e6d
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 6 deletions.
1 change: 1 addition & 0 deletions native/wasmex/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion native/wasmex/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ path = "src/lib.rs"
crate-type = ["dylib"]

[dependencies]
rustler = { version = "0.35", features = ["big_integer"] }
rustler = { version = "0.35", features = ["big_integer", "serde"] }
once_cell = "1.20.2"
rand = "0.8.5"
wasmtime = "26.0.1"
Expand Down
17 changes: 14 additions & 3 deletions native/wasmex/src/component_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ fn term_to_val(param_term: &Term, param_type: &Type) -> Result<Val, Error> {
let decoded_map = param_term.decode::<HashMap<Term, Term>>()?;
let terms = decoded_map
.iter()
.map(|(key, val)| (key.decode::<String>().unwrap(), val))
.map(|(key_term, val)| (term_to_field_name(key_term), val))
.collect::<Vec<(String, &Term)>>();
for field in record.fields() {
let field_term_option = terms.iter().find(|(k, _)| k == field.name);
Expand Down Expand Up @@ -148,6 +148,17 @@ fn term_to_val(param_term: &Term, param_type: &Type) -> Result<Val, Error> {
}
}

fn term_to_field_name(key_term: &Term) -> String {
match key_term.get_type() {
TermType::Atom => key_term.atom_to_string().unwrap(),
_ => key_term.decode::<String>().unwrap(),
}
}

fn field_name_to_term<'a>(env: &rustler::Env<'a>, field_name: &str) -> Term<'a> {
rustler::serde::atoms::str_to_term(env, field_name).unwrap()
}

fn encode_result(env: rustler::Env, vals: Vec<Val>) -> Term {
let result_term = match vals.len() {
1 => val_to_term(vals.first().unwrap(), env),
Expand Down Expand Up @@ -182,8 +193,8 @@ fn val_to_term<'a>(val: &Val, env: rustler::Env<'a>) -> Term<'a> {
Val::Record(record) => {
let converted_pairs = record
.iter()
.map(|(key, val)| (key, val_to_term(val, env)))
.collect::<Vec<(&String, Term<'a>)>>();
.map(|(key, val)| (field_name_to_term(&env, key), val_to_term(val, env)))
.collect::<Vec<(Term, Term)>>();
Term::map_from_pairs(env, converted_pairs.as_slice()).unwrap()
}
Val::Tuple(tuple) => {
Expand Down
8 changes: 6 additions & 2 deletions test/components/component_types_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,16 @@ defmodule Wasm.Components.ComponentTypesTest do
end

test "records", %{instance: instance} do
# don't love this yet, be nicer to support atom keys
assert {:ok, %{"x" => 1, "y" => 2}} =
assert {:ok, %{x: 1, y: 2}} =
Wasmex.Components.Instance.call_function(instance, "id-record", [
%{"x" => 1, "y" => 2}
])

assert {:ok, %{x: 1, y: 2}} =
Wasmex.Components.Instance.call_function(instance, "id-record", [
%{x: 1, y: 2}
])

assert {:error, _error} =
Wasmex.Components.Instance.call_function(instance, "id-record", [
%{"invalid-field" => "foo"}
Expand Down

0 comments on commit 1351e6d

Please sign in to comment.