statsig_rust/specs_response/
spec_directory.rs

1use super::spec_types::Spec;
2use crate::{event_logging::exposable_string::ExposableString, hashing::ahash_str};
3use ahash::HashMap;
4use serde::{Deserialize, Deserializer, Serialize};
5use std::sync::Arc;
6
7#[derive(Debug, PartialEq)]
8pub struct AddressableSpec {
9    pub name: ExposableString,
10    pub spec: Arc<Spec>,
11}
12
13#[derive(Debug, Default, PartialEq)]
14pub struct SpecDirectory {
15    pub specs: HashMap<u64, AddressableSpec>,
16}
17
18impl SpecDirectory {
19    pub fn get(&self, name: &str) -> Option<&AddressableSpec> {
20        let hash = ahash_str(name);
21        self.specs.get(&hash)
22    }
23
24    pub fn keys(&self) -> impl Iterator<Item = &str> {
25        self.specs.values().map(|v| v.name.as_str())
26    }
27
28    pub fn unperformant_keys(&self) -> Vec<String> {
29        self.specs
30            .values()
31            .map(|v| v.name.unperformant_to_string())
32            .collect()
33    }
34
35    pub fn unperformant_keys_entity_filter(&self, entity_type: &str) -> Vec<String> {
36        self.specs
37            .iter()
38            .filter(|(_, v)| v.spec.entity == entity_type)
39            .map(|(_, v)| v.name.unperformant_to_string())
40            .collect()
41    }
42}
43
44impl<'de> Deserialize<'de> for SpecDirectory {
45    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
46    where
47        D: Deserializer<'de>,
48    {
49        let specs = HashMap::<String, Spec>::deserialize(deserializer)?
50            .into_iter()
51            .map(|(k, v)| {
52                let name = ExposableString::from_str_ref(k.as_str());
53                let hash = name.hash_value;
54                let addressable = AddressableSpec {
55                    name,
56                    spec: Arc::new(v),
57                };
58
59                (hash, addressable)
60            })
61            .collect();
62
63        Ok(SpecDirectory { specs })
64    }
65}
66
67impl Serialize for SpecDirectory {
68    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
69    where
70        S: serde::Serializer,
71    {
72        let map: HashMap<&str, &Spec> = self
73            .specs
74            .values()
75            .map(|v| (v.name.as_str(), v.spec.as_ref()))
76            .collect();
77
78        map.serialize(serializer)
79    }
80}