Merge pull request #24 from icetemple/env-type-doc

Add documentation for env string
This commit is contained in:
Dmitriy Pleshevskiy 2021-04-16 00:24:13 +02:00 committed by GitHub
commit b9f6372495
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 102 additions and 60 deletions

View File

@ -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

View File

@ -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" }

View File

@ -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<T> From<T> 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<Self, Self::Err>;
}
impl<T> 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<T> FromEnvString for Vec<T>
where
T: FromEnvString,
{
type Err = ArrayEnvError;
fn from_env_string(s: &EnvString) -> Result<Self, Self::Err> {
serde_json::from_str::<Vec<isize>>(s.trim())
.map(|vec| vec.iter().map(|v| v.to_string()).collect::<Vec<String>>())
.or_else(|_| serde_json::from_str::<Vec<String>>(s.trim()))
.map_err(|_| ArrayEnvError::InvalidType)
.and_then(|vec| {
vec.iter()
.map(|v| {
v.to_env_string()
.parse::<T>()
.map_err(|_| ArrayEnvError::FailedToParse)
})
.collect::<Result<Vec<T>, _>>()
})
}
}
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<T: FromEnvString>(&self) -> Result<T, T::Err> {
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<T> FromEnvString for Vec<T>
where
T: FromEnvString,
{
type Err = ArrayEnvError;
fn deref(&self) -> &Self::Target {
&self.0
fn from_env_string(s: &EnvString) -> Result<Self, Self::Err> {
serde_json::from_str::<Vec<isize>>(s.trim())
.map(|vec| vec.iter().map(|v| v.to_string()).collect::<Vec<String>>())
.or_else(|_| serde_json::from_str::<Vec<String>>(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::<Result<Vec<T>, _>>()
})
}
}

View File

@ -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),
}

View File

@ -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<T>(env_name: &str, env_str: EnvString) -> Result<T, EnvError>
where
T: FromEnvString,
{
env_str
.parse::<T>()
FromEnvString::from_env_string(&env_str)
.map_err(|_| EnvError::FailedToParse(env_name.to_string()))
}
#[doc(hidden)]
fn make_panic<T>(e: EnvError) -> T {
panic!("{}", e)
}

View File

@ -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")]