diff --git a/src/env.rs b/src/env/mod.rs similarity index 55% rename from src/env.rs rename to src/env/mod.rs index 4580661..e917aa3 100644 --- a/src/env.rs +++ b/src/env/mod.rs @@ -5,6 +5,9 @@ use std::fmt; use serde::de::IntoDeserializer; +pub mod parse; + + /// Error type only for deserialization of env values. /// /// Semantically private, only public as it's used in the API of the `internal` @@ -132,97 +135,4 @@ impl<'de> serde::Deserializer<'de> for Deserializer { #[cfg(test)] -mod tests { - use super::*; - - fn de<'de, T: serde::Deserialize<'de>>(v: &'static str) -> Result { - T::deserialize(Deserializer { value: v.into() }) - } - - - #[test] - fn boolean() { - assert_eq!(de("1"), Ok(true)); - assert_eq!(de("true "), Ok(true)); - assert_eq!(de(" TRUE"), Ok(true)); - assert_eq!(de("0 "), Ok(false)); - assert_eq!(de(" false"), Ok(false)); - assert_eq!(de("FALSE "), Ok(false)); - } - - #[test] - fn ints() { - assert_eq!(de("0"), Ok(0u8)); - assert_eq!(de("-1 "), Ok(-1i8)); - assert_eq!(de(" 27"), Ok(27u16)); - assert_eq!(de("-27"), Ok(-27i16)); - assert_eq!(de(" 4301"), Ok(4301u32)); - assert_eq!(de(" -123456"), Ok(-123456i32)); - assert_eq!(de(" 986543210 "), Ok(986543210u64)); - assert_eq!(de("-986543210"), Ok(-986543210i64)); - } - - #[test] - fn floats() { - assert_eq!(de("3.1415"), Ok(3.1415f32)); - assert_eq!(de("-123.456"), Ok(-123.456f64)); - } -} - -/// Functions for the `#[config(parse_env = ...)]` attribute. -pub mod parse { - use std::str::FromStr; - - /// Splits the environment variable by separator `SEP`, parses each element - /// with [`FromStr`] and collects everything via [`FromIterator`]. - /// - /// To avoid having to specify the separator via `::<>` syntax, see the - /// other functions in this module. - /// - /// [`FromStr`]: std::str::FromStr - /// [`FromIterator`]: std::iter::FromIterator - /// - /// - /// # Example - /// - /// ``` - /// use confique::Config; - /// - /// #[derive(Debug, confique::Config)] - /// struct Conf { - /// #[config(env = "PORTS", parse_env = confique::env::parse::list_by_sep::<',', _, _>)] - /// ports: Vec, - /// } - /// - /// std::env::set_var("PORTS", "8080,8000,8888"); - /// let conf = Conf::builder().env().load()?; - /// assert_eq!(conf.ports, vec![8080, 8000, 8888]); - /// # Ok::<_, confique::Error>(()) - /// ``` - pub fn list_by_sep(input: &str) -> Result::Err> - where - T: FromStr, - C: FromIterator, - { - input.split(SEP).map(T::from_str).collect() - } - - - macro_rules! specify_fn_wrapper { - ($fn_name:ident, $sep:literal) => { - #[doc = concat!("Like [`list_by_sep`] with `", $sep, "` separator.")] - pub fn $fn_name(input: &str) -> Result::Err> - where - T: FromStr, - C: FromIterator, - { - list_by_sep::<$sep, _, _>(input) - } - } - } - - specify_fn_wrapper!(list_by_comma, ','); - specify_fn_wrapper!(list_by_semicolon, ';'); - specify_fn_wrapper!(list_by_colon, ':'); - specify_fn_wrapper!(list_by_space, ' '); -} +mod tests; diff --git a/src/env/parse.rs b/src/env/parse.rs new file mode 100644 index 0000000..aa81359 --- /dev/null +++ b/src/env/parse.rs @@ -0,0 +1,56 @@ +//! Functions for the `#[config(parse_env = ...)]` attribute. + +use std::str::FromStr; + +/// Splits the environment variable by separator `SEP`, parses each element +/// with [`FromStr`] and collects everything via [`FromIterator`]. +/// +/// To avoid having to specify the separator via `::<>` syntax, see the +/// other functions in this module. +/// +/// [`FromStr`]: std::str::FromStr +/// [`FromIterator`]: std::iter::FromIterator +/// +/// +/// # Example +/// +/// ``` +/// use confique::Config; +/// +/// #[derive(Debug, confique::Config)] +/// struct Conf { +/// #[config(env = "PORTS", parse_env = confique::env::parse::list_by_sep::<',', _, _>)] +/// ports: Vec, +/// } +/// +/// std::env::set_var("PORTS", "8080,8000,8888"); +/// let conf = Conf::builder().env().load()?; +/// assert_eq!(conf.ports, vec![8080, 8000, 8888]); +/// # Ok::<_, confique::Error>(()) +/// ``` +pub fn list_by_sep(input: &str) -> Result::Err> +where + T: FromStr, + C: FromIterator, +{ + input.split(SEP).map(T::from_str).collect() +} + + +macro_rules! specify_fn_wrapper { + ($fn_name:ident, $sep:literal) => { + #[doc = concat!("Like [`list_by_sep`] with `", $sep, "` separator.")] + pub fn $fn_name(input: &str) -> Result::Err> + where + T: FromStr, + C: FromIterator, + { + list_by_sep::<$sep, _, _>(input) + } + } +} + +specify_fn_wrapper!(list_by_comma, ','); +specify_fn_wrapper!(list_by_semicolon, ';'); +specify_fn_wrapper!(list_by_colon, ':'); +specify_fn_wrapper!(list_by_space, ' '); diff --git a/src/env/tests.rs b/src/env/tests.rs new file mode 100644 index 0000000..7fdeb3e --- /dev/null +++ b/src/env/tests.rs @@ -0,0 +1,34 @@ +use super::*; + +fn de<'de, T: serde::Deserialize<'de>>(v: &'static str) -> Result { + T::deserialize(Deserializer { value: v.into() }) +} + + +#[test] +fn boolean() { + assert_eq!(de("1"), Ok(true)); + assert_eq!(de("true "), Ok(true)); + assert_eq!(de(" TRUE"), Ok(true)); + assert_eq!(de("0 "), Ok(false)); + assert_eq!(de(" false"), Ok(false)); + assert_eq!(de("FALSE "), Ok(false)); +} + +#[test] +fn ints() { + assert_eq!(de("0"), Ok(0u8)); + assert_eq!(de("-1 "), Ok(-1i8)); + assert_eq!(de(" 27"), Ok(27u16)); + assert_eq!(de("-27"), Ok(-27i16)); + assert_eq!(de(" 4301"), Ok(4301u32)); + assert_eq!(de(" -123456"), Ok(-123456i32)); + assert_eq!(de(" 986543210 "), Ok(986543210u64)); + assert_eq!(de("-986543210"), Ok(-986543210i64)); +} + +#[test] +fn floats() { + assert_eq!(de("3.1415"), Ok(3.1415f32)); + assert_eq!(de("-123.456"), Ok(-123.456f64)); +}