statsig_rust/user/
statsig_user_internal.rs

1use super::StatsigUserLoggable;
2use crate::evaluation::dynamic_value::DynamicValue;
3use crate::StatsigUser;
4use crate::{evaluation::dynamic_string::DynamicString, Statsig};
5
6pub type FullUserKey = (
7    u64,      // app_version
8    u64,      // country
9    u64,      // email
10    u64,      // ip
11    u64,      // locale
12    u64,      // user_agent
13    u64,      // user_id
14    Vec<u64>, // custom_ids
15    Vec<u64>, // custom
16    Vec<u64>, // private_attributes
17    Vec<u64>, // statsig_env
18);
19
20#[derive(Clone)]
21pub struct StatsigUserInternal<'statsig, 'user> {
22    pub user_ref: &'user StatsigUser,
23    pub statsig_instance: Option<&'statsig Statsig>,
24}
25
26impl<'statsig, 'user> StatsigUserInternal<'statsig, 'user> {
27    pub fn new(user: &'user StatsigUser, statsig_instance: Option<&'statsig Statsig>) -> Self {
28        Self {
29            user_ref: user,
30            statsig_instance,
31        }
32    }
33
34    pub fn get_unit_id(&self, id_type: &DynamicString) -> Option<&DynamicValue> {
35        if id_type.lowercased_value.eq("userid") {
36            return self.user_ref.data.user_id.as_ref();
37        }
38
39        let custom_ids = self.user_ref.data.custom_ids.as_ref()?;
40
41        if let Some(custom_id) = custom_ids.get(&id_type.value) {
42            return Some(custom_id);
43        }
44
45        custom_ids.get(&id_type.lowercased_value)
46    }
47
48    pub fn get_user_value(&self, field: &Option<DynamicString>) -> Option<&DynamicValue> {
49        let field = field.as_ref()?;
50
51        let lowered_field = &field.lowercased_value;
52
53        let str_value = match lowered_field as &str {
54            "userid" => &self.user_ref.data.user_id,
55            "email" => &self.user_ref.data.email,
56            "ip" => &self.user_ref.data.ip,
57            "country" => &self.user_ref.data.country,
58            "locale" => &self.user_ref.data.locale,
59            "appversion" => &self.user_ref.data.app_version,
60            "useragent" => &self.user_ref.data.user_agent,
61            _ => &None,
62        };
63
64        if let Some(value) = str_value {
65            if let Some(str_val) = &value.string_value {
66                if !str_val.value.is_empty() {
67                    return Some(value);
68                }
69            }
70        }
71
72        if let Some(custom) = &self.user_ref.data.custom {
73            if let Some(found) = custom.get(&field.value) {
74                return Some(found);
75            }
76            if let Some(lowered_found) = custom.get(lowered_field) {
77                return Some(lowered_found);
78            }
79        }
80
81        if let Some(instance) = &self.statsig_instance {
82            if let Some(val) = instance.get_value_from_global_custom_fields(&field.value) {
83                return Some(val);
84            }
85
86            if let Some(val) = instance.get_value_from_global_custom_fields(&field.lowercased_value)
87            {
88                return Some(val);
89            }
90        }
91
92        if let Some(private_attributes) = &self.user_ref.data.private_attributes {
93            if let Some(found) = private_attributes.get(&field.value) {
94                return Some(found);
95            }
96            if let Some(lowered_found) = private_attributes.get(lowered_field) {
97                return Some(lowered_found);
98            }
99        }
100
101        let str_value_alt = match lowered_field as &str {
102            "user_id" => &self.user_ref.data.user_id,
103            "app_version" => &self.user_ref.data.app_version,
104            "user_agent" => &self.user_ref.data.user_agent,
105            _ => &None,
106        };
107
108        if str_value_alt.is_some() {
109            return str_value_alt.as_ref();
110        }
111
112        None
113    }
114
115    pub fn get_value_from_environment(
116        &self,
117        field: &Option<DynamicString>,
118    ) -> Option<DynamicValue> {
119        let field = field.as_ref()?;
120
121        if let Some(result) = self.statsig_instance?.get_from_statsig_env(&field.value) {
122            return Some(result);
123        }
124
125        self.statsig_instance?
126            .get_from_statsig_env(&field.lowercased_value)
127    }
128
129    pub fn to_loggable(&self) -> StatsigUserLoggable {
130        let (environment, global_custom) = match self.statsig_instance {
131            Some(statsig) => (
132                statsig.use_statsig_env(|e| e.cloned()),
133                statsig.use_global_custom_fields(|gc| gc.cloned()),
134            ),
135            None => (None, None),
136        };
137
138        StatsigUserLoggable::new(&self.user_ref.data, environment, global_custom)
139    }
140}