diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml index c62c854..3a78585 100644 --- a/interpreter/Cargo.toml +++ b/interpreter/Cargo.toml @@ -8,6 +8,9 @@ edition = "2018" license = "MIT" categories = ["interpreter", "cel"] +[features] +pared = ["dep:pared"] + [dependencies] cel-parser = { path = "../parser", version = "0.6.0" } thiserror = "1.0.40" @@ -16,6 +19,7 @@ nom = "7.1.3" paste = "1.0.14" serde = "1.0.196" regex = "1.10.5" +pared = { version="0.3.0", optional = true } [dev-dependencies] criterion = { version = "0.5.1", features = ["html_reports"] } diff --git a/interpreter/src/functions.rs b/interpreter/src/functions.rs index dbcfd35..e0e7e4a 100644 --- a/interpreter/src/functions.rs +++ b/interpreter/src/functions.rs @@ -547,7 +547,6 @@ mod tests { use std::sync::Arc; use crate::context::Context; - use crate::objects::{DynamicCollection, MemberResolver, ResolvedMember}; use crate::testing::test_script; use crate::Value; use std::collections::HashMap; @@ -789,8 +788,12 @@ mod tests { assert_eq!(test_script("hello == 'world'", Some(ctx)), Ok(true.into())); } + #[cfg(feature = "pared")] #[test] fn test_deep_dynamic_resolver() { + use pared::sync::Parc; + use crate::objects::{MemberResolver, ParcDynamicCollection, ResolvedMember}; + #[derive(Clone)] struct Species { name: String, @@ -798,9 +801,8 @@ mod tests { homeworld: Option, } - impl DynamicCollection for Species { - fn resolver(&self) -> MemberResolver { - let receiver = self.clone(); + impl ParcDynamicCollection for Species { + fn resolver(receiver: Parc) -> MemberResolver { MemberResolver::new(move |name| match name { ResolvedMember::Attribute(name) => match name.as_str() { "name" => Some(receiver.name.clone().into()), @@ -826,9 +828,8 @@ mod tests { species: Species, } - impl DynamicCollection for Character { - fn resolver(&self) -> MemberResolver { - let receiver = self.clone(); + impl ParcDynamicCollection for Character { + fn resolver(receiver: Parc) -> MemberResolver { MemberResolver::new(move |member| match member { ResolvedMember::Attribute(name) => match name.as_str() { "name" => Some(receiver.name.clone().into()), @@ -836,7 +837,7 @@ mod tests { Some(v) => Some(v.clone().into()), None => Some(Value::Null), }, - "species" => Some(receiver.species.clone().into()), + "species" => Some(receiver.project(|receiver| &receiver.species).into()), _ => None, }, _ => None, @@ -851,9 +852,8 @@ mod tests { characters: Vec, } - impl DynamicCollection for Film { - fn resolver(&self) -> MemberResolver { - let receiver = self.clone(); + impl ParcDynamicCollection for Film { + fn resolver(receiver: Parc) -> MemberResolver { MemberResolver::new(move |member| { let receiver = receiver.clone(); match member { @@ -864,10 +864,11 @@ mod tests { move |member| { let receiver = receiver.clone(); match member { - ResolvedMember::Index(Value::Int(idx)) => receiver - .characters - .get(idx as usize) - .map(|v| v.clone().into()), + ResolvedMember::Index(Value::Int(idx)) => { + receiver.try_project( + |receiver| receiver.characters.get(idx as usize).ok_or(()) + ).ok().map(|x| x.into()) + } _ => None, } }, @@ -880,7 +881,7 @@ mod tests { } } - let doc = Film { + let doc = Parc::new(Film { director: "George Lucas".to_string(), title: "A New Hope".to_string(), characters: vec![ @@ -912,7 +913,7 @@ mod tests { }, }, ], - }; + }); let mut ctx = Context::default(); ctx.set_dynamic_resolver(move |name| match name { diff --git a/interpreter/src/objects.rs b/interpreter/src/objects.rs index a19fe7e..f295334 100644 --- a/interpreter/src/objects.rs +++ b/interpreter/src/objects.rs @@ -721,6 +721,19 @@ where T: DynamicCollection { } } +#[cfg(feature = "pared")] +pub trait ParcDynamicCollection { + fn resolver(item: pared::sync::Parc) -> MemberResolver; +} + +#[cfg(feature = "pared")] +impl From> for Value +where T: ParcDynamicCollection { + fn from(item: pared::sync::Parc) -> Self { + Value::DynamicCollection(T::resolver(item)) + } +} + impl ops::Add for Value { type Output = Value;