deps: bump estring to v0.2.0

Closes #35
This commit is contained in:
Dmitriy Pleshevskiy 2022-07-27 18:42:49 +03:00
parent 930e33a138
commit bbbf355fc0
7 changed files with 148 additions and 155 deletions

4
Cargo.lock generated
View file

@ -11,6 +11,6 @@ dependencies = [
[[package]] [[package]]
name = "estring" name = "estring"
version = "0.1.2" version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72ea7e904ef7cb950eee02f9332b6a5c24c33bebeca6c027651b04f6c20658d9" checksum = "515fc26a9876dfa25822d8cc040c6e4497ff9f5be96f101ee136d6ece160d2cc"

View file

@ -5,12 +5,10 @@ authors = ["Dmitriy Pleshevskiy <dmitriy@ideascup.me>"]
description = "it helps you work with environment variables and convert it to any type using only type annotations" description = "it helps you work with environment variables and convert it to any type using only type annotations"
categories = ["config"] categories = ["config"]
keywords = ["env", "environment"] keywords = ["env", "environment"]
edition = "2018" edition = "2021"
license = "MIT" license = "MIT"
repository = "https://github.com/pleshevskiy/enve" repository = "https://github.com/pleshevskiy/enve"
rust-version = "1.59.0"
[package.metadata]
msrv = "1.51.0"
# https://docs.rs/about # https://docs.rs/about
[package.metadata.docs.rs] [package.metadata.docs.rs]
@ -20,17 +18,21 @@ all-features = true
[features] [features]
default = [] default = []
number = ["estring/number"] low-level = ["estring/low-level"]
bool = ["estring/bool"] structs = ["estring/structs"]
vec = ["estring/vec"]
# deprecated
number = []
bool = []
vec = ["structs"]
[dependencies] [dependencies]
estring = "0.1" estring = "0.2"
[badges] [badges]
maintenance = { status = "actively-developed" } maintenance = { status = "actively-developed" }
[[example]] [[example]]
name = "calc" name = "calc"
required-features = ["number", "vec"] required-features = ["structs"]

View file

@ -1,6 +1,5 @@
use crate::error::Error; use crate::error::Error;
use estring::EString; use estring::{EString, ParseFragment, ToEString};
use std::convert::TryFrom;
/// Fetches the environment variable `key` from the current process. It set value `default` /// Fetches the environment variable `key` from the current process. It set value `default`
/// if environment variable `key` ins'n set. Then this function tries to parse ``EString`` to /// if environment variable `key` ins'n set. Then this function tries to parse ``EString`` to
@ -28,10 +27,10 @@ use std::convert::TryFrom;
#[allow(clippy::needless_pass_by_value)] #[allow(clippy::needless_pass_by_value)]
pub fn get_or_set_default<R>(env_name: &str, default: R) -> Result<R, Error> pub fn get_or_set_default<R>(env_name: &str, default: R) -> Result<R, Error>
where where
R: TryFrom<EString> + std::fmt::Display, R: ParseFragment + ToEString,
{ {
get::<R>(env_name).or_else(|err| match err { get::<R>(env_name).or_else(|err| match err {
Error::NotPresent => sset(env_name, &default).parse().map_err(Error::from), Error::NotPresent => sset(env_name, default).parse().map_err(Error::from),
_ => Err(err), _ => Err(err),
}) })
} }
@ -63,7 +62,7 @@ where
/// ``` /// ```
pub fn get<R>(key: &str) -> Result<R, Error> pub fn get<R>(key: &str) -> Result<R, Error>
where where
R: TryFrom<EString>, R: ParseFragment,
{ {
sget(key).and_then(|v| v.parse().map_err(Error::from)) sget(key).and_then(|v| v.parse().map_err(Error::from))
} }
@ -108,18 +107,20 @@ pub fn sget(key: &str) -> Result<EString, Error> {
/// let estr = enve::sset("KEY", "10"); /// let estr = enve::sset("KEY", "10");
/// assert_eq!(estr.to_string(), String::from("10")); /// assert_eq!(estr.to_string(), String::from("10"));
/// ``` /// ```
#[allow(clippy::needless_pass_by_value)]
pub fn sset<V>(key: &str, value: V) -> EString pub fn sset<V>(key: &str, value: V) -> EString
where where
V: std::fmt::Display, V: ToEString,
{ {
let val = value.to_string(); let es = value.to_estring();
std::env::set_var(key, &val); std::env::set_var(key, &*es);
val.into() es
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::estr::{CommaVec, SemiVec, SepVec};
struct TestCase<const N: u8>; struct TestCase<const N: u8>;
@ -171,150 +172,134 @@ mod tests {
}; };
} }
#[cfg(feature = "number")] #[test]
mod numbers { fn should_return_parsed_num() {
use super::*; let en = TestCase::<4>.to_string();
std::env::set_var(&en, "-10");
#[test] match get::<i32>(&en) {
fn should_return_parsed_num() { Ok(res) => assert_eq!(res, -10),
let en = TestCase::<4>.to_string(); _ => unreachable!(),
std::env::set_var(&en, "-10"); };
match get::<i32>(&en) {
Ok(res) => assert_eq!(res, -10),
_ => unreachable!(),
};
}
#[test]
fn should_throw_parse_error() {
let en = TestCase::<5>.to_string();
std::env::set_var(&en, "-10");
match get::<u32>(&en) {
Err(Error::Parse(orig)) => {
assert_eq!(orig, String::from("-10"));
}
_ => unreachable!(),
};
}
#[test]
fn should_set_default_num_if_var_is_no_present() {
let en = TestCase::<6>.to_string();
let orig = 10;
match get_or_set_default(&en, orig) {
Ok(res) => {
assert_eq!(res, orig);
assert_eq!(std::env::var(&en).unwrap(), "10");
}
_ => unreachable!(),
};
}
} }
#[cfg(feature = "bool")] #[test]
mod boolean { fn should_throw_parse_error() {
use super::*; let en = TestCase::<5>.to_string();
std::env::set_var(&en, "-10");
#[test] match get::<u32>(&en) {
fn should_parse_bool_variable() { Err(Error::Parse(orig)) => {
let en = TestCase::<7>.to_string(); assert_eq!(orig, EString::from("-10"));
let test_cases = [
("1", true),
("y", true),
("yes", true),
("true", true),
("t", true),
("on", true),
("false", false),
("f", false),
("0", false),
];
for (val, expected) in &test_cases {
let mut en = en.clone();
en.push_str(val.as_ref());
std::env::set_var(&en, val);
match get::<bool>(&en) {
Ok(res) => assert_eq!(res, *expected),
_ => unreachable!(),
};
} }
} _ => unreachable!(),
};
} }
#[cfg(feature = "vec")] #[test]
mod vector { fn should_set_default_num_if_var_is_no_present() {
use super::*; let en = TestCase::<6>.to_string();
use crate::estr::{CommaVec, SemiVec, SepVec}; let orig = 10;
match get_or_set_default(&en, orig) {
Ok(res) => {
assert_eq!(res, orig);
assert_eq!(std::env::var(&en).unwrap(), "10");
}
_ => unreachable!(),
};
}
#[test] #[test]
fn should_return_var_as_vector() { fn should_parse_bool_variable() {
let en = TestCase::<8>.to_string(); let en = TestCase::<7>.to_string();
std::env::set_var(&en, "1,2,3,4,5"); let test_cases = [
match get::<CommaVec<i32>>(&en) { ("1", true),
Ok(res) => assert_eq!(*res, vec![1, 2, 3, 4, 5]), ("y", true),
("yes", true),
("true", true),
("t", true),
("on", true),
("false", false),
("f", false),
("0", false),
];
for (val, expected) in test_cases {
let mut en = en.clone();
en.push_str(val.as_ref());
std::env::set_var(&en, val);
match get::<bool>(&en) {
Ok(res) => assert_eq!(res, expected),
_ => unreachable!(), _ => unreachable!(),
}; };
} }
}
#[test] #[test]
fn should_trim_identations_before_parsing() { fn should_return_var_as_vector() {
let en = TestCase::<9>.to_string(); let en = TestCase::<8>.to_string();
let input = " std::env::set_var(&en, "1,2,3,4,5");
match get::<CommaVec<i32>>(&en) {
Ok(res) => assert_eq!(*res, vec![1, 2, 3, 4, 5]),
_ => unreachable!(),
};
}
#[test]
fn should_trim_identations_before_parsing() {
let en = TestCase::<9>.to_string();
let input = "
1 , 2, 3, 1 , 2, 3,
4,5"; 4,5";
std::env::set_var(&en, input); std::env::set_var(&en, input);
match get::<CommaVec<i32>>(&en) { match get::<CommaVec<i32>>(&en) {
Ok(res) => assert_eq!(*res, vec![1, 2, 3, 4, 5]), Ok(res) => assert_eq!(*res, vec![1, 2, 3, 4, 5]),
_ => unreachable!(), _ => unreachable!(),
}; };
} }
#[test] #[test]
fn should_return_vector_of_vectors() { fn should_return_vector_of_vectors() {
let en = TestCase::<10>.to_string(); let en = TestCase::<10>.to_string();
std::env::set_var(&en, "1,2; 3,4,5; 6,7"); std::env::set_var(&en, "1,2; 3,4,5; 6,7");
match get::<SemiVec<CommaVec<i32>>>(&en) { match get::<SemiVec<CommaVec<i32>>>(&en) {
Ok(res) => assert_eq!( Ok(res) => assert_eq!(
res, res,
SemiVec::from(vec![ SemiVec::from(vec![
CommaVec::from(vec![1, 2]), CommaVec::from(vec![1, 2]),
CommaVec::from(vec![3, 4, 5]), CommaVec::from(vec![3, 4, 5]),
CommaVec::from(vec![6, 7]) CommaVec::from(vec![6, 7])
]) ])
), ),
_ => unreachable!(), _ => unreachable!(),
}; };
} }
#[test] #[test]
fn should_throw_parse_vec_error() { fn should_throw_parse_vec_error() {
let en = TestCase::<11>.to_string(); let en = TestCase::<11>.to_string();
std::env::set_var(&en, "1,2,3,4,5"); std::env::set_var(&en, "1,2,3,4,5");
match get::<SepVec<i32, '+'>>(&en) { match get::<SepVec<i32, '+'>>(&en) {
Err(Error::Parse(orig)) => { Err(Error::Parse(orig)) => {
assert_eq!(orig, String::from("1,2,3,4,5")); assert_eq!(orig, EString::from("1,2,3,4,5"));
} }
_ => unreachable!(), _ => unreachable!(),
}; };
} }
#[test] #[test]
fn should_set_default_vector_if_var_is_no_present() { fn should_set_default_vector_if_var_is_no_present() {
let en = TestCase::<12>.to_string(); let en = TestCase::<12>.to_string();
let orig = CommaVec::from(vec![1, 2, 3, 4]); let orig = CommaVec::from(vec![1, 2, 3, 4]);
match get_or_set_default(&en, orig.clone()) { match get_or_set_default(&en, orig.clone()) {
Ok(res) => { Ok(res) => {
assert_eq!(res, orig); assert_eq!(res, orig);
assert_eq!(std::env::var(&en).unwrap(), "1,2,3,4"); assert_eq!(std::env::var(&en).unwrap(), "1,2,3,4");
} }
_ => unreachable!(), _ => unreachable!(),
}; };
}
} }
} }

