1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
use crate::to_parse_error; use crate::CanExtractOptional; use crate::CanExtractRequired; use crate::Error; use crate::Error::NotPresent; use crate::ExtractorResult; use std::env; use std::env::VarError; use std::fmt::Debug; use std::str::FromStr; pub struct SingleValue { pub key: String, } type ResultFromStr<Y, X> = ExtractorResult<Y, <X as FromStr>::Err>; impl SingleValue { pub fn new<A: Into<String>>(key: A) -> SingleValue { SingleValue { key: key.into() } } pub fn as_optional<A>(&self) -> Result<A, <Self as CanExtractOptional<A>>::Err> where Self: CanExtractOptional<A>, { self.get_optional() } pub fn as_required<A>(&self) -> Result<A, <Self as CanExtractRequired<A>>::Err> where Self: CanExtractRequired<A>, { self.get_required() } fn parse<X, Y, F1, F2>(&self, if_not_found: F1, reify: F2) -> ResultFromStr<Y, X> where X: FromStr, <X as FromStr>::Err: Debug, F1: Fn() -> ResultFromStr<Y, X>, F2: Fn(X) -> ResultFromStr<Y, X>, { let to_parsed = |value: String| { X::from_str(&value) .map_err(|e| to_parse_error(self.key.to_string(), value, e)) .and_then(reify) }; let maybe = match env::var(&self.key) { Ok(x1) => Some(x1), Err(VarError::NotPresent) => None, Err(e) => return Err(Error::EnvVarError(e)), }; maybe.map(to_parsed).unwrap_or_else(if_not_found) } } impl<A: FromStr> CanExtractOptional<Option<A>> for SingleValue where <A as FromStr>::Err: Debug, { type Err = Error<<A as FromStr>::Err>; fn get_optional(&self) -> Result<Option<A>, Self::Err> { let if_not_found = || Ok(None); let reify = |item| Ok(Some(item)); self.parse(if_not_found, reify) } } impl<A: FromStr> CanExtractRequired<A> for SingleValue where <A as FromStr>::Err: Debug, { type Err = Error<<A as FromStr>::Err>; fn get_required(&self) -> Result<A, Self::Err> { let if_not_found = || Err(NotPresent(self.key.to_string())); let reify = |item| Ok(item); self.parse(if_not_found, reify) } }