statsig_rust/evaluation/
evaluation_types.rs1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::collections::HashMap;
4
5pub fn is_false(v: &bool) -> bool {
6 !(*v)
7}
8
9#[derive(Serialize, Deserialize, Clone, Debug)]
10#[serde(rename_all = "camelCase")]
11pub struct SecondaryExposure {
12 pub gate: String,
13 pub gate_value: String,
14 #[serde(rename = "ruleID")]
15 pub rule_id: String,
16}
17
18impl SecondaryExposure {
19 pub fn get_dedupe_key(&self) -> String {
20 let mut key = String::new();
21 key += &self.gate;
22 key += "|";
23 key += &self.gate_value;
24 key += "|";
25 key += &self.rule_id;
26 key
27 }
28}
29
30#[derive(Serialize, Deserialize, Clone, Debug, Default)]
31pub(crate) struct ExposureSamplingInfo {
32 pub sampling_rate: Option<u64>,
33 pub forward_all_exposures: Option<bool>,
34 pub has_seen_analytical_gates: Option<bool>,
35}
36
37#[derive(Serialize, Deserialize, Clone)]
38pub struct BaseEvaluation {
39 pub name: String,
40 pub rule_id: String,
41 pub secondary_exposures: Vec<SecondaryExposure>,
42
43 #[serde(skip_serializing)]
44 pub(crate) sampling_info: Option<ExposureSamplingInfo>,
45}
46
47pub enum AnyEvaluation<'a> {
48 FeatureGate(&'a GateEvaluation),
49 DynamicConfig(&'a DynamicConfigEvaluation),
50 Experiment(&'a ExperimentEvaluation),
51 Layer(&'a LayerEvaluation),
52}
53
54impl AnyEvaluation<'_> {
55 pub fn get_base_result(&self) -> &BaseEvaluation {
56 match self {
57 AnyEvaluation::FeatureGate(gate) => &gate.base,
58 AnyEvaluation::DynamicConfig(config) => &config.base,
59 AnyEvaluation::Experiment(experiment) => &experiment.base,
60 AnyEvaluation::Layer(layer) => &layer.base,
61 }
62 }
63
64 pub fn get_gate_bool_value(&self) -> bool {
65 match self {
66 AnyEvaluation::FeatureGate(eval) => eval.value,
67 _ => false, }
69 }
70}
71
72impl<'a> From<&'a LayerEvaluation> for AnyEvaluation<'a> {
73 fn from(layer_eval: &'a LayerEvaluation) -> Self {
74 AnyEvaluation::Layer(layer_eval)
75 }
76}
77
78impl<'a> From<&'a GateEvaluation> for AnyEvaluation<'a> {
79 fn from(gate_eval: &'a GateEvaluation) -> Self {
80 AnyEvaluation::FeatureGate(gate_eval)
81 }
82}
83
84impl<'a> From<&'a ExperimentEvaluation> for AnyEvaluation<'a> {
85 fn from(experiment_eval: &'a ExperimentEvaluation) -> Self {
86 AnyEvaluation::Experiment(experiment_eval)
87 }
88}
89
90impl<'a> From<&'a DynamicConfigEvaluation> for AnyEvaluation<'a> {
91 fn from(dynamic_config_evalation: &'a DynamicConfigEvaluation) -> Self {
92 AnyEvaluation::DynamicConfig(dynamic_config_evalation)
93 }
94}
95
96#[derive(Serialize, Deserialize, Clone)]
97pub struct GateEvaluation {
98 #[serde(flatten)]
99 pub base: BaseEvaluation,
100
101 pub id_type: String,
102 pub value: bool,
103}
104
105#[derive(Serialize, Deserialize, Clone)]
106pub struct DynamicConfigEvaluation {
107 #[serde(flatten)]
108 pub base: BaseEvaluation,
109
110 pub id_type: String,
111 pub value: HashMap<String, Value>,
112
113 pub group: String,
115 pub is_device_based: bool,
116
117 pub passed: bool,
118}
119
120#[derive(Serialize, Deserialize, Clone)]
121pub struct ExperimentEvaluation {
122 #[serde(flatten)]
123 pub base: BaseEvaluation,
124
125 pub id_type: String,
126 pub value: HashMap<String, Value>,
127
128 pub group: String,
130 pub is_device_based: bool,
131
132 #[serde(skip_serializing_if = "is_false")]
133 pub is_in_layer: bool,
134
135 #[serde(skip_serializing_if = "Option::is_none")]
136 pub explicit_parameters: Option<Vec<String>>,
137
138 #[serde(skip_serializing_if = "Option::is_none")]
139 pub group_name: Option<String>,
140
141 #[serde(skip_serializing_if = "Option::is_none")]
142 pub is_experiment_active: Option<bool>,
143
144 #[serde(skip_serializing_if = "Option::is_none")]
145 pub is_user_in_experiment: Option<bool>,
146 #[serde(skip_serializing_if = "Option::is_none")]
147 pub undelegated_secondary_exposures: Option<Vec<SecondaryExposure>>,
148}
149
150#[derive(Serialize, Deserialize, Clone)]
151#[serde(untagged)]
152pub enum AnyConfigEvaluation {
153 DynamicConfig(DynamicConfigEvaluation),
154 Experiment(ExperimentEvaluation),
155}
156
157#[derive(Serialize, Deserialize, Clone)]
158pub struct LayerEvaluation {
159 #[serde(flatten)]
160 pub base: BaseEvaluation,
161
162 pub value: HashMap<String, Value>,
163
164 pub id_type: String,
165
166 pub group: String,
168 pub is_device_based: bool,
169
170 #[serde(skip_serializing_if = "Option::is_none")]
171 pub group_name: Option<String>,
172
173 #[serde(skip_serializing_if = "Option::is_none")]
174 pub is_experiment_active: Option<bool>,
175
176 #[serde(skip_serializing_if = "Option::is_none")]
177 pub is_user_in_experiment: Option<bool>,
178
179 #[serde(skip_serializing_if = "Option::is_none")]
180 pub allocated_experiment_name: Option<String>,
181 pub explicit_parameters: Vec<String>,
182 #[serde(skip_serializing_if = "Option::is_none")]
183 pub undelegated_secondary_exposures: Option<Vec<SecondaryExposure>>,
184}