Browse Source

Adding TryFromJs implementations for tuples (#3843)

* Adding TryFromJs implementations for tuples

* rustfmt and clippies

* rustfmt

* Remove unit type

* Clippies
pull/3882/head
Hans Larsen 6 months ago committed by GitHub
parent
commit
149693ae8b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 51
      core/engine/src/value/conversions/try_from_js.rs
  2. 41
      core/engine/src/value/conversions/try_from_js/tuples.rs

51
core/engine/src/value/conversions/try_from_js.rs

@ -5,6 +5,7 @@ use num_bigint::BigInt;
use crate::{js_string, Context, JsBigInt, JsNativeError, JsObject, JsResult, JsString, JsValue};
mod collections;
mod tuples;
/// This trait adds a fallible and efficient conversions from a [`JsValue`] to Rust types.
pub trait TryFromJs: Sized {
@ -367,6 +368,56 @@ fn value_into_vec() {
]);
}
#[test]
fn value_into_tuple() {
use boa_engine::{run_test_actions, TestAction};
use indoc::indoc;
run_test_actions([
TestAction::assert_with_op(indoc! {r#" [42, "hello", true] "#}, |value, context| {
type TestType = (i32, String, bool);
TestType::try_from_js(&value, context).unwrap() == (42, "hello".to_string(), true)
}),
TestAction::assert_with_op(indoc! {r#" [42, "hello", true] "#}, |value, context| {
type TestType = (i32, String, Option<bool>, Option<u8>);
TestType::try_from_js(&value, context).unwrap()
== (42, "hello".to_string(), Some(true), None)
}),
TestAction::assert_with_op(indoc! {r#" [] "#}, |value, context| {
type TestType = (
Option<bool>,
Option<bool>,
Option<bool>,
Option<bool>,
Option<bool>,
Option<bool>,
Option<bool>,
Option<bool>,
Option<bool>,
Option<bool>,
);
TestType::try_from_js(&value, context).unwrap()
== (None, None, None, None, None, None, None, None, None, None)
}),
TestAction::assert_with_op(indoc!(r#"[42, "hello", {}]"#), |value, context| {
type TestType = (i32, String, bool);
let Err(value) = TestType::try_from_js(&value, context) else {
return false;
};
assert!(value.to_string().contains("TypeError"));
true
}),
TestAction::assert_with_op(indoc!(r#"[42, "hello"]"#), |value, context| {
type TestType = (i32, String, bool);
let Err(value) = TestType::try_from_js(&value, context) else {
return false;
};
assert!(value.to_string().contains("TypeError"));
true
}),
]);
}
#[test]
fn value_into_map() {
use boa_engine::{run_test_actions, TestAction};

41
core/engine/src/value/conversions/try_from_js/tuples.rs

@ -0,0 +1,41 @@
//! Implementation of [`TryFromJs`] for tuples.
//!
//! Tuples are converted from a JavaScript array, using similar semantics to `TypeScript` tuples:
//! - If the tuple is shorter than the array, the extra elements are ignored.
//! - If the tuple is longer than the array, the extra elements are `undefined`.
//! - If the array is empty, all elements are `undefined`.
//!
//! A tuple of size 0 (unit type) does not implement [`TryFromJs`].
use crate::value::JsValue;
use crate::{Context, JsResult};
use super::TryFromJs;
macro_rules! impl_try_from_js_for_tuples {
($($name:ident),*) => {
impl<$($name: TryFromJs),*> TryFromJs for ($($name,)*) {
fn try_from_js(value: &JsValue, context: &mut Context) -> JsResult<Self> {
let vec: Vec<JsValue> = value.try_js_into(context)?;
let mut iter = vec.into_iter();
Ok((
$(
$name::try_from_js(&iter.next().unwrap_or_else(JsValue::undefined), context)?,
)*
))
}
}
};
}
impl_try_from_js_for_tuples!(A);
impl_try_from_js_for_tuples!(A, B);
impl_try_from_js_for_tuples!(A, B, C);
impl_try_from_js_for_tuples!(A, B, C, D);
impl_try_from_js_for_tuples!(A, B, C, D, E);
impl_try_from_js_for_tuples!(A, B, C, D, E, F);
impl_try_from_js_for_tuples!(A, B, C, D, E, F, G);
impl_try_from_js_for_tuples!(A, B, C, D, E, F, G, H);
impl_try_from_js_for_tuples!(A, B, C, D, E, F, G, H, I);
impl_try_from_js_for_tuples!(A, B, C, D, E, F, G, H, I, J);
Loading…
Cancel
Save