Skip to content

Commit

Permalink
Non-String based Error implemenattion. Still remaining TODO's, but te…
Browse files Browse the repository at this point in the history
…sts all pass.
  • Loading branch information
Grinkers committed Dec 10, 2023
1 parent 29e853e commit 2cf6966
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 163 deletions.
6 changes: 2 additions & 4 deletions examples/complex_struct_deserialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,8 @@ fn complex_wrong() -> Result<(), EdnError> {
let complex: Result<Complex, EdnError> = edn_rs::from_str(bad_edn_str);

assert_eq!(
complex,
Err(EdnError::Deserialize(
"couldn't convert `\"some text\"` into `uint`".to_string()
))
format!("{}", complex.err().unwrap()),
"couldn't convert `\"some text\"` into `uint`"
);

Ok(())
Expand Down
6 changes: 2 additions & 4 deletions examples/from_edn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,8 @@ fn person_mistyped() -> Result<(), EdnError> {
let person: Result<Person, EdnError> = edn_rs::from_edn(&bad_edn);

assert_eq!(
person,
Err(EdnError::Deserialize(
"couldn't convert `\"some text\"` into `uint`".to_string()
))
format!("{}", person.err().unwrap()),
"couldn't convert `\"some text\"` into `uint`"
);

Ok(())
Expand Down
11 changes: 5 additions & 6 deletions examples/struct_from_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,8 @@ fn person_mistyped() -> Result<(), EdnError> {
let person: Result<Person, EdnError> = edn_rs::from_str(bad_edn_str);

assert_eq!(
person,
Err(EdnError::Deserialize(
"couldn't convert `\"some text\"` into `uint`".to_string()
))
format!("{}", person.err().unwrap()),
"couldn't convert `\"some text\"` into `uint`"
);

Ok(())
Expand All @@ -50,9 +48,10 @@ fn person_overflow() -> Result<(), EdnError> {
let overflow_edn_str = " {:name \"rose\" :age 9002 } ";
let person: Result<Person, EdnError> = edn_rs::from_str(overflow_edn_str);

let person = person.err().unwrap();
assert_eq!(
format!("{person:?}"),
"Err(TryFromInt(TryFromIntError(())))"
format!("{person}"),
"out of range integral type conversion attempted"
);

Ok(())
Expand Down
26 changes: 6 additions & 20 deletions src/deserialize/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::edn::{Edn, Error};
use crate::edn::Edn;
use crate::EdnError as Error;
use std::collections::{BTreeMap, HashMap};
#[cfg(feature = "sets")]
use std::collections::{BTreeSet, HashSet};
Expand All @@ -14,7 +15,7 @@ use ordered_float::OrderedFloat;
///
/// # Errors
///
/// Error will be like `EdnError::Deserialize("couldn't convert <value> into <type>")`
/// Error implements Display and Debug. See docs for more implementations.
///
/// ```
/// use crate::edn_rs::{Edn, EdnError, Deserialize};
Expand Down Expand Up @@ -51,12 +52,7 @@ use ordered_float::OrderedFloat;
/// let bad_edn_str = "{:name \"rose\" :age \"some text\" }";
/// let person: Result<Person, EdnError> = edn_rs::from_str(bad_edn_str);
///
/// assert_eq!(
/// person,
/// Err(EdnError::Deserialize(
/// "couldn't convert `\"some text\"` into `uint`".to_string()
/// ))
/// );
/// println!("{:?}", person);
/// ```
#[allow(clippy::missing_errors_doc)]
pub trait Deserialize: Sized {
Expand Down Expand Up @@ -338,12 +334,7 @@ where
/// let bad_edn_str = "{:name \"rose\" :age \"some text\" }";
/// let person: Result<Person, EdnError> = edn_rs::from_str(bad_edn_str);
///
/// assert_eq!(
/// person,
/// Err(EdnError::Deserialize(
/// "couldn't convert `\"some text\"` into `uint`".to_string()
/// ))
/// );
/// println!("{:?}", person);
/// ```
pub fn from_str<T: Deserialize>(s: &str) -> Result<T, Error> {
let edn = Edn::from_str(s)?;
Expand Down Expand Up @@ -397,12 +388,7 @@ pub fn from_str<T: Deserialize>(s: &str) -> Result<T, Error> {
/// }));
/// let person: Result<Person, EdnError> = edn_rs::from_edn(&bad_edn);
///
/// assert_eq!(
/// person,
/// Err(EdnError::Deserialize(
/// "couldn't convert `\"some text\"` into `uint`".to_string()
/// ))
/// );
/// println!("{:?}", person);
/// ```
pub fn from_edn<T: Deserialize>(edn: &Edn) -> Result<T, Error> {
T::deserialize(edn)
Expand Down
3 changes: 2 additions & 1 deletion src/deserialize/parse.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#[cfg(feature = "sets")]
use crate::edn::Set;
use crate::edn::{Edn, Error, List, Map, Vector};
use crate::edn::{Edn, List, Map, Vector};
use crate::EdnError as Error;
use std::collections::BTreeMap;
#[cfg(feature = "sets")]
use std::collections::BTreeSet;
Expand Down
91 changes: 91 additions & 0 deletions src/edn/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
use core::fmt::{self, Debug, Display};

pub struct Error {
code: Code,
// line: usize, // TODO walker
// column: usize, // TODO walker
}

#[non_exhaustive]
pub enum Code {
/// Catchall/placeholder error messages
Message(Box<str>),
Io(std::io::Error),
TryFromInt(std::num::TryFromIntError),
#[doc(hidden)]
Infallable(), // Makes the compiler happy for converting u64 to u64 and i64 to i64
}

impl Error {
pub(crate) fn ParseEdn(owned_string: String) -> Self {
// TODO remove, just so things can compile with less changes
Self {
code: Code::Message(owned_string.into_boxed_str()),
}
}
pub(crate) fn Deserialize(owned_string: String) -> Self {
// TODO remove, just so things can compile with less changes
Self {
code: Code::Message(owned_string.into_boxed_str()),
}
}
pub(crate) fn Iter(owned_string: String) -> Self {
// TODO remove, just so things can compile with less changes
Self {
code: Code::Message(owned_string.into_boxed_str()),
}
}
}

impl Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.code {
Code::Message(m) => write!(f, "{}", m.as_ref()),
_ => todo!(),
}
}
}

impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.code {
Code::Message(m) => write!(f, "{}", m.as_ref()),
Code::TryFromInt(e) => write!(f, "{}", e),
_ => todo!(),
}
}
}

impl From<std::num::ParseIntError> for Error {
fn from(s: std::num::ParseIntError) -> Self {
Self::ParseEdn(s.to_string())
}
}

impl From<std::num::ParseFloatError> for Error {
fn from(s: std::num::ParseFloatError) -> Self {
Self::ParseEdn(s.to_string())
}
}

impl From<std::str::ParseBoolError> for Error {
fn from(s: std::str::ParseBoolError) -> Self {
Self::ParseEdn(s.to_string())
}
}

impl From<std::num::TryFromIntError> for Error {
fn from(e: std::num::TryFromIntError) -> Self {
Self {
code: Code::TryFromInt(e),
}
}
}

impl From<std::convert::Infallible> for Error {
fn from(_: std::convert::Infallible) -> Self {
Self {
code: Code::Infallable(),
}
}
}
60 changes: 2 additions & 58 deletions src/edn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use utils::index::Index;
#[cfg(feature = "sets")]
use ordered_float::OrderedFloat;

pub mod error;
#[doc(hidden)]
pub mod utils;

Expand Down Expand Up @@ -705,7 +706,7 @@ impl Edn {
}

impl std::str::FromStr for Edn {
type Err = Error;
type Err = error::Error;

/// Parses a `&str` that contains an Edn into `Result<Edn, EdnError>`
fn from_str(s: &str) -> Result<Self, Self::Err> {
Expand Down Expand Up @@ -733,63 +734,6 @@ pub(crate) fn rational_to_double(r: &str) -> Option<f64> {
None
}

#[derive(Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum Error {
ParseEdn(String),
Deserialize(String),
Iter(String),
TryFromInt(std::num::TryFromIntError),
#[doc(hidden)]
Infallable(), // Makes the compiler happy for converting u64 to u64 and i64 to i64
}

impl From<String> for Error {
fn from(s: String) -> Self {
Self::ParseEdn(s)
}
}

impl From<std::num::ParseIntError> for Error {
fn from(s: std::num::ParseIntError) -> Self {
Self::ParseEdn(s.to_string())
}
}

impl From<std::num::ParseFloatError> for Error {
fn from(s: std::num::ParseFloatError) -> Self {
Self::ParseEdn(s.to_string())
}
}

impl From<std::str::ParseBoolError> for Error {
fn from(s: std::str::ParseBoolError) -> Self {
Self::ParseEdn(s.to_string())
}
}

impl From<std::num::TryFromIntError> for Error {
fn from(e: std::num::TryFromIntError) -> Self {
Self::TryFromInt(e)
}
}

impl From<std::convert::Infallible> for Error {
fn from(_: std::convert::Infallible) -> Self {
Self::Infallable()
}
}

impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ParseEdn(s) | Self::Deserialize(s) | Self::Iter(s) => write!(f, "{}", &s),
Self::TryFromInt(e) => write!(f, "{e}"),
Self::Infallable() => panic!("Infallable conversion"),
}
}
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ pub fn json_to_edn<'a>(json: impl AsRef<str>) -> Cow<'a, str> {
}

pub use deserialize::{from_edn, from_str, Deserialize};
pub use edn::Error as EdnError;
pub use edn::error::Error as EdnError;
#[cfg(feature = "sets")]
pub use edn::Set;
pub use edn::{Edn, List, Map, Vector};
Expand Down
Loading

0 comments on commit 2cf6966

Please sign in to comment.