From c3e7b9004d136fd968468abc7559f003a9f7d235 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Fri, 30 Oct 2020 20:10:33 +0000 Subject: Roll our own Value for binary decoding --- dhall/src/syntax/binary/decode.rs | 174 +++++++++++++++++++++++++++++++++++--- 1 file changed, 162 insertions(+), 12 deletions(-) (limited to 'dhall') diff --git a/dhall/src/syntax/binary/decode.rs b/dhall/src/syntax/binary/decode.rs index d360949..f4747d3 100644 --- a/dhall/src/syntax/binary/decode.rs +++ b/dhall/src/syntax/binary/decode.rs @@ -1,5 +1,7 @@ use itertools::Itertools; -use serde_cbor::value::value as cbor; +use serde::de; +use std::collections::BTreeMap; +use std::fmt; use std::iter::FromIterator; use crate::error::DecodeError; @@ -19,18 +21,32 @@ pub fn decode(data: &[u8]) -> Result { } } +/// An enum that can encode most CBOR values. +#[derive(Clone, Debug, PartialEq)] +pub enum Value { + Null, + Bool(bool), + U64(u64), + I64(i64), + F64(f64), + String(String), + Array(Vec), + Object(BTreeMap), + Bytes(Vec), +} + // Should probably rename this fn rc(x: UnspannedExpr) -> Expr { Expr::new(x, Span::Decoded) } -fn cbor_value_to_dhall(data: &cbor::Value) -> Result { +fn cbor_value_to_dhall(data: &Value) -> Result { use crate::builtins::Builtin; use crate::operations::BinOp; - use cbor::Value::*; use syntax::Const; use ExprKind::*; use OpKind::*; + use Value::*; Ok(rc(match data { String(s) => match Builtin::parse(s) { Some(b) => ExprKind::Builtin(b), @@ -467,16 +483,13 @@ fn cbor_value_to_dhall(data: &cbor::Value) -> Result { } fn cbor_map_to_dhall_map<'a, T>( - map: impl IntoIterator, + map: impl IntoIterator, ) -> Result where T: FromIterator<(Label, DecodedExpr)>, { map.into_iter() .map(|(k, v)| -> Result<(_, _), _> { - let k = k.as_string().ok_or_else(|| { - DecodeError::WrongFormatError("map/key".to_owned()) - })?; let v = cbor_value_to_dhall(v)?; Ok((Label::from(k.as_ref()), v)) }) @@ -484,21 +497,158 @@ where } fn cbor_map_to_dhall_opt_map<'a, T>( - map: impl IntoIterator, + map: impl IntoIterator, ) -> Result where T: FromIterator<(Label, Option)>, { map.into_iter() .map(|(k, v)| -> Result<(_, _), _> { - let k = k.as_string().ok_or_else(|| { - DecodeError::WrongFormatError("map/key".to_owned()) - })?; let v = match v { - cbor::Value::Null => None, + Value::Null => None, _ => Some(cbor_value_to_dhall(v)?), }; Ok((Label::from(k.as_ref()), v)) }) .collect::>() } + +impl Value { + pub fn as_string(&self) -> Option<&String> { + if let Value::String(v) = self { + Some(v) + } else { + None + } + } +} + +impl<'de> de::Deserialize<'de> for Value { + #[inline] + fn deserialize(deserializer: D) -> Result + where + D: de::Deserializer<'de>, + { + struct ValueVisitor; + + impl<'de> de::Visitor<'de> for ValueVisitor { + type Value = Value; + + fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt.write_str("any valid CBOR value") + } + + #[inline] + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + self.visit_string(String::from(value)) + } + + #[inline] + fn visit_string(self, value: String) -> Result + where + E: de::Error, + { + Ok(Value::String(value)) + } + #[inline] + fn visit_bytes(self, v: &[u8]) -> Result + where + E: de::Error, + { + self.visit_byte_buf(v.to_owned()) + } + + #[inline] + fn visit_byte_buf(self, v: Vec) -> Result + where + E: de::Error, + { + Ok(Value::Bytes(v)) + } + + #[inline] + fn visit_u64(self, v: u64) -> Result + where + E: de::Error, + { + Ok(Value::U64(v)) + } + + #[inline] + fn visit_i64(self, v: i64) -> Result + where + E: de::Error, + { + Ok(Value::I64(v)) + } + + #[inline] + fn visit_bool(self, v: bool) -> Result + where + E: de::Error, + { + Ok(Value::Bool(v)) + } + + #[inline] + fn visit_none(self) -> Result + where + E: de::Error, + { + self.visit_unit() + } + + #[inline] + fn visit_unit(self) -> Result + where + E: de::Error, + { + Ok(Value::Null) + } + + #[inline] + fn visit_seq( + self, + mut visitor: V, + ) -> Result + where + V: de::SeqAccess<'de>, + { + let mut vec = Vec::new(); + + while let Some(elem) = visitor.next_element()? { + vec.push(elem); + } + + Ok(Value::Array(vec)) + } + + #[inline] + fn visit_map(self, mut visitor: V) -> Result + where + V: de::MapAccess<'de>, + { + let mut values = BTreeMap::new(); + + while let Some((key, value)) = visitor.next_entry()? { + values.insert(key, value); + } + + Ok(Value::Object(values)) + } + + #[inline] + fn visit_f64(self, v: f64) -> Result + where + E: de::Error, + { + Ok(Value::F64(v)) + } + } + + deserializer.deserialize_any(ValueVisitor) + } +} -- cgit v1.2.3