diff --git a/README.md b/README.md index 4a2ee26..a3ef219 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,6 @@ cargo test --all-features * **default** - ["primitives"] * **macro** - Activates `config!` macros for easy configure web application. -* **array** - Add EnvString impl for vector type (uses optional `serde_json` package). * **primitives** - Group for features: `numbers` and `bool`. * **numbers** - Group for features: `int`, `uint` and `float`. * **int** - Group for features: `i8`, `i16`, `i32`, `i64`, `i128` and `isize`. @@ -149,6 +148,7 @@ cargo test --all-features * **f32** - impl EnvString for `f32` type * **f64** - impl EnvString for `f64` type * **bool** - impl EnvString for `bool` type +* **json_array** - Add EnvString impl for vector type (uses optional `serde_json` package). ⚠ **_DEPRECATED_** ## License diff --git a/itconfig/Cargo.toml b/itconfig/Cargo.toml index c327ec2..15d80d3 100644 --- a/itconfig/Cargo.toml +++ b/itconfig/Cargo.toml @@ -26,8 +26,6 @@ default = ["primitives"] macro = ["itconfig-macro"] -array = ["serde_json"] - primitives = ["numbers", "bool"] numbers = ["int", "uint", "float"] int = ["i8", "i16", "i32", "i64", "i128", "isize"] @@ -53,6 +51,9 @@ f64 = [] bool = [] +# deprecated since 1.1 +json_array = ["serde_json"] + [badges] travis-ci = { repository = "icetemple/itconfig-rs" } diff --git a/itconfig/src/envstr.rs b/itconfig/src/envstr.rs index 7bed80a..efc7838 100644 --- a/itconfig/src/envstr.rs +++ b/itconfig/src/envstr.rs @@ -1,20 +1,71 @@ use std::ops::Deref; -#[doc(hidden)] +/// Wrapper under String type. +/// +/// When we read the environment variable, we automatically convert the value +/// to EnvString and then convert it to your expected type. +/// +#[derive(Debug, PartialEq, Clone)] +pub struct EnvString(String); + +impl From for EnvString +where + T: ToEnvString, +{ + fn from(val: T) -> Self { + val.to_env_string() + } +} + +impl Deref for EnvString { + type Target = String; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +/// A trait for converting value to EnvString. +/// +/// This trait automatically implemented for any type which implements the +/// [`Display`] trait. As such, `ToEnvString` shouldn't be implemented directly: +/// [`Display`] should be implemented instead, and you get the `ToEnvString` +/// implementation for free. +/// +/// [`Display`]: std::fmt::Display pub trait ToEnvString { + /// Converts the giving value to a `EnvString`. + /// + /// # Examples + /// + /// basic usage + /// + /// ```rust + /// # use itconfig::{EnvString, ToEnvString}; + /// let i = 5; + /// let five = EnvString::from("5"); + /// assert_eq!(five, i.to_env_string()); + /// ``` fn to_env_string(&self) -> EnvString; } -#[doc(hidden)] +/// Simple and safe type conversions that may fail in a controlled way under +/// some circumstances. +/// +/// This trait automatically implemented for all standard primitives. If you +/// want to use your custom type in the library you need to implement +/// `ToEnvString` and `FromEnvString` manually. pub trait FromEnvString: Sized { + /// The type returned in the event of a conversion error. type Err; + /// Performs the conversion. fn from_env_string(s: &EnvString) -> Result; } impl ToEnvString for T where - T: ToString, + T: std::fmt::Display, { #[inline] fn to_env_string(&self) -> EnvString { @@ -68,37 +119,6 @@ impl FromEnvString for bool { } } -#[cfg(feature = "array")] -#[derive(Debug)] -pub enum ArrayEnvError { - InvalidType, - FailedToParse, -} - -#[cfg(feature = "array")] -impl FromEnvString for Vec -where - T: FromEnvString, -{ - type Err = ArrayEnvError; - - fn from_env_string(s: &EnvString) -> Result { - serde_json::from_str::>(s.trim()) - .map(|vec| vec.iter().map(|v| v.to_string()).collect::>()) - .or_else(|_| serde_json::from_str::>(s.trim())) - .map_err(|_| ArrayEnvError::InvalidType) - .and_then(|vec| { - vec.iter() - .map(|v| { - v.to_env_string() - .parse::() - .map_err(|_| ArrayEnvError::FailedToParse) - }) - .collect::, _>>() - }) - } -} - impl FromEnvString for String { type Err = (); @@ -115,20 +135,42 @@ impl FromEnvString for &'static str { } } -#[doc(hidden)] -#[derive(Debug, PartialEq, Clone)] -pub struct EnvString(String); +//===========================================================================// +// DEPRECATED // +//===========================================================================// -impl EnvString { - pub fn parse(&self) -> Result { - FromEnvString::from_env_string(self) - } +/// Error type for json array implementation +#[cfg(feature = "json_array")] +#[derive(Debug)] +#[deprecated(since = "1.1.0")] +pub enum ArrayEnvError { + /// Invalid type. + InvalidType, + + /// Failed to parse environment variable + FailedToParse, } -impl Deref for EnvString { - type Target = String; +#[cfg(feature = "json_array")] +#[allow(deprecated)] +impl FromEnvString for Vec +where + T: FromEnvString, +{ + type Err = ArrayEnvError; - fn deref(&self) -> &Self::Target { - &self.0 + fn from_env_string(s: &EnvString) -> Result { + serde_json::from_str::>(s.trim()) + .map(|vec| vec.iter().map(|v| v.to_string()).collect::>()) + .or_else(|_| serde_json::from_str::>(s.trim())) + .map_err(|_| ArrayEnvError::InvalidType) + .and_then(|vec| { + vec.iter() + .map(|v| { + FromEnvString::from_env_string(&v.to_env_string()) + .map_err(|_| ArrayEnvError::FailedToParse) + }) + .collect::, _>>() + }) } } diff --git a/itconfig/src/error.rs b/itconfig/src/error.rs index 2b0c92a..7173c70 100644 --- a/itconfig/src/error.rs +++ b/itconfig/src/error.rs @@ -1,9 +1,13 @@ use std::error; use std::fmt; +/// The error type for operations interacting with environment variables #[derive(Debug, PartialEq)] pub enum EnvError { + /// The specified environment variable was not present in the current process's environment. MissingVariable(String), + + /// Failed to parse the specified environment variable. FailedToParse(String), } diff --git a/itconfig/src/getenv.rs b/itconfig/src/getenv.rs index a396604..4f1d90d 100644 --- a/itconfig/src/getenv.rs +++ b/itconfig/src/getenv.rs @@ -1,4 +1,5 @@ -use crate::prelude::*; +use crate::envstr::*; +use crate::error::*; use std::env; /// Same as get_env but returns Option enum instead Result @@ -151,17 +152,14 @@ where .and_then(|env_str| parse_env_variable(env_name, env_str)) } -#[doc(hidden)] fn parse_env_variable(env_name: &str, env_str: EnvString) -> Result where T: FromEnvString, { - env_str - .parse::() + FromEnvString::from_env_string(&env_str) .map_err(|_| EnvError::FailedToParse(env_name.to_string())) } -#[doc(hidden)] fn make_panic(e: EnvError) -> T { panic!("{}", e) } diff --git a/itconfig/src/lib.rs b/itconfig/src/lib.rs index bee8ba7..2ca2655 100644 --- a/itconfig/src/lib.rs +++ b/itconfig/src/lib.rs @@ -113,7 +113,6 @@ //! //! * **default** - ["primitives"] //! * **macro** - Activates `config!` macros for easy configure web application. -//! * **array** - Add EnvString impl for vector type (uses optional `serde_json` package). //! * **primitives** - Group for features: `numbers` and `bool`. //! * **numbers** - Group for features: `int`, `uint` and `float`. //! * **int** - Group for features: `i8`, `i16`, `i32`, `i64`, `i128` and `isize`. @@ -134,12 +133,14 @@ //! * **f32** - impl EnvString for `f32` type //! * **f64** - impl EnvString for `f64` type //! * **bool** - impl EnvString for `bool` type +//! * **json_array** - Add EnvString impl for vector type (uses optional `serde_json` package). ⚠ **_DEPRECATED_** //! // Rustc lints. #![forbid(unsafe_code)] #![deny( missing_debug_implementations, + missing_docs, unstable_features, unused_imports, unused_qualifications @@ -149,18 +150,14 @@ ///////////////////////////////////////////////////////////////////////////// -pub mod envstr; +mod envstr; mod error; mod getenv; +pub use self::envstr::*; pub use self::error::*; pub use self::getenv::*; -pub mod prelude { - pub use crate::envstr::*; - pub use crate::error::*; -} - #[cfg(feature = "macro")] extern crate itconfig_macro; #[cfg(feature = "macro")]