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