@@ -12,6 +12,21 @@ use std::{convert::Infallible, env::VarError, num::ParseIntError, str::FromStr};
12
12
/// occur when trying to create an instance of the struct from environment
13
13
/// variables. This error type is used in the `FromEnv` trait implementation.
14
14
///
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
+ ///
15
30
/// ## Conditions of use
16
31
///
17
32
/// There are a few usage requirements:
@@ -266,6 +281,87 @@ pub trait FromEnv: core::fmt::Debug + Sized + 'static {
266
281
fn from_env ( ) -> Result < Self , FromEnvErr < Self :: Error > > ;
267
282
}
268
283
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
+
269
365
/// Trait for loading primitives from the environment. These are simple types
270
366
/// that should correspond to a single environment variable. It has been
271
367
/// implemented for common integer types, [`String`], [`url::Url`],
@@ -331,6 +427,49 @@ pub trait FromEnvVar: core::fmt::Debug + Sized + 'static {
331
427
332
428
/// Load the primitive from the environment at the given variable.
333
429
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
+ }
334
473
}
335
474
336
475
impl < T > FromEnvVar for Option < T >
@@ -348,6 +487,40 @@ where
348
487
}
349
488
}
350
489
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
+
351
524
impl FromEnvVar for String {
352
525
type Error = std:: convert:: Infallible ;
353
526
0 commit comments