Compare commits
2 commits
main
...
low-level-
Author | SHA1 | Date | |
---|---|---|---|
4a74324ff2 | |||
d036fd2d90 |
7 changed files with 100 additions and 8 deletions
|
@ -26,6 +26,7 @@ number = []
|
||||||
bool = []
|
bool = []
|
||||||
vec = []
|
vec = []
|
||||||
tuple = []
|
tuple = []
|
||||||
|
low-level = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|
||||||
|
@ -38,4 +39,4 @@ required-features = ["vec", "number"]
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
name = "dotenv"
|
name = "dotenv"
|
||||||
required-features = ["vec", "tuple"]
|
required-features = ["vec", "tuple", "low-level"]
|
||||||
|
|
|
@ -10,7 +10,7 @@ A simple way to parse a string using type annotations.
|
||||||
|
|
||||||
This package was originally designed for [enve]
|
This package was originally designed for [enve]
|
||||||
|
|
||||||
[enve]: https://github.com/pleshevskiy/itconfig-rs/tree/redesign
|
[enve]: https://github.com/pleshevskiy/enve
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
|
|
|
@ -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
|
DATABASE_URL=postgres://user:password@localhost:5432/recipes
|
||||||
APP_HOST=http://localhost:3000";
|
APP_HOST=http://localhost:3000
|
||||||
|
";
|
||||||
|
|
||||||
fn main() -> Result<(), estring::ParseError> {
|
fn main() -> Result<(), estring::ParseError> {
|
||||||
EString::from(DOTENV_CONTENT)
|
EString::from(DOTENV_CONTENT)
|
||||||
.parse::<SepVec<Pair<&str, '=', &str>, '\n'>>()?
|
.parse::<Trim<SepVec<Pair<&str, '=', &str>, '\n'>>>()?
|
||||||
.iter()
|
.iter()
|
||||||
.for_each(|p @ Pair(key, value)| {
|
.for_each(|p @ Pair(key, value)| {
|
||||||
println!("pair: {}", p);
|
println!("pair: {}", p);
|
||||||
|
|
|
@ -16,6 +16,11 @@ pub mod tuple;
|
||||||
#[cfg(feature = "tuple")]
|
#[cfg(feature = "tuple")]
|
||||||
pub use tuple::*;
|
pub use tuple::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "low-level")]
|
||||||
|
pub mod low;
|
||||||
|
#[cfg(feature = "low-level")]
|
||||||
|
pub use low::*;
|
||||||
|
|
||||||
use crate::ParseError;
|
use crate::ParseError;
|
||||||
use std::convert::{Infallible, TryFrom};
|
use std::convert::{Infallible, TryFrom};
|
||||||
|
|
||||||
|
|
7
src/core/low.rs
Normal file
7
src/core/low.rs
Normal file
|
@ -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::*;
|
78
src/core/low/trim.rs
Normal file
78
src/core/low/trim.rs
Normal file
|
@ -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::<Trim<i32>>()?;
|
||||||
|
/// assert_eq!(res, Trim(99));
|
||||||
|
/// Ok(())
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct Trim<T>(pub T);
|
||||||
|
|
||||||
|
impl<T> std::ops::Deref for Trim<T> {
|
||||||
|
type Target = T;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: std::fmt::Display> std::fmt::Display for Trim<T> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> TryFrom<EString> for Trim<T>
|
||||||
|
where
|
||||||
|
T: TryFrom<EString>,
|
||||||
|
{
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(value: EString) -> Result<Self, Self::Error> {
|
||||||
|
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::<Trim<&str>>() {
|
||||||
|
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::<Trim<i32>>() {
|
||||||
|
Ok(res) => assert_eq!(*res, 999),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
//!
|
//!
|
||||||
//! This package was originally designed for [enve]
|
//! This package was originally designed for [enve]
|
||||||
//!
|
//!
|
||||||
//! [enve]: https://github.com/pleshevskiy/itconfig-rs/tree/redesign
|
//! [enve]: https://github.com/pleshevskiy/enve
|
||||||
//!
|
//!
|
||||||
//! ## Getting started
|
//! ## Getting started
|
||||||
//!
|
//!
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
//!
|
//!
|
||||||
#![deny(clippy::pedantic)]
|
#![deny(clippy::pedantic)]
|
||||||
#![allow(clippy::module_name_repetitions)]
|
#![allow(clippy::module_name_repetitions)]
|
||||||
#![deny(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
pub mod core;
|
pub mod core;
|
||||||
mod error;
|
mod error;
|
||||||
|
|
Reference in a new issue