diff --git a/Cargo.toml b/Cargo.toml index 4263e08..5060ccb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ number = [] bool = [] vec = [] tuple = [] +low-level = [] [dependencies] @@ -38,4 +39,4 @@ required-features = ["vec", "number"] [[example]] name = "dotenv" -required-features = ["vec", "tuple"] +required-features = ["vec", "tuple", "low-level"] diff --git a/examples/dotenv.rs b/examples/dotenv.rs index 3ce76a0..a13d441 100644 --- a/examples/dotenv.rs +++ b/examples/dotenv.rs @@ -1,12 +1,13 @@ -use estring::{EString, Pair, SepVec}; +use estring::{EString, Pair, SepVec, Trim}; -const DOTENV_CONTENT: &str = "\ +const DOTENV_CONTENT: &str = " DATABASE_URL=postgres://user:password@localhost:5432/recipes -APP_HOST=http://localhost:3000"; +APP_HOST=http://localhost:3000 +"; fn main() -> Result<(), estring::ParseError> { EString::from(DOTENV_CONTENT) - .parse::>()? + .parse::>>()? .iter() .for_each(|p @ Pair(key, value)| { println!("pair: {}", p); diff --git a/src/core.rs b/src/core.rs index 3e2fdac..672038a 100644 --- a/src/core.rs +++ b/src/core.rs @@ -16,6 +16,11 @@ pub mod tuple; #[cfg(feature = "tuple")] pub use tuple::*; +#[cfg(feature = "low-level")] +pub mod low; +#[cfg(feature = "low-level")] +pub use low::*; + use crate::ParseError; use std::convert::{Infallible, TryFrom}; diff --git a/src/core/low.rs b/src/core/low.rs new file mode 100644 index 0000000..609d144 --- /dev/null +++ b/src/core/low.rs @@ -0,0 +1,7 @@ +//! Contains the low-level api parse string more accurate! +//! +//! **NOTE**: Require the enabling the `low-level` feature. +//! + +mod trim; +pub use trim::*; diff --git a/src/core/low/trim.rs b/src/core/low/trim.rs new file mode 100644 index 0000000..b1f2fa8 --- /dev/null +++ b/src/core/low/trim.rs @@ -0,0 +1,78 @@ +use crate::core::EString; +use std::convert::TryFrom; + +//===========================================================================// +// TRIM // +//===========================================================================// + +/// Wrapper that allow to trim substring before continue +/// +/// **NOTE**: Required the enabling of the `low-level` feature. +/// +/// # Examples +/// +/// ```rust +/// use estring::{EString, Trim}; +/// +/// fn main() -> Result<(), estring::ParseError> { +/// let res = EString::from(" 99 ").parse::>()?; +/// assert_eq!(res, Trim(99)); +/// Ok(()) +/// } +/// ``` +/// +#[derive(Debug, PartialEq, Eq)] +pub struct Trim(pub T); + +impl std::ops::Deref for Trim { + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl std::fmt::Display for Trim { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl TryFrom for Trim +where + T: TryFrom, +{ + type Error = (); + + fn try_from(value: EString) -> Result { + T::try_from(EString::from(value.trim())) + .map(Trim) + .map_err(|_| ()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn should_trim_string() { + let estr = EString::from(" 999 "); + + match estr.parse::>() { + Ok(res) => assert_eq!(*res, "999"), + _ => unreachable!(), + } + } + + #[cfg(feature = "number")] + #[test] + fn should_trim_and_convert_to_number() { + let estr = EString::from(" 999 "); + + match estr.parse::>() { + Ok(res) => assert_eq!(*res, 999), + _ => unreachable!(), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index c274322..d5bc9b4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,7 @@ //! #![deny(clippy::pedantic)] #![allow(clippy::module_name_repetitions)] -#![deny(missing_docs)] +#![warn(missing_docs)] pub mod core; mod error;