@@ -12,6 +12,21 @@ use std::{convert::Infallible, env::VarError, num::ParseIntError, str::FromStr};
1212/// occur when trying to create an instance of the struct from environment
1313/// variables. This error type is used in the `FromEnv` trait implementation.
1414///
15+ /// ## Attributes
16+ ///
17+ /// The macro supports the following attributes:
18+ /// - `var = ""`: The name of the environment variable. This is required if the
19+ /// prop implements [`FromEnvVar`].
20+ /// - `desc = ""`: A description of the environment variable. This is required
21+ /// if the prop implements [`FromEnvVar`].
22+ /// - `optional`: Marks the prop as optional. This is currently only used in the
23+ /// generated `fn inventory`, and is informational.
24+ /// - `infallible`: Marks the prop as infallible. This means that the prop
25+ /// cannot fail to be parsed after the environment variable is loaded.
26+ /// - `skip`: Marks the prop as skipped. This means that the prop will not be
27+ /// loaded from the environment, and will be generated via
28+ /// `Default::default()` instead.
29+ ///
1530/// ## Conditions of use
1631///
1732/// There are a few usage requirements:
@@ -266,6 +281,87 @@ pub trait FromEnv: core::fmt::Debug + Sized + 'static {
266281 fn from_env ( ) -> Result < Self , FromEnvErr < Self :: Error > > ;
267282}
268283
284+ impl < T > FromEnv for Option < T >
285+ where
286+ T : FromEnv ,
287+ {
288+ type Error = T :: Error ;
289+
290+ fn inventory ( ) -> Vec < & ' static EnvItemInfo > {
291+ T :: inventory ( )
292+ }
293+
294+ fn check_inventory ( ) -> Result < ( ) , Vec < & ' static EnvItemInfo > > {
295+ T :: check_inventory ( )
296+ }
297+
298+ fn from_env ( ) -> Result < Self , FromEnvErr < Self :: Error > > {
299+ match T :: from_env ( ) {
300+ Ok ( v) => Ok ( Some ( v) ) ,
301+ Err ( FromEnvErr :: Empty ( _) ) | Err ( FromEnvErr :: EnvError ( _, _) ) => Ok ( None ) ,
302+ Err ( e) => Err ( e) ,
303+ }
304+ }
305+ }
306+
307+ impl < T > FromEnv for Box < T >
308+ where
309+ T : FromEnv ,
310+ {
311+ type Error = T :: Error ;
312+
313+ fn inventory ( ) -> Vec < & ' static EnvItemInfo > {
314+ T :: inventory ( )
315+ }
316+
317+ fn check_inventory ( ) -> Result < ( ) , Vec < & ' static EnvItemInfo > > {
318+ T :: check_inventory ( )
319+ }
320+
321+ fn from_env ( ) -> Result < Self , FromEnvErr < Self :: Error > > {
322+ T :: from_env ( ) . map ( Box :: new)
323+ }
324+ }
325+
326+ impl < T > FromEnv for std:: sync:: Arc < T >
327+ where
328+ T : FromEnv ,
329+ {
330+ type Error = T :: Error ;
331+
332+ fn inventory ( ) -> Vec < & ' static EnvItemInfo > {
333+ T :: inventory ( )
334+ }
335+
336+ fn check_inventory ( ) -> Result < ( ) , Vec < & ' static EnvItemInfo > > {
337+ T :: check_inventory ( )
338+ }
339+
340+ fn from_env ( ) -> Result < Self , FromEnvErr < Self :: Error > > {
341+ T :: from_env ( ) . map ( std:: sync:: Arc :: new)
342+ }
343+ }
344+
345+ impl < T , U > FromEnv for std:: borrow:: Cow < ' static , U >
346+ where
347+ T : FromEnv ,
348+ U : std:: borrow:: ToOwned < Owned = T > + core:: fmt:: Debug ,
349+ {
350+ type Error = T :: Error ;
351+
352+ fn inventory ( ) -> Vec < & ' static EnvItemInfo > {
353+ T :: inventory ( )
354+ }
355+
356+ fn check_inventory ( ) -> Result < ( ) , Vec < & ' static EnvItemInfo > > {
357+ T :: check_inventory ( )
358+ }
359+
360+ fn from_env ( ) -> Result < Self , FromEnvErr < Self :: Error > > {
361+ T :: from_env ( ) . map ( std:: borrow:: Cow :: Owned )
362+ }
363+ }
364+
269365/// Trait for loading primitives from the environment. These are simple types
270366/// that should correspond to a single environment variable. It has been
271367/// implemented for common integer types, [`String`], [`url::Url`],
@@ -331,6 +427,49 @@ pub trait FromEnvVar: core::fmt::Debug + Sized + 'static {
331427
332428 /// Load the primitive from the environment at the given variable.
333429 fn from_env_var ( env_var : & str ) -> Result < Self , FromEnvErr < Self :: Error > > ;
430+
431+ /// Load the primitive from the environment at the given variable. If the
432+ /// variable is unset or empty, return the default value.
433+ ///
434+ /// This function will return an error if the environment variable is set
435+ /// but cannot be parsed.
436+ fn from_env_var_or ( env_var : & str , default : Self ) -> Result < Self , FromEnvErr < Self :: Error > > {
437+ match Self :: from_env_var ( env_var) {
438+ Ok ( v) => Ok ( v) ,
439+ Err ( FromEnvErr :: Empty ( _) ) | Err ( FromEnvErr :: EnvError ( _, _) ) => Ok ( default) ,
440+ Err ( e) => Err ( e) ,
441+ }
442+ }
443+
444+ /// Load the primitive from the environment at the given variable. If the
445+ /// variable is unset or empty, call the provided function to get the
446+ /// default value.
447+ ///
448+ /// This function will return an error if the environment variable is set
449+ /// but cannot be parsed.
450+ fn from_env_var_or_else (
451+ env_var : & str ,
452+ default : impl FnOnce ( ) -> Self ,
453+ ) -> Result < Self , FromEnvErr < Self :: Error > > {
454+ match Self :: from_env_var ( env_var) {
455+ Ok ( v) => Ok ( v) ,
456+ Err ( FromEnvErr :: Empty ( _) ) | Err ( FromEnvErr :: EnvError ( _, _) ) => Ok ( default ( ) ) ,
457+ Err ( e) => Err ( e) ,
458+ }
459+ }
460+
461+ /// Load the primitive from the environment at the given variable. If the
462+ /// variable is unset or empty, return the value generated by
463+ /// [`Default::default`].
464+ ///
465+ /// This function will return an error if the environment variable is set
466+ /// but cannot be parsed.
467+ fn from_env_var_or_default ( env_var : & str ) -> Result < Self , FromEnvErr < Self :: Error > >
468+ where
469+ Self : Default ,
470+ {
471+ Self :: from_env_var_or_else ( env_var, Self :: default)
472+ }
334473}
335474
336475impl < T > FromEnvVar for Option < T >
@@ -348,6 +487,40 @@ where
348487 }
349488}
350489
490+ impl < T > FromEnvVar for Box < T >
491+ where
492+ T : FromEnvVar ,
493+ {
494+ type Error = T :: Error ;
495+
496+ fn from_env_var ( env_var : & str ) -> Result < Self , FromEnvErr < Self :: Error > > {
497+ T :: from_env_var ( env_var) . map ( Box :: new)
498+ }
499+ }
500+
501+ impl < T > FromEnvVar for std:: sync:: Arc < T >
502+ where
503+ T : FromEnvVar ,
504+ {
505+ type Error = T :: Error ;
506+
507+ fn from_env_var ( env_var : & str ) -> Result < Self , FromEnvErr < Self :: Error > > {
508+ T :: from_env_var ( env_var) . map ( std:: sync:: Arc :: new)
509+ }
510+ }
511+
512+ impl < T , U > FromEnvVar for std:: borrow:: Cow < ' static , U >
513+ where
514+ T : FromEnvVar ,
515+ U : std:: borrow:: ToOwned < Owned = T > + core:: fmt:: Debug ,
516+ {
517+ type Error = T :: Error ;
518+
519+ fn from_env_var ( env_var : & str ) -> Result < Self , FromEnvErr < Self :: Error > > {
520+ T :: from_env_var ( env_var) . map ( std:: borrow:: Cow :: Owned )
521+ }
522+ }
523+
351524impl FromEnvVar for String {
352525 type Error = std:: convert:: Infallible ;
353526
0 commit comments