diff --git a/maraiah/cenum.rs b/maraiah/cenum.rs index 120d624..f3426a6 100644 --- a/maraiah/cenum.rs +++ b/maraiah/cenum.rs @@ -26,9 +26,9 @@ /// assert_eq!(MyEnum::try_from(0), Ok(MyEnum::Zero)); /// assert_eq!(MyEnum::try_from(1), Ok(MyEnum::One)); /// assert_eq!(MyEnum::try_from(2), Ok(MyEnum::Two)); -/// assert_eq!(MyEnum::try_from(3), Err(ReprError::new(3))); -/// assert_eq!(MyEnum::try_from(4), Err(ReprError::new(4))); -/// assert_eq!(MyEnum::try_from(5), Err(ReprError::new(5))); +/// assert_eq!(MyEnum::try_from(3), Err(ReprError::new("MyEnum", 3))); +/// assert_eq!(MyEnum::try_from(4), Err(ReprError::new("MyEnum", 4))); +/// assert_eq!(MyEnum::try_from(5), Err(ReprError::new("MyEnum", 5))); /// ``` #[macro_export] macro_rules! c_enum @@ -61,14 +61,28 @@ macro_rules! c_enum } } } + + #[allow(unused_qualifications)] + impl std::str::FromStr for $t + { + type Err = $crate::err::ParseEnumError; + + fn from_str(s: &str) -> Result + { + match s { + $(stringify!($en) => Ok($t::$en),)+ + _ => Err(Self::Err::new(stringify!($t))) + } + } + } }; } #[cfg(test)] mod test { - use crate::err::ReprError; - use std::convert::TryFrom; + use crate::err::{ParseEnumError, ReprError}; + use std::{convert::TryFrom, str::FromStr}; c_enum! { enum TestEnum: u16 { @@ -79,19 +93,20 @@ mod test } #[test] - fn c_enum_should_be_ok() + fn c_enum() { assert_eq!(TestEnum::try_from(0), Ok(TestEnum::Zero)); assert_eq!(TestEnum::try_from(1), Ok(TestEnum::One)); assert_eq!(TestEnum::try_from(2), Ok(TestEnum::Two)); - assert_eq!(TestEnum::try_from(3), Err(ReprError::new(3))); - assert_eq!(TestEnum::try_from(4), Err(ReprError::new(4))); - assert_eq!(TestEnum::try_from(5), Err(ReprError::new(5))); + assert_eq!(TestEnum::try_from(3), Err(ReprError::new("TestEnum", 3))); + assert_eq!(TestEnum::try_from(4), Err(ReprError::new("TestEnum", 4))); + assert_eq!(TestEnum::try_from(5), Err(ReprError::new("TestEnum", 5))); + assert_eq!(TestEnum::from_str("Zero"), Ok(TestEnum::Zero)); + assert_eq!(TestEnum::from_str("One"), Ok(TestEnum::One)); + assert_eq!(TestEnum::from_str("Two"), Ok(TestEnum::Two)); + assert_eq!(TestEnum::from_str("Three"), + Err(ParseEnumError::new("TestEnum"))); } - - #[test] - #[should_panic] - fn c_enum_should_error() {TestEnum::try_from(3).unwrap();} } // EOF diff --git a/maraiah/err.rs b/maraiah/err.rs index 9a7ae20..8dd9fe6 100644 --- a/maraiah/err.rs +++ b/maraiah/err.rs @@ -53,6 +53,24 @@ macro_rules! backtrace { /// ``` pub fn err_msg(msg: &'static str) -> Error {ErrMsg(msg).into()} +impl ParseEnumError +{ + /// Returns an `Error` with a message for enumeration parsing errata. + /// + /// # Examples + /// + /// ``` + /// use maraiah::err::ParseEnumError; + /// + /// assert_eq!(format!("{}", ParseEnumError::new("TypeName")), + /// "could not parse TypeName"); + /// ``` + pub fn new(t: &'static str) -> Self + { + Self(t) + } +} + impl ReprError { /// Returns an `Error` with a message for representation errata. @@ -60,9 +78,9 @@ impl ReprError /// # Examples /// /// ``` - /// use maraiah::err::repr_error; + /// use maraiah::err::ReprError; /// - /// assert_eq!(format!("{}", repr_error("TypeName", 77)), + /// assert_eq!(format!("{}", ReprError::new("TypeName", 77)), /// "bad TypeName (77)"); /// ``` pub fn new>(t: &'static str, n: T) -> Self @@ -71,8 +89,17 @@ impl ReprError } } -impl Fail for ReprError {} impl Fail for ErrMsg {} +impl Fail for ParseEnumError {} +impl Fail for ReprError {} + +impl fmt::Display for ParseEnumError +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result + { + write!(f, "could not parse {}", self.0) + } +} impl fmt::Display for ReprError { @@ -90,13 +117,17 @@ impl fmt::Display for ErrMsg } } -/// A representation error for an integer. -#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)] -pub struct ReprError(&'static str, i64); - -#[derive(Debug)] +#[derive(Clone, Debug)] struct ErrMsg(&'static str); +/// A parser error for an enumeration. +#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct ParseEnumError(&'static str); + +/// A representation error for an integer. +#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] +pub struct ReprError(&'static str, i64); + /// A generic `failure` based `Result` type. pub type ResultS = Result;