zenv/lib.rs
1//! Zenv is a dotenv loader which parses and loads your environment variables from a `.env` file.
2//!
3//! This crate also supports variable substitution inside your .env file, if not found then
4//! tries to fetch from the running operating system. By default, this is disabled.
5//!
6//! _This crate only meant to use inside a development environment._
7//!
8//! Example
9//! ```
10//! use zenv::{zenv, Zenv};
11//!
12//! fn main() {
13//! Zenv::new(".env", false).configure().ok();
14//! // is equivalent to
15//! zenv!();
16//!
17//! // with other file
18//! zenv!(".env.development");
19//!
20//! // or with variable substitution
21//! zenv!(".env.development", true);
22//! }
23//! ```
24
25mod parser;
26
27use std::{
28 collections::HashMap,
29 fs::read_to_string,
30 io::{Error, ErrorKind, Result},
31 path::PathBuf,
32};
33
34// Just re-exporting to use as a standalone parser
35pub use parser::{KeyVal, Line, Lines, Quote};
36
37/// Use this to load and configure the environment variables
38#[derive(Debug)]
39pub struct Zenv {
40 path: PathBuf,
41 expand: bool,
42}
43
44impl Zenv {
45 /// Create a new instance of Zenv with the provided file path
46 pub fn new(path: &str, expand: bool) -> Self {
47 Self {
48 path: PathBuf::from(path),
49 expand,
50 }
51 }
52
53 /// Read and parse the file from provided path and returns a hashmap
54 ///
55 /// Example
56 /// ```
57 /// let parsed = zenv::Zenv::new("tests/.env.basic", false).parse().unwrap();
58 ///
59 /// assert_eq!(parsed.get("BASIC"), Some(&"basic".to_string()))
60 /// ```
61 pub fn parse(&self) -> Result<HashMap<String, String>> {
62 let path = &self.path;
63
64 if !path.exists() {
65 return Err(Error::new(
66 ErrorKind::NotFound,
67 format!("Unable to find file - {}", path.display()),
68 ));
69 }
70
71 let r = read_to_string(path)?;
72 let lines = Lines::from(r.as_str());
73
74 let hash = match self.expand {
75 true => lines.expand(),
76 false => lines.to_hash_map(),
77 };
78
79 Ok(hash)
80 }
81
82 /// Parse the file using [Zenv::parse] and sets the environment variable
83 ///
84 /// Example
85 /// ```
86 /// zenv::Zenv::new("tests/.env.basic", false).configure().ok();
87 ///
88 /// assert_eq!(std::env::var_os("BASIC"), Some("basic".into()))
89 /// ```
90 pub fn configure(&self) -> Result<()> {
91 let vars = self.parse()?;
92
93 for (key, val) in vars {
94 std::env::set_var(key, val);
95 }
96
97 Ok(())
98 }
99}
100
101/// This macro can be used as a shortcut for [`Zenv`]
102///
103/// Example
104/// ```
105/// use zenv::zenv;
106///
107/// zenv!();
108///
109/// // with other file
110/// zenv!(".env.development");
111///
112/// // or with variable substitution
113/// zenv!(".env.development", true);
114/// ````
115#[macro_export]
116macro_rules! zenv {
117 () => {
118 zenv::Zenv::new(".env", false).configure().ok()
119 };
120 ($path:expr) => {
121 zenv::Zenv::new($path, false).configure().ok()
122 };
123 ($path:expr, $expand:expr) => {
124 zenv::Zenv::new($path, $expand).configure().ok()
125 };
126}