View file

@ -3,6 +3,8 @@ use std::error;
use std::ffi::OsString; use std::ffi::OsString;
use std::fmt; use std::fmt;
use estring::EString;
/// The error type for operations interacting with environment variables /// The error type for operations interacting with environment variables
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
@ -10,7 +12,7 @@ pub enum Error {
NotPresent, NotPresent,
/// Failed to parse the specified environment variable. /// Failed to parse the specified environment variable.
Parse(String), Parse(EString),
/// The specified environment variable was found, but it did not contain /// The specified environment variable was found, but it did not contain
/// valid unicode data. The found data is returned as a payload of this /// valid unicode data. The found data is returned as a payload of this
@ -45,8 +47,8 @@ impl From<VarError> for Error {
} }
} }
impl From<estring::ParseError> for Error { impl From<estring::Error> for Error {
fn from(err: estring::ParseError) -> Self { fn from(err: estring::Error) -> Self {
Error::Parse(err.clone()) Error::Parse(err.0)
} }
} }

View file

@ -1,6 +1,8 @@
#[cfg(feature = "vec")] #[cfg(feature = "structs")]
mod vec; mod structs;
#[cfg(feature = "vec")] #[cfg(feature = "structs")]
pub use vec::{CommaVec, SemiVec}; pub use structs::{CommaVec, SemiVec};
pub use estring::core::*; pub use estring::core::EString;
pub use estring::low::*;
pub use estring::structs::*;

View file

@ -62,3 +62,5 @@ mod estr;
pub use crate::core::{get, get_or_set_default, sget, sset}; pub use crate::core::{get, get_or_set_default, sget, sset};
pub use error::Error; pub use error::Error;
pub use estr::*; pub use estr::*;
pub use estring;