1
use std::fmt;
2

            
3
use hashbrown::HashMap;
4
use serde::de::{
5
  self,
6
  MapAccess,
7
  Visitor,
8
};
9
use serde::{
10
  Deserialize,
11
  Deserializer,
12
};
13
use serde_json::Value as JsonValue;
14

            
15
#[allow(dead_code)]
16
#[derive(Debug)]
17
enum AnyValue {
18
  String(String),
19
  Number(serde_json::Number),
20
  Bool(bool),
21
}
22

            
23
impl fmt::Display for AnyValue {
24
36
  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25
36
    match self {
26
32
      AnyValue::String(s) => write!(f, "{}", s),
27
4
      AnyValue::Number(n) => write!(f, "{}", n),
28
      AnyValue::Bool(b) => write!(f, "{}", b),
29
    }
30
36
  }
31
}
32

            
33
impl<'de> Deserialize<'de> for AnyValue {
34
36
  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
35
36
  where
36
36
    D: Deserializer<'de>,
37
36
  {
38
36
    let value: JsonValue = Deserialize::deserialize(deserializer)?;
39
36
    match value {
40
32
      JsonValue::String(s) => Ok(AnyValue::String(s)),
41
4
      JsonValue::Number(n) => Ok(AnyValue::Number(n)),
42
      JsonValue::Bool(b) => Ok(AnyValue::Bool(b)),
43
      _ => Err(de::Error::custom("expected a string, number, or boolean")),
44
    }
45
36
  }
46
}
47

            
48
18
pub(crate) fn deserialize_environment<'de, D>(deserializer: D) -> Result<HashMap<String, String>, D::Error>
49
18
where
50
18
  D: Deserializer<'de>,
51
18
{
52
  struct EnvironmentVisitor;
53

            
54
  impl<'de> Visitor<'de> for EnvironmentVisitor {
55
    type Value = HashMap<String, String>;
56

            
57
    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
58
      formatter.write_str("a map of strings to any value (string, int, or bool)")
59
    }
60

            
61
18
    fn visit_map<M>(self, mut access: M) -> Result<HashMap<String, String>, M::Error>
62
18
    where
63
18
      M: MapAccess<'de>,
64
18
    {
65
18
      let mut map = HashMap::new();
66
54
      while let Some((key, value)) = access.next_entry::<String, AnyValue>()? {
67
36
        map.insert(key, value.to_string());
68
36
      }
69
18
      Ok(map)
70
18
    }
71
  }
72

            
73
18
  deserializer.deserialize_map(EnvironmentVisitor)
74
18
}