1use core::{fmt, ops::Deref};
2use std::{
3 collections::HashMap,
4 io::{BufRead as _, Cursor, Error as IoError},
5};
6
7#[derive(Debug, Clone)]
9pub struct EnvironmentVariables(pub HashMap<Box<str>, Box<str>>);
10
11impl Deref for EnvironmentVariables {
12 type Target = HashMap<Box<str>, Box<str>>;
13
14 fn deref(&self) -> &Self::Target {
15 &self.0
16 }
17}
18
19impl EnvironmentVariables {
20 pub fn from_kv_bytes(
21 bytes: impl AsRef<[u8]>,
22 ) -> Result<Self, EnvironmentVariablesFromKvBytesError> {
23 let bytes = bytes.as_ref();
24
25 let cursor = Cursor::new(bytes);
26
27 let map: HashMap<Box<str>, Box<str>> = cursor
28 .lines()
29 .map(|x| match x {
30 Ok(s) => {
31 let mut split = s.split('=');
32 let k: Box<str> = split.next().unwrap_or_default().into();
33 let v: Box<str> = split.next().unwrap_or_default().into();
34
35 Ok((k, v))
36 }
37 Err(err) => Err(EnvironmentVariablesFromKvBytesError::LinesReadFailed(err)),
38 })
39 .collect::<Result<_, _>>()?;
40
41 Ok(Self(map))
42 }
43}
44
45#[derive(Debug)]
47pub enum EnvironmentVariablesFromKvBytesError {
48 LinesReadFailed(IoError),
49}
50
51impl fmt::Display for EnvironmentVariablesFromKvBytesError {
52 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53 write!(f, "{:?}", self)
54 }
55}
56
57impl std::error::Error for EnvironmentVariablesFromKvBytesError {}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn test_info_from_kv_bytes() {
65 let bytes = include_bytes!("../tests/files/2_5_5_show_env.txt");
66
67 let vars = EnvironmentVariables::from_kv_bytes(bytes).unwrap();
68
69 assert_eq!(
70 vars.get("HAPROXY_VERSION").cloned().unwrap(),
71 "2.5.5".into()
72 );
73 }
74}