Skip to main content

statsig_rust/evaluation/
dynamic_string.rs

1use serde::{Deserialize, Deserializer, Serialize, Serializer};
2use serde_json::Value;
3
4use crate::{hashing::ahash_str, interned_string::InternedString};
5
6lazy_static::lazy_static! {
7    static ref USER_ID: DynamicString = DynamicString::from("userID".to_string());
8    static ref STABLE_ID: DynamicString = DynamicString::from("stableID".to_string());
9}
10
11#[derive(Clone, Eq, Debug)]
12pub struct DynamicString {
13    pub value: InternedString,
14    pub lowercased_value: InternedString,
15    pub hash_value: u64,
16}
17
18impl DynamicString {
19    pub fn user_id() -> Self {
20        USER_ID.clone()
21    }
22
23    pub fn stable_id() -> Self {
24        STABLE_ID.clone()
25    }
26}
27
28// ------------------------------------------------------------------------------- [Serialization]
29
30impl Serialize for DynamicString {
31    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
32    where
33        S: Serializer,
34    {
35        if let Ok(bool_value) = self.value.parse::<bool>() {
36            return serializer.serialize_bool(bool_value);
37        }
38
39        serializer.serialize_str(&self.value)
40    }
41}
42
43impl<'de> Deserialize<'de> for DynamicString {
44    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
45    where
46        D: Deserializer<'de>,
47    {
48        let value = String::deserialize(deserializer)?;
49        Ok(DynamicString::from(value))
50    }
51}
52
53// ------------------------------------------------------------------------------- [PartialEq]
54
55impl PartialEq for DynamicString {
56    fn eq(&self, other: &Self) -> bool {
57        self.value == other.value
58    }
59}
60
61impl PartialEq<&str> for DynamicString {
62    fn eq(&self, other: &&str) -> bool {
63        self.value.as_str() == *other
64    }
65}
66
67impl PartialEq<String> for DynamicString {
68    fn eq(&self, other: &String) -> bool {
69        self.value == *other
70    }
71}
72
73impl PartialEq<&String> for DynamicString {
74    fn eq(&self, other: &&String) -> bool {
75        self.value.as_str() == other.as_str()
76    }
77}
78
79// ------------------------------------------------------------------------------- [From<T> Implementations]
80
81impl From<Value> for DynamicString {
82    fn from(value: Value) -> Self {
83        let str_value = match value.as_str() {
84            Some(value) => value.to_string(),
85            None => value.to_string(),
86        };
87        DynamicString::from(str_value)
88    }
89}
90
91impl From<String> for DynamicString {
92    fn from(value: String) -> Self {
93        let hash_value = ahash_str(&value);
94        let lowercased_value = value.to_lowercase();
95
96        Self {
97            value: InternedString::from_string(value),
98            lowercased_value: InternedString::from_string(lowercased_value),
99            hash_value,
100        }
101    }
102}