git.delta.rocks / jrsonnet / refs/commits / a51d3e524236

difftreelog

feat impl Typed for BTreeMap

Yaroslav Bolyukin2023-07-27parent: #9567d36.patch.diff
in: master

2 files changed

modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/typed/conversions.rs
+++ b/crates/jrsonnet-evaluator/src/typed/conversions.rs
@@ -347,6 +347,51 @@
 	}
 }
 
+impl<K: Typed + Ord, V: Typed> Typed for BTreeMap<K, V> {
+	const TYPE: &'static ComplexValType = &ComplexValType::AttrsOf(V::TYPE);
+
+	fn into_untyped(typed: Self) -> Result<Val> {
+		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> {
+		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;
 
modifiedcrates/jrsonnet-evaluator/src/typed/mod.rsdiffbeforeafterboth
191 }191 }
192 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),192 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),
193 },193 },
194 Self::AttrsOf(a) => match value {
195 Val::Obj(o) => {
196 for (_key, value) in o.iter(
197 #[cfg(feature = "exp-preserve-order")]
198 false,
199 ) {
200 let value = value?;
201 a.check(&value)?;
202 }
203 Ok(())
204 }
205 v => Err(TypeError::ExpectedGot(self.clone(), v.value_type()).into()),
206 },
194 Self::ObjectRef(elems) => match value {207 Self::ObjectRef(elems) => match value {
195 Val::Obj(obj) => {208 Val::Obj(obj) => {
196 for (k, v) in elems.iter() {209 for (k, v) in elems.iter() {