Skip to content

Commit

Permalink
Started fixing #8
Browse files Browse the repository at this point in the history
  • Loading branch information
Genarito committed May 4, 2024
1 parent 3c9a8c4 commit 1db10de
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 37 deletions.
70 changes: 51 additions & 19 deletions src/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> {
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,
Expand Down Expand Up @@ -34,7 +41,7 @@ impl Deserializer {
if let GuraType::Bool(boolean) = self.obj {
Ok(boolean)
} else {
Err(Error::ExpectedBoolean)
Err(Error::ExpectedBoolean(None))
}
}

Expand All @@ -46,10 +53,10 @@ impl Deserializer {
if let Ok(key_unsigned) = key.parse::<usize>() {
Ok(key_unsigned)
} else {
Err(Error::ExpectedInteger)
Err(Error::ExpectedInteger(None))
}
}
_ => Err(Error::ExpectedInteger),
_ => Err(Error::ExpectedInteger(None)),
}
}

Expand All @@ -60,19 +67,17 @@ impl Deserializer {
if let Ok(key_signed) = key.parse::<isize>() {
Ok(key_signed)
} else {
Err(Error::ExpectedInteger)
Err(Error::ExpectedInteger(None))
}
}
_ => {
Err(Error::ExpectedInteger)
}
_ => Err(Error::ExpectedInteger(None)),
}
}

fn parse_float(&mut self) -> Result<f64> {
match &self.obj {
GuraType::Float(float_value) => Ok(*float_value),
_ => Err(Error::ExpectedFloat),
_ => Err(Error::ExpectedFloat(None)),
}
}

Expand All @@ -81,18 +86,18 @@ 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))
}
}

fn parse_string(&mut self) -> Result<String> {
match &self.obj {
GuraType::Pair(key, _, _) => Ok(key.clone()),
GuraType::String(str_value) => Ok(str_value.clone()),
_ => Err(Error::ExpectedString),
_ => Err(Error::ExpectedString(None)),
}
}
}
Expand Down Expand Up @@ -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)),
}
}

Expand Down Expand Up @@ -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))
}
}

Expand All @@ -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<V>(
self,
_name: &'static str,
_fields: &'static [&'static str],
name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value>
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<V>(
Expand Down Expand Up @@ -397,15 +429,15 @@ impl CommaSeparated {
if let Some(elem) = self.vec.front() {
Ok(elem.clone())
} else {
Err(Error::ExpectedMap)
Err(Error::ExpectedMap(None))
}
}

fn get_next_elem(&mut self) -> Result<(String, GuraType)> {
if let Some(elem) = self.vec.pop_front() {
Ok(elem)
} else {
Err(Error::ExpectedMap)
Err(Error::ExpectedMap(None))
}
}
}
Expand Down Expand Up @@ -486,7 +518,7 @@ impl Enum {
if let Some(elem) = self.vec.front() {
Ok(elem.clone())
} else {
Err(Error::ExpectedMap)
Err(Error::ExpectedMap(None))
}
}
}
Expand Down
55 changes: 37 additions & 18 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,19 @@ use std::fmt::{self, Display};

pub type Result<T> = std::result::Result<T, Error>;

/// Write error message to formatter
fn write_error(
f: &mut fmt::Formatter,
msg_option: &Option<String>,
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 {
Expand All @@ -19,16 +32,16 @@ pub enum Error {
Eof,
Syntax(String),
ExpectedBytes,
ExpectedBoolean,
ExpectedInteger,
ExpectedFloat,
ExpectedChar,
ExpectedString,
ExpectedBoolean(Option<String>),
ExpectedInteger(Option<String>),
ExpectedFloat(Option<String>),
ExpectedChar(Option<String>),
ExpectedString(Option<String>),
ExpectedNull,
ExpectedArray,
ExpectedArray(Option<String>),
ExpectedArrayComma,
ExpectedArrayEnd,
ExpectedMap,
ExpectedMap(Option<String>),
ExpectedMapColon,
ExpectedMapComma,
ExpectedMapEnd,
Expand Down Expand Up @@ -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,
Expand All @@ -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"),
Expand Down

0 comments on commit 1db10de

Please sign in to comment.