Skip to main content

statsig_rust/specs_response/
specs_hash_map.rs

1use std::sync::Arc;
2
3use ahash::HashMap;
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5use serde_json::value::RawValue;
6
7use crate::{interned_string::InternedString, log_e, specs_response::spec_types::Spec};
8
9const TAG: &str = "SpecsHashMap";
10
11#[derive(PartialEq, Debug, Default)] /* DO_NOT_CLONE */
12pub struct SpecsHashMap(pub HashMap<InternedString, SpecPointer>);
13
14impl<'de> Deserialize<'de> for SpecsHashMap {
15    fn deserialize<D>(_deserializer: D) -> Result<Self, D::Error>
16    where
17        D: Deserializer<'de>,
18    {
19        let raw_values: HashMap<InternedString, Box<RawValue>> =
20            Deserialize::deserialize(_deserializer)?;
21
22        let mut result = HashMap::default();
23        for (key, raw_value) in raw_values.into_iter() {
24            let json_string = raw_value.get();
25
26            let spec = match serde_json::from_str(json_string) {
27                Ok(spec) => spec,
28                Err(e) => {
29                    log_e!(TAG, "Failed to deserialize spec: {}", e);
30                    continue;
31                }
32            };
33
34            result.insert(key, SpecPointer::Pointer(Arc::new(spec)));
35        }
36
37        Ok(SpecsHashMap(result))
38    }
39}
40
41impl Serialize for SpecsHashMap {
42    fn serialize<S>(&self, _serializer: S) -> Result<S::Ok, S::Error>
43    where
44        S: Serializer,
45    {
46        self.0.serialize(_serializer)
47    }
48}
49
50/// Feel free to add more HashMap pass-through methods here as needed.
51impl SpecsHashMap {
52    pub fn get(&self, key: &InternedString) -> Option<&SpecPointer> {
53        self.0.get(key)
54    }
55
56    pub fn keys(&self) -> impl Iterator<Item = &InternedString> {
57        self.0.keys()
58    }
59
60    pub fn iter(&self) -> impl Iterator<Item = (&InternedString, &SpecPointer)> {
61        self.0.iter()
62    }
63
64    pub fn insert(&mut self, key: InternedString, value: SpecPointer) {
65        self.0.insert(key, value);
66    }
67
68    pub fn len(&self) -> usize {
69        self.0.len()
70    }
71
72    pub fn is_empty(&self) -> bool {
73        self.0.is_empty()
74    }
75
76    pub fn clear(&mut self) {
77        self.0.clear();
78    }
79
80    pub fn remove(&mut self, key: &InternedString) -> Option<SpecPointer> {
81        self.0.remove(key)
82    }
83}
84
85#[derive(PartialEq, Debug, Clone /* Clone Ok because Arc */)]
86pub enum SpecPointer {
87    Pointer(Arc<Spec>),
88    Static(&'static Spec),
89}
90
91impl SpecPointer {
92    pub fn as_spec_ref(&self) -> &Spec {
93        match self {
94            Self::Pointer(spec) => spec,
95            Self::Static(spec) => spec,
96        }
97    }
98}
99
100impl Serialize for SpecPointer {
101    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
102    where
103        S: Serializer,
104    {
105        match self {
106            Self::Pointer(spec) => spec.serialize(serializer),
107            Self::Static(spec) => spec.serialize(serializer),
108        }
109    }
110}
111
112impl SpecPointer {
113    pub fn from_spec(spec: Spec) -> Self {
114        Self::Pointer(Arc::new(spec))
115    }
116}