Skip to main content

statsig_rust/
statsig_types_raw.rs

1use std::collections::HashMap;
2
3use serde::Serialize;
4use serde_with::skip_serializing_none;
5
6use crate::evaluation::dynamic_returnable::DynamicReturnable;
7use crate::evaluation::evaluation_details::EvaluationDetails;
8use crate::interned_string::InternedString;
9use crate::specs_response::explicit_params::ExplicitParameters;
10use crate::user::StatsigUserLoggable;
11use crate::SecondaryExposure;
12
13#[derive(Serialize)]
14#[serde(rename_all = "camelCase")]
15pub(crate) struct FeatureGateRaw<'a> {
16    pub name: &'a str,
17
18    pub value: bool,
19
20    #[serde(rename = "ruleID")]
21    pub rule_id: SuffixedRuleId<'a>,
22
23    pub id_type: Option<&'a InternedString>,
24
25    pub details: &'a EvaluationDetails,
26}
27
28impl<'a> FeatureGateRaw<'a> {
29    pub fn empty(name: &'a str, details: &'a EvaluationDetails) -> Self {
30        Self {
31            name,
32            value: false,
33            details,
34            rule_id: SuffixedRuleId {
35                rule_id: InternedString::empty_ref(),
36                rule_id_suffix: None,
37            },
38            id_type: None,
39        }
40    }
41}
42
43#[derive(Serialize)]
44#[serde(rename_all = "camelCase")]
45pub(crate) struct DynamicConfigRaw<'a> {
46    pub name: &'a str,
47
48    pub value: Option<&'a DynamicReturnable>,
49
50    #[serde(rename = "ruleID")]
51    pub rule_id: SuffixedRuleId<'a>,
52
53    pub id_type: Option<&'a InternedString>,
54
55    pub details: &'a EvaluationDetails,
56}
57
58impl<'a> DynamicConfigRaw<'a> {
59    pub fn empty(name: &'a str, details: &'a EvaluationDetails) -> Self {
60        Self {
61            name,
62            value: None,
63            details,
64            rule_id: SuffixedRuleId {
65                rule_id: InternedString::empty_ref(),
66                rule_id_suffix: None,
67            },
68            id_type: None,
69        }
70    }
71}
72
73#[derive(Serialize)]
74#[serde(rename_all = "camelCase")]
75pub(crate) struct ExperimentRaw<'a> {
76    pub name: &'a str,
77
78    pub value: Option<&'a DynamicReturnable>,
79
80    #[serde(rename = "ruleID")]
81    pub rule_id: SuffixedRuleId<'a>,
82
83    pub id_type: Option<&'a InternedString>,
84
85    pub group_name: Option<&'a InternedString>,
86
87    pub is_experiment_active: Option<bool>,
88
89    pub details: &'a EvaluationDetails,
90
91    pub secondary_exposures: Option<&'a Vec<SecondaryExposure>>,
92}
93
94impl<'a> ExperimentRaw<'a> {
95    pub fn empty(name: &'a str, details: &'a EvaluationDetails) -> Self {
96        Self {
97            name,
98            value: None,
99            details,
100            rule_id: SuffixedRuleId {
101                rule_id: InternedString::empty_ref(),
102                rule_id_suffix: None,
103            },
104            id_type: None,
105            group_name: None,
106            is_experiment_active: None,
107            secondary_exposures: None,
108        }
109    }
110}
111
112fn is_interned_string_none_or_empty(value: &Option<&InternedString>) -> bool {
113    match value {
114        Some(value) => value.is_empty(),
115        None => true,
116    }
117}
118
119#[derive(Serialize)]
120#[serde(rename_all = "camelCase")]
121#[skip_serializing_none]
122pub(crate) struct LayerRaw<'a> {
123    pub name: &'a str,
124
125    pub value: Option<&'a DynamicReturnable>,
126
127    #[serde(rename = "ruleID")]
128    pub rule_id: SuffixedRuleId<'a>,
129
130    pub id_type: Option<&'a InternedString>,
131
132    pub group_name: Option<&'a InternedString>,
133
134    pub is_experiment_active: Option<bool>,
135
136    pub details: &'a EvaluationDetails,
137
138    #[serde(skip_serializing_if = "is_interned_string_none_or_empty")]
139    pub allocated_experiment_name: Option<&'a InternedString>,
140
141    pub disable_exposure: bool,
142
143    pub user: StatsigUserLoggable,
144
145    pub secondary_exposures: Option<&'a Vec<SecondaryExposure>>,
146
147    pub undelegated_secondary_exposures: Option<&'a Vec<SecondaryExposure>>,
148
149    pub explicit_parameters: Option<ExplicitParameters>,
150
151    pub parameter_rule_ids: Option<&'a HashMap<InternedString, InternedString>>,
152}
153
154impl<'a> LayerRaw<'a> {
155    pub fn empty(name: &'a str, details: &'a EvaluationDetails) -> Self {
156        Self {
157            name,
158            details,
159            rule_id: SuffixedRuleId {
160                rule_id: InternedString::empty_ref(),
161                rule_id_suffix: None,
162            },
163            id_type: None,
164            group_name: None,
165            is_experiment_active: None,
166            value: None,
167            allocated_experiment_name: None,
168            disable_exposure: false,
169            user: StatsigUserLoggable::null(),
170            secondary_exposures: None,
171            undelegated_secondary_exposures: None,
172            explicit_parameters: None,
173            parameter_rule_ids: None,
174        }
175    }
176}
177
178#[derive(serde::Deserialize)]
179#[serde(rename_all = "camelCase")]
180#[cfg(feature = "ffi-support")]
181pub(crate) struct PartialLayerRaw {
182    pub name: InternedString,
183
184    #[serde(rename = "ruleID")]
185    pub rule_id: Option<InternedString>,
186
187    pub id_type: Option<InternedString>,
188
189    pub group_name: Option<InternedString>,
190
191    pub details: EvaluationDetails,
192
193    pub allocated_experiment_name: Option<InternedString>,
194    pub disable_exposure: bool,
195    pub user: StatsigUserLoggable,
196    pub secondary_exposures: Option<Vec<SecondaryExposure>>,
197    pub undelegated_secondary_exposures: Option<Vec<SecondaryExposure>>,
198    pub explicit_parameters: Option<ExplicitParameters>,
199    pub parameter_rule_ids: Option<HashMap<InternedString, InternedString>>,
200}
201
202pub struct SuffixedRuleId<'a> {
203    pub rule_id: &'a InternedString,
204    pub rule_id_suffix: Option<&'a str>,
205}
206
207impl<'a> std::fmt::Display for SuffixedRuleId<'a> {
208    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209        f.write_str(self.rule_id.as_str())?;
210        if let Some(suffix) = self.rule_id_suffix {
211            f.write_str(":")?;
212            f.write_str(suffix)?;
213        }
214        Ok(())
215    }
216}
217
218impl<'a> Serialize for SuffixedRuleId<'a> {
219    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
220    where
221        S: serde::Serializer,
222    {
223        serializer.collect_str(self)
224    }
225}