mk_lib/
utils.rs

1use std::fmt;
2
3use hashbrown::HashMap;
4use serde::de::{
5  self,
6  MapAccess,
7  Visitor,
8};
9use serde::{
10  Deserialize,
11  Deserializer,
12};
13use serde_json::Value as JsonValue;
14
15#[allow(dead_code)]
16#[derive(Debug)]
17enum AnyValue {
18  String(String),
19  Number(serde_json::Number),
20  Bool(bool),
21}
22
23impl fmt::Display for AnyValue {
24  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25    match self {
26      AnyValue::String(s) => write!(f, "{}", s),
27      AnyValue::Number(n) => write!(f, "{}", n),
28      AnyValue::Bool(b) => write!(f, "{}", b),
29    }
30  }
31}
32
33impl<'de> Deserialize<'de> for AnyValue {
34  fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
35  where
36    D: Deserializer<'de>,
37  {
38    let value: JsonValue = Deserialize::deserialize(deserializer)?;
39    match value {
40      JsonValue::String(s) => Ok(AnyValue::String(s)),
41      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  }
46}
47
48pub(crate) fn deserialize_environment<'de, D>(deserializer: D) -> Result<HashMap<String, String>, D::Error>
49where
50  D: Deserializer<'de>,
51{
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    fn visit_map<M>(self, mut access: M) -> Result<HashMap<String, String>, M::Error>
62    where
63      M: MapAccess<'de>,
64    {
65      let mut map = HashMap::new();
66      while let Some((key, value)) = access.next_entry::<String, AnyValue>()? {
67        map.insert(key, value.to_string());
68      }
69      Ok(map)
70    }
71  }
72
73  deserializer.deserialize_map(EnvironmentVisitor)
74}