From c099d860bd5d1c4e63ba86c9ff6e34a9e6ab3f2a Mon Sep 17 00:00:00 2001 From: Dmitriy Pleshevskiy Date: Sun, 24 Jul 2022 02:18:44 +0300 Subject: [PATCH] core/tuple: add support for pair tuple --- Cargo.toml | 1 + src/core.rs | 5 ++ src/core/tuple.rs | 132 ++++++++++++++++++++++++++++++++++++++++++++++ src/core/vec.rs | 2 - src/lib.rs | 9 ---- 5 files changed, 138 insertions(+), 11 deletions(-) create mode 100644 src/core/tuple.rs diff --git a/Cargo.toml b/Cargo.toml index 3713155..93c00b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ prim = ["number", "bool"] number = [] bool = [] vec = [] +tuple = [] [dependencies] diff --git a/src/core.rs b/src/core.rs index 68a2151..3e2fdac 100644 --- a/src/core.rs +++ b/src/core.rs @@ -11,6 +11,11 @@ pub mod vec; #[cfg(feature = "vec")] pub use vec::*; +#[cfg(feature = "tuple")] +pub mod tuple; +#[cfg(feature = "tuple")] +pub use tuple::*; + use crate::ParseError; use std::convert::{Infallible, TryFrom}; diff --git a/src/core/tuple.rs b/src/core/tuple.rs new file mode 100644 index 0000000..0e993b5 --- /dev/null +++ b/src/core/tuple.rs @@ -0,0 +1,132 @@ +//! Contains the implementations to tuple type +//! +//! **NOTE**: Require the enabling of the `tuple` features +//! + +use crate::core::EString; +use std::convert::TryFrom; +use std::fmt::Write; + +/// The error type for operations interacting with parsing tuples. Possibly returned from +/// ``EString::parse`` +#[derive(Debug)] +pub enum Error { + /// The specified input string is not split. + Split, + + /// The specified substring of the split input string is not parsed + Parse(u8), +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Error::Split => f.write_str("Cannot split input string"), + Error::Parse(n) => write!(f, "Cannot parse {} substring", n), + } + } +} + +impl std::error::Error for Error {} + +/// Wrapper for pair (A, B) tuple to split string by a separator (`S1`). +/// +/// **NOTE**: Required the enabling of the `tuple` feature. +/// +/// # Examples +/// +/// ```rust +/// use estring::{Pair, EString}; +/// +/// type EqPair = Pair) -> std::fmt::Result { + f.write_str(&self.0.to_string())?; + f.write_char(S1)?; + f.write_str(&self.1.to_string()) + } +} + +impl TryFrom for Pair +where + A: TryFrom, + B: TryFrom, +{ + type Error = Error; + + fn try_from(value: EString) -> Result { + value.split_once(S1).ok_or(Error::Split).and_then(|(a, b)| { + let a = A::try_from(EString::from(a)).map_err(|_| Error::Parse(0))?; + let b = B::try_from(EString::from(b)).map_err(|_| Error::Parse(1))?; + Ok(Self(a, b)) + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + type EqPair = Pair; + + #[test] + fn should_parse_vec_of_pairs() { + let estr = EString::from( + "foo=bar +hello=bar", + ); + match estr.parse::>>() { + Ok(res) => assert_eq!(res, SepVec(vec![Pair("foo", "bar"), Pair("hello", "bar"),])), + _ => unreachable!(), + }; + } + } +} diff --git a/src/core/vec.rs b/src/core/vec.rs index c59d45c..3077379 100644 --- a/src/core/vec.rs +++ b/src/core/vec.rs @@ -21,10 +21,8 @@ use std::fmt::Write; /// fn main() -> Result<(), estring::ParseError> { /// let res = EString::from("1,2,3").parse::>()?; /// assert_eq!(*res, vec![1, 2, 3]); -/// /// Ok(()) /// } -/// /// ``` /// #[derive(Debug, PartialEq, Clone)] diff --git a/src/lib.rs b/src/lib.rs index ef409a0..3d57f5d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,12 +36,3 @@ mod error; pub use crate::core::*; pub use crate::error::ParseError; - -#[cfg(test)] -mod tests { - #[test] - fn it_works() { - let result = 2 + 2; - assert_eq!(result, 4); - } -}