From a51d3e524236c48f7a9225441b1be1e3afc49329 Mon Sep 17 00:00:00 2001 From: Yaroslav Bolyukin Date: Thu, 27 Jul 2023 14:23:34 +0000 Subject: [PATCH] feat: impl Typed for BTreeMap --- --- a/crates/jrsonnet-evaluator/src/typed/conversions.rs +++ b/crates/jrsonnet-evaluator/src/typed/conversions.rs @@ -347,6 +347,51 @@ } } +impl Typed for BTreeMap { + const TYPE: &'static ComplexValType = &ComplexValType::AttrsOf(V::TYPE); + + fn into_untyped(typed: Self) -> Result { + let mut out = ObjValueBuilder::with_capacity(typed.len()); + for (k, v) in typed { + let Some(key) = K::into_untyped(k)?.as_str() else { + throw!("map key should serialize to string"); + }; + let value = V::into_untyped(v)?; + out.member(key).value_unchecked(value); + } + Ok(Val::Obj(out.build())) + } + + fn from_untyped(value: Val) -> Result { + Self::TYPE.check(&value)?; + let obj = value.as_obj().expect("typecheck should fail"); + + let mut out = BTreeMap::new(); + if V::wants_lazy() { + for key in obj.fields_ex( + false, + #[cfg(feature = "exp-preserve-order")] + false, + ) { + let value = obj.get_lazy(key.clone()).expect("field exists"); + let value = V::from_lazy_untyped(value)?; + let key = K::from_untyped(Val::Str(key.into()))?; + let _ = out.insert(key, value); + } + } else { + for (key, value) in obj.iter( + #[cfg(feature = "exp-preserve-order")] + false, + ) { + let key = K::from_untyped(Val::Str(key.into()))?; + let value = V::from_untyped(value?)?; + let _ = out.insert(key, value); + } + } + Ok(out) + } +} + impl Typed for Val { const TYPE: &'static ComplexValType = &ComplexValType::Any; --- a/crates/jrsonnet-evaluator/src/typed/mod.rs +++ b/crates/jrsonnet-evaluator/src/typed/mod.rs @@ -191,6 +191,19 @@ } v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()), }, + Self::AttrsOf(a) => match value { + Val::Obj(o) => { + for (_key, value) in o.iter( + #[cfg(feature = "exp-preserve-order")] + false, + ) { + let value = value?; + a.check(&value)?; + } + Ok(()) + } + v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()), + }, Self::ObjectRef(elems) => match value { Val::Obj(obj) => { for (k, v) in elems.iter() { -- gitstuff