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}