#![allow(clippy::disallowed_names)]
use rex::{
Rex,
engine::{Engine, EngineError, Handle, Module},
json::rex_to_json,
typesystem::Type,
};
use serde::{Deserialize, Serialize};
fn engine_with_prelude() -> Engine {
Engine::with_prelude(()).unwrap()
}
async fn eval_snippet<State: Clone + Send + Sync + 'static>(
engine: Engine<State>,
source: &str,
) -> Result<(Handle, Type), EngineError> {
engine
.into_evaluator()
.eval_snippet(source)
.await
.map_err(|err| err.into_engine_error())
}
#[derive(Rex, Clone, Debug, PartialEq, Deserialize, Serialize)]
enum EchoEnum {
Foo,
#[serde(rename = "BAR")]
Bar,
}
#[derive(Rex, Clone, Debug, PartialEq, Deserialize, Serialize)]
struct EchoRecord {
foo: u8,
bar: u8,
optbar: Option<u8>,
}
#[tokio::test]
async fn injected_echo_module_roundtrips_embedder_types_through_json() {
let mut engine = engine_with_prelude();
engine.add_default_resolvers();
let mut module = Module::new("echo");
module.add_rex_adt::<EchoEnum>().unwrap();
module.add_rex_adt::<EchoRecord>().unwrap();
module
.export(
"echo",
|_state: &(), variant: EchoEnum, record: EchoRecord| Ok((variant, record)),
)
.unwrap();
engine.inject_module(module).unwrap();
let type_system = engine.type_system.clone();
let (value_handle, ty) = eval_snippet(
engine,
r#"
import echo (EchoEnum, EchoRecord, Foo, BAR, echo);
let
foo_variant: EchoEnum = Foo,
foo_record: EchoRecord =
EchoRecord {
foo = (1 is u8),
bar = (2 is u8),
optbar = Some (3 is u8)
},
bar_variant: EchoEnum = BAR,
bar_record: EchoRecord =
EchoRecord {
foo = (4 is u8),
bar = (5 is u8),
optbar = None
},
foo_result = echo foo_variant foo_record,
bar_result = echo bar_variant bar_record
in
[foo_result, bar_result]
"#,
)
.await
.unwrap();
let parsed = rex_to_json(&value_handle, &ty, &type_system).unwrap();
let items = parsed.as_array().expect("expected top-level array");
assert_eq!(items.len(), 2);
let first = items[0].as_array().expect("expected tuple JSON array");
assert_eq!(first.len(), 2);
assert_eq!(
first[1],
serde_json::json!({ "foo": 1, "bar": 2, "optbar": 3 })
);
let first_variant = first[0].as_str().expect("expected enum JSON string");
assert_eq!(first_variant, "Foo");
let second = items[1].as_array().expect("expected tuple JSON array");
assert_eq!(second.len(), 2);
assert_eq!(
second[1],
serde_json::json!({ "foo": 4, "bar": 5, "optbar": null })
);
let second_variant = second[0].as_str().expect("expected enum JSON string");
assert_eq!(second_variant, "BAR");
}