From 1db10de5c4a9c5f6858830ede06e40501d9b1432 Mon Sep 17 00:00:00 2001 From: Genaro Camele Date: Sat, 4 May 2024 13:47:22 -0300 Subject: [PATCH] Started fixing #8 --- src/de.rs | 70 ++++++++++++++++++++++++++++++++++++++-------------- src/error.rs | 55 +++++++++++++++++++++++++++-------------- 2 files changed, 88 insertions(+), 37 deletions(-) diff --git a/src/de.rs b/src/de.rs index 2d11bdb..74d3ea5 100644 --- a/src/de.rs +++ b/src/de.rs @@ -6,6 +6,13 @@ use serde::de::{ }; use std::collections::VecDeque; +/// Generates an error message with the expected type and the field name +fn get_error_with_field_msg(expected_type: &'static str, name: &'static str, fields: &'static [&'static str]) -> Option { + let fields_joined = fields.join("."); + let failed_struct_str = format!("Expected {} for {}[{}]", expected_type, name, fields_joined); + Some(failed_struct_str) +} + #[derive(Debug)] pub struct Deserializer { obj: GuraType, @@ -34,7 +41,7 @@ impl Deserializer { if let GuraType::Bool(boolean) = self.obj { Ok(boolean) } else { - Err(Error::ExpectedBoolean) + Err(Error::ExpectedBoolean(None)) } } @@ -46,10 +53,10 @@ impl Deserializer { if let Ok(key_unsigned) = key.parse::() { Ok(key_unsigned) } else { - Err(Error::ExpectedInteger) + Err(Error::ExpectedInteger(None)) } } - _ => Err(Error::ExpectedInteger), + _ => Err(Error::ExpectedInteger(None)), } } @@ -60,19 +67,17 @@ impl Deserializer { if let Ok(key_signed) = key.parse::() { Ok(key_signed) } else { - Err(Error::ExpectedInteger) + Err(Error::ExpectedInteger(None)) } } - _ => { - Err(Error::ExpectedInteger) - } + _ => Err(Error::ExpectedInteger(None)), } } fn parse_float(&mut self) -> Result { match &self.obj { GuraType::Float(float_value) => Ok(*float_value), - _ => Err(Error::ExpectedFloat), + _ => Err(Error::ExpectedFloat(None)), } } @@ -81,10 +86,10 @@ impl Deserializer { if str.len() == 1 { Ok(str.chars().next().unwrap()) } else { - Err(Error::ExpectedChar) + Err(Error::ExpectedChar(None)) } } else { - Err(Error::ExpectedChar) + Err(Error::ExpectedChar(None)) } } @@ -92,7 +97,7 @@ impl Deserializer { match &self.obj { GuraType::Pair(key, _, _) => Ok(key.clone()), GuraType::String(str_value) => Ok(str_value.clone()), - _ => Err(Error::ExpectedString), + _ => Err(Error::ExpectedString(None)), } } } @@ -273,7 +278,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer { let value = visitor.visit_seq(CommaSeparated::new(obj))?; Ok(value) } - _ => Err(Error::ExpectedArray), + _ => Err(Error::ExpectedArray(None)), } } @@ -310,7 +315,7 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer { let value = visitor.visit_map(CommaSeparated::new(obj_aux))?; Ok(value) } else { - Err(Error::ExpectedMap) + Err(Error::ExpectedMap(None)) } } @@ -320,14 +325,41 @@ impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer { // the fields cannot be known ahead of time is probably a map. fn deserialize_struct( self, - _name: &'static str, - _fields: &'static [&'static str], + name: &'static str, + fields: &'static [&'static str], visitor: V, ) -> Result where V: Visitor<'de>, { - self.deserialize_map(visitor) + // TODO: add current type of value and add to the message + match self.deserialize_map(visitor) { + Ok(value) => Ok(value), + Err(Error::ExpectedBoolean(None)) => { + Err(Error::ExpectedBoolean(get_error_with_field_msg("boolean", name, fields))) + } + Err(Error::ExpectedInteger(None)) => { + Err(Error::ExpectedInteger(get_error_with_field_msg("integer", name, fields))) + } + Err(Error::ExpectedFloat(None)) => { + Err(Error::ExpectedFloat(get_error_with_field_msg("float", name, fields))) + } + Err(Error::ExpectedChar(None)) => { + Err(Error::ExpectedChar(get_error_with_field_msg("char", name, fields))) + } + Err(Error::ExpectedString(None)) => { + Err(Error::ExpectedString(get_error_with_field_msg("string", name, fields))) + } + Err(Error::ExpectedArray(None)) => { + Err(Error::ExpectedArray(get_error_with_field_msg("array", name, fields))) + } + Err(Error::ExpectedMap(None)) => { + Err(Error::ExpectedMap(get_error_with_field_msg("map", name, fields))) + } + Err(err) => { + Err(err) + }, + } } fn deserialize_enum( @@ -397,7 +429,7 @@ impl CommaSeparated { if let Some(elem) = self.vec.front() { Ok(elem.clone()) } else { - Err(Error::ExpectedMap) + Err(Error::ExpectedMap(None)) } } @@ -405,7 +437,7 @@ impl CommaSeparated { if let Some(elem) = self.vec.pop_front() { Ok(elem) } else { - Err(Error::ExpectedMap) + Err(Error::ExpectedMap(None)) } } } @@ -486,7 +518,7 @@ impl Enum { if let Some(elem) = self.vec.front() { Ok(elem.clone()) } else { - Err(Error::ExpectedMap) + Err(Error::ExpectedMap(None)) } } } diff --git a/src/error.rs b/src/error.rs index 70baa4e..eafc005 100644 --- a/src/error.rs +++ b/src/error.rs @@ -3,6 +3,19 @@ use std::fmt::{self, Display}; pub type Result = std::result::Result; +/// Write error message to formatter +fn write_error( + f: &mut fmt::Formatter, + msg_option: &Option, + msg_default: &'static str, +) -> fmt::Result { + if let Some(msg_value) = msg_option { + f.write_str(msg_value) + } else { + f.write_str(msg_default) + } +} + /// Types of errors that may occur during serialization/deserialization #[derive(Clone, Debug, PartialEq)] pub enum Error { @@ -19,16 +32,16 @@ pub enum Error { Eof, Syntax(String), ExpectedBytes, - ExpectedBoolean, - ExpectedInteger, - ExpectedFloat, - ExpectedChar, - ExpectedString, + ExpectedBoolean(Option), + ExpectedInteger(Option), + ExpectedFloat(Option), + ExpectedChar(Option), + ExpectedString(Option), ExpectedNull, - ExpectedArray, + ExpectedArray(Option), ExpectedArrayComma, ExpectedArrayEnd, - ExpectedMap, + ExpectedMap(Option), ExpectedMapColon, ExpectedMapComma, ExpectedMapEnd, @@ -57,6 +70,7 @@ impl Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use Error::*; + // TODO: refactor all if let/else in a function match self { Syntax(msg) => write!( f, @@ -68,20 +82,25 @@ impl Display for Error { UnitNotSupported => f.write_str("Unit values are not supported in Gura"), ExpectedBytes => f.write_str("Expected byte sequence"), - ExpectedBoolean => f.write_str("Expected boolean"), - ExpectedInteger => f.write_str("Expected integer"), - ExpectedFloat => f.write_str(concat!( - "Expected float: perhaps you forgot decimal fractional part", - " (No implicit coversion between int and float, ", - "see https://gura.netlify.app/docs/spec#float)" - )), - ExpectedChar => f.write_str("Expected char"), - ExpectedString => f.write_str("Expected string"), + ExpectedBoolean(msg) => write_error(f, msg, "Expected boolean"), + ExpectedInteger(msg) => write_error(f, msg, "Expected integer"), + ExpectedFloat(msg) => write_error( + f, + msg, + concat!( + "Expected float: perhaps you forgot decimal fractional part", + " (no implicit conversion between int and float, ", + "see https://gura.netlify.app/docs/spec#float)" + ), + ), + ExpectedChar(msg) => write_error(f, msg, "Expected char"), + ExpectedString(msg) => write_error(f, msg, "Expected string"), ExpectedNull => f.write_str("Expected null value"), - ExpectedArray => f.write_str("Expected array"), + ExpectedArray(msg) => write_error(f, msg, "Expected array"), ExpectedArrayEnd => f.write_str("Expected array end"), - ExpectedMap => f.write_str("Expected map"), + // ExpectedMap => write!(f, "Expected map"), + ExpectedMap(msg) => write_error(f, msg, "Expected map"), ExpectedMapColon => f.write_str("Expected colon at map"), ExpectedMapComma => f.write_str("Expected comma at map"), ExpectedMapEnd => f.write_str("Expected map end"),