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