Skip to content

Commit

Permalink
support option type
Browse files Browse the repository at this point in the history
  • Loading branch information
Chris Nelson committed Nov 29, 2024
1 parent de5616c commit 0849dd7
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 11 deletions.
40 changes: 29 additions & 11 deletions native/wasmex/src/component_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::component::ComponentInstanceResource;
use crate::store::ComponentStoreData;
use crate::store::ComponentStoreResource;

use rustler::env;
use rustler::types::atom::nil;
use rustler::types::tuple;
use rustler::types::tuple::make_tuple;
use rustler::Encoder;
Expand Down Expand Up @@ -49,7 +49,7 @@ pub fn component_call_function<'a>(
let param_types = function.params(&mut *component_store);
let converted_params = match convert_params(param_types, given_params) {
Ok(params) => params,
Err(e) => return Ok(env.error_tuple("Unable to convert params")),
Err(e) => return Ok(env.error_tuple(format!("Unable to convert params: {:?}", e))),
};
let results_count = function.results(&*component_store).len();

Expand All @@ -59,8 +59,8 @@ pub fn component_call_function<'a>(
converted_params.as_slice(),
&mut result,
) {
Ok(res) => {
function.post_return(&mut *component_store);
Ok(_) => {
let _ = function.post_return(&mut *component_store);
Ok(encode_result(env, result))
}
Err(err) => return Ok(env.error_tuple(format!("Error executing function: {err}"))),
Expand All @@ -70,7 +70,7 @@ pub fn component_call_function<'a>(
fn convert_params(param_types: Box<[Type]>, param_terms: Vec<Term>) -> Result<Vec<Val>, Error> {
let mut params = Vec::with_capacity(param_types.len());

for (i, (param_term, param_type)) in param_terms.iter().zip(param_types.iter()).enumerate() {
for (_i, (param_term, param_type)) in param_terms.iter().zip(param_types.iter()).enumerate() {
let param = term_to_val(param_term, param_type)?;
params.push(param);
}
Expand Down Expand Up @@ -105,7 +105,7 @@ fn term_to_val(param_term: &Term, param_type: &Type) -> Result<Val, Error> {
let dedoded_tuple = tuple::get_tuple(*param_term)?;
let tuple_types = tuple.types();
let mut tuple_vals: Vec<Val> = Vec::with_capacity(tuple_types.len());
for (i, (tuple_type, tuple_term)) in tuple_types.zip(dedoded_tuple).enumerate() {
for (_i, (tuple_type, tuple_term)) in tuple_types.zip(dedoded_tuple).enumerate() {
let component_val = term_to_val(&tuple_term, &tuple_type)?;
tuple_vals.push(component_val);
}
Expand All @@ -131,14 +131,28 @@ fn term_to_val(param_term: &Term, param_type: &Type) -> Result<Val, Error> {
}
Ok(Val::Record(kv))
}
(_, _) => Ok(Val::Bool(false)),
(TermType::Atom, Type::Option(option_type)) => {
let the_atom = param_term.atom_to_string()?;
if the_atom == "nil" {
Ok(Val::Option(None))
} else {
let converted_val = term_to_val(param_term, &option_type.ty())?;
Ok(Val::Option(Some(Box::new(converted_val))))
}
}
(_term_type, Type::Option(option_type)) => {
let converted_val = term_to_val(param_term, &option_type.ty())?;
Ok(Val::Option(Some(Box::new(converted_val))))
}
(term_type, val_type) => {
Err(rustler::Error::Term(Box::new(format!(
"Could not convert {:?} to {:?}",
term_type, val_type
))))
}
}
}

fn make_error_tuple<'a>(reason: &str, env: rustler::Env<'a>) -> Term<'a> {
env.error_tuple(reason)
}

fn encode_result(env: rustler::Env, vals: Vec<Val>) -> Term {
let result_term = match vals.len() {
1 => val_to_term(vals.iter().next().unwrap(), env),
Expand Down Expand Up @@ -184,6 +198,10 @@ fn val_to_term<'a>(val: &Val, env: rustler::Env<'a>) -> Term<'a> {
.collect::<Vec<Term<'a>>>();
make_tuple(env, tuple_terms.as_slice())
}
Val::Option(option) => match option {
Some(boxed_val) => val_to_term(*&boxed_val, env),
None => nil().encode(env),
},
_ => String::from("wut").encode(env),
}
}
5 changes: 5 additions & 0 deletions test/components/component_types_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,9 @@ defmodule Wasm.Components.ComponentTypesTest do
assert {:ok, {1, "two"}} =
Wasmex.Components.Instance.call_function(instance, "id-tuple", [{1, "two"}])
end

test "option types", %{instance: instance} do
assert {:ok, 7} = Wasmex.Components.Instance.call_function(instance, "id-option", [7])
assert {:ok, nil} = Wasmex.Components.Instance.call_function(instance, "id-option", [nil])
end
end

0 comments on commit 0849dd7

Please sign in to comment.