--- a/crates/jrsonnet-evaluator/src/integrations/serde.rs +++ b/crates/jrsonnet-evaluator/src/integrations/serde.rs @@ -1,12 +1,21 @@ use std::borrow::Cow; +use jrsonnet_interner::IStr; use serde::{ de::Visitor, - ser::{Error, SerializeMap, SerializeSeq}, - Deserialize, Serialize, + ser::{ + Error, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple, + SerializeTupleStruct, SerializeTupleVariant, + }, + Deserialize, Serialize, Serializer, }; -use crate::{arr::ArrValue, error::Result, val::StrValue, ObjValueBuilder, State, Val}; +use crate::{ + arr::ArrValue, + error::{Error as JrError, ErrorKind, Result}, + val::StrValue, + ObjValue, ObjValueBuilder, State, Val, +}; impl<'de> Deserialize<'de> for Val { fn deserialize(deserializer: D) -> Result @@ -204,3 +213,404 @@ } } } + +struct IntoVecValSerializer { + variant: Option, + data: Vec, +} +impl IntoVecValSerializer { + fn new() -> Self { + Self { + variant: None, + data: Vec::new(), + } + } + fn with_capacity(capacity: usize) -> Self { + Self { + variant: None, + data: Vec::with_capacity(capacity), + } + } + fn variant_with_capacity(variant: impl Into, capacity: usize) -> Self { + Self { + variant: Some(variant.into()), + data: Vec::with_capacity(capacity), + } + } +} +impl SerializeSeq for IntoVecValSerializer { + type Ok = Val; + type Error = JrError; + + fn serialize_element(&mut self, value: &T) -> Result<()> + where + T: Serialize, + { + let value = value.serialize(IntoValSerializer)?; + self.data.push(value); + Ok(()) + } + + fn end(self) -> Result { + let inner = Val::Arr(ArrValue::eager(self.data)); + if let Some(variant) = self.variant { + let mut out = ObjValue::builder_with_capacity(1); + out.member(variant).value_unchecked(inner); + Ok(Val::Obj(out.build())) + } else { + Ok(inner) + } + } +} +impl SerializeTuple for IntoVecValSerializer { + type Ok = Val; + type Error = JrError; + + fn serialize_element(&mut self, value: &T) -> Result<()> + where + T: Serialize, + { + SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result { + SerializeSeq::end(self) + } +} +impl SerializeTupleVariant for IntoVecValSerializer { + type Ok = Val; + type Error = JrError; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where + T: Serialize, + { + SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result { + SerializeSeq::end(self) + } +} +impl SerializeTupleStruct for IntoVecValSerializer { + type Ok = Val; + type Error = JrError; + + fn serialize_field(&mut self, value: &T) -> Result<()> + where + T: Serialize, + { + SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result { + SerializeSeq::end(self) + } +} + +struct IntoObjValueSerializer { + variant: Option, + data: ObjValueBuilder, + key: Option, +} +impl IntoObjValueSerializer { + fn new() -> Self { + Self { + variant: None, + data: ObjValue::builder(), + key: None, + } + } + fn with_capacity(capacity: usize) -> Self { + Self { + variant: None, + data: ObjValue::builder_with_capacity(capacity), + key: None, + } + } + fn variant_with_capacity(variant: impl Into, capacity: usize) -> Self { + Self { + variant: Some(variant.into()), + data: ObjValue::builder_with_capacity(capacity), + key: None, + } + } +} +impl SerializeMap for IntoObjValueSerializer { + type Ok = Val; + type Error = JrError; + + fn serialize_key(&mut self, key: &T) -> Result<()> + where + T: Serialize, + { + let key = key.serialize(IntoValSerializer)?; + let key = key.to_string()?; + self.key = Some(key); + Ok(()) + } + + fn serialize_value(&mut self, value: &T) -> Result<()> + where + T: Serialize, + { + let key = self.key.take().expect("no serialize_key called"); + let value = value.serialize(IntoValSerializer)?; + self.data.member(key).value(value)?; + Ok(()) + } + + // TODO: serialize_key/serialize_value + fn serialize_entry(&mut self, key: &K, value: &V) -> Result<()> + where + K: Serialize, + V: Serialize, + { + let key = key.serialize(IntoValSerializer)?; + let key = key.to_string()?; + let value = value.serialize(IntoValSerializer)?; + self.data.member(key).value(value)?; + Ok(()) + } + + fn end(self) -> Result { + let inner = Val::Obj(self.data.build()); + if let Some(variant) = self.variant { + let mut out = ObjValue::builder_with_capacity(1); + out.member(variant).value_unchecked(inner); + Ok(Val::Obj(out.build())) + } else { + Ok(inner) + } + } +} +impl SerializeStruct for IntoObjValueSerializer { + type Ok = Val; + type Error = JrError; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where + T: Serialize, + { + SerializeMap::serialize_entry(self, key, value)?; + Ok(()) + } + + fn end(self) -> Result { + SerializeMap::end(self) + } +} +impl SerializeStructVariant for IntoObjValueSerializer { + type Ok = Val; + + type Error = JrError; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> + where + T: Serialize, + { + SerializeMap::serialize_entry(self, key, value)?; + Ok(()) + } + + fn end(self) -> Result { + SerializeMap::end(self) + } +} + +struct IntoValSerializer; +impl Serializer for IntoValSerializer { + type Ok = Val; + + type Error = JrError; + + type SerializeSeq = IntoVecValSerializer; + + type SerializeTuple = IntoVecValSerializer; + + type SerializeTupleStruct = IntoVecValSerializer; + + type SerializeTupleVariant = IntoVecValSerializer; + + type SerializeMap = IntoObjValueSerializer; + + type SerializeStruct = IntoObjValueSerializer; + + type SerializeStructVariant = IntoObjValueSerializer; + + fn serialize_bool(self, v: bool) -> Result { + Ok(Val::Bool(v)) + } + + fn serialize_i8(self, v: i8) -> Result { + Ok(Val::Num(f64::from(v))) + } + + fn serialize_i16(self, v: i16) -> Result { + Ok(Val::Num(f64::from(v))) + } + + fn serialize_i32(self, v: i32) -> Result { + Ok(Val::Num(f64::from(v))) + } + + fn serialize_i64(self, v: i64) -> Result { + Ok(Val::Str(v.to_string().into())) + } + + fn serialize_u8(self, v: u8) -> Result { + Ok(Val::Num(f64::from(v))) + } + + fn serialize_u16(self, v: u16) -> Result { + Ok(Val::Num(f64::from(v))) + } + + fn serialize_u32(self, v: u32) -> Result { + Ok(Val::Num(f64::from(v))) + } + + fn serialize_u64(self, v: u64) -> Result { + Ok(Val::Str(v.to_string().into())) + } + + fn serialize_f32(self, v: f32) -> Result { + Ok(Val::Num(f64::from(v))) + } + + fn serialize_f64(self, v: f64) -> Result { + Ok(Val::Num(v)) + } + + fn serialize_char(self, v: char) -> Result { + Ok(Val::Str(v.to_string().into())) + } + + fn serialize_str(self, v: &str) -> Result { + Ok(Val::Str(v.into())) + } + + fn serialize_bytes(self, v: &[u8]) -> Result { + Ok(Val::Arr(ArrValue::bytes(v.into()))) + } + + fn serialize_none(self) -> Result { + Ok(Val::Null) + } + + fn serialize_some(self, value: &T) -> Result + where + T: Serialize, + { + value.serialize(self) + } + + fn serialize_unit(self) -> Result { + Ok(Val::Null) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + Ok(Val::Null) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result { + Ok(Val::Str(variant.into())) + } + + fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result + where + T: Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result + where + T: Serialize, + { + let mut out = ObjValue::builder_with_capacity(1); + let value = value.serialize(self)?; + out.member(variant.into()).value_unchecked(value); + Ok(Val::Obj(out.build())) + } + + fn serialize_seq(self, len: Option) -> Result { + Ok(len.map_or_else( + IntoVecValSerializer::new, + IntoVecValSerializer::with_capacity, + )) + } + + fn serialize_tuple(self, len: usize) -> Result { + Ok(IntoVecValSerializer::with_capacity(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + Ok(IntoVecValSerializer::with_capacity(len)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + Ok(IntoVecValSerializer::variant_with_capacity(variant, len)) + } + + fn serialize_map(self, len: Option) -> Result { + Ok(len.map_or_else( + IntoObjValueSerializer::new, + IntoObjValueSerializer::with_capacity, + )) + } + + fn serialize_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + Ok(IntoObjValueSerializer::with_capacity(len)) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + Ok(IntoObjValueSerializer::variant_with_capacity(variant, len)) + } +} + +impl Val { + pub fn from_serde(v: impl Serialize) -> Result { + v.serialize(IntoValSerializer) + } +} + +impl serde::ser::Error for JrError { + fn custom(msg: T) -> Self + where + T: std::fmt::Display, + { + JrError::new(ErrorKind::RuntimeError(format!("serde: {msg}").into())) + } +}