diff --git a/Cargo.lock b/Cargo.lock index 1084a7925b..562face6db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -399,6 +399,7 @@ dependencies = [ "cfg-if", "criterion", "dashmap", + "either", "fast-float", "fixed_decimal", "float-cmp", diff --git a/core/engine/Cargo.toml b/core/engine/Cargo.toml index 385562358f..40883df1bd 100644 --- a/core/engine/Cargo.toml +++ b/core/engine/Cargo.toml @@ -14,6 +14,7 @@ rust-version.workspace = true [features] profiler = ["boa_profiler/profiler"] deser = ["boa_interner/serde", "boa_ast/serde"] +either = ["dep:either"] # Enables the `Intl` builtin object and bundles a default ICU4X data provider. # Prefer this over `intl` if you just want to enable `Intl` without dealing with the @@ -104,6 +105,7 @@ intrusive-collections = "0.9.6" cfg-if = "1.0.0" time.workspace = true hashbrown.workspace = true +either = { version = "1", optional = true } # intl deps boa_icu_provider = { workspace = true, features = ["std"], optional = true } diff --git a/core/engine/src/value/conversions/either.rs b/core/engine/src/value/conversions/either.rs new file mode 100644 index 0000000000..fa8eebe99f --- /dev/null +++ b/core/engine/src/value/conversions/either.rs @@ -0,0 +1,44 @@ +//! Implementation of [`TryFromJs`] for [`Either`]. +//! +//! This will try to deserialize for the [`Either::Left`] type +//! first, and if it fails will try the [`Either::Right`] type. +//! +//! Upon failure of both, the second failure will be returned. +#![cfg(feature = "either")] + +use crate::value::TryFromJs; +use boa_engine::{Context, JsResult, JsValue}; +use either::Either; + +impl TryFromJs for Either +where + L: TryFromJs, + R: TryFromJs, +{ + #[inline] + fn try_from_js(value: &JsValue, context: &mut Context) -> JsResult { + L::try_from_js(value, context) + .map(Self::Left) + .or_else(|_| R::try_from_js(value, context).map(Self::Right)) + } +} + +#[test] +fn either() { + let v = JsValue::Integer(123); + let mut context = Context::default(); + + assert_eq!( + Either::::try_from_js(&v, &mut context), + Ok(Either::Left(123)) + ); + assert_eq!( + Either::::try_from_js(&v, &mut context), + Ok(Either::Left(123)) + ); + assert_eq!( + Either::::try_from_js(&v, &mut context), + Ok(Either::Right(123)) + ); + assert!(Either::::try_from_js(&v, &mut context).is_err()); +} diff --git a/core/engine/src/value/conversions/mod.rs b/core/engine/src/value/conversions/mod.rs index 6d68ea075e..a23f048d08 100644 --- a/core/engine/src/value/conversions/mod.rs +++ b/core/engine/src/value/conversions/mod.rs @@ -4,6 +4,7 @@ use crate::js_string; use super::{JsBigInt, JsObject, JsString, JsSymbol, JsValue, Profiler}; +mod either; mod serde_json; pub(super) mod try_from_js;