statsig_rust/evaluation/
evaluator_context.rs1use crate::evaluation::dynamic_value::DynamicValue;
2use crate::evaluation::evaluator_result::EvaluatorResult;
3use crate::hashing::HashUtil;
4use crate::spec_store::SpecStoreData;
5use crate::spec_types::{Rule, Spec};
6use crate::user::StatsigUserInternal;
7use crate::StatsigErr::StackOverflowError;
8use crate::{OverrideAdapter, StatsigErr};
9use std::sync::Arc;
10
11const MAX_RECURSIVE_DEPTH: u16 = 300;
12
13pub struct EvaluatorContext<'a> {
14 pub user: &'a StatsigUserInternal<'a, 'a>,
15 pub spec_store_data: &'a SpecStoreData,
16 pub hashing: &'a HashUtil,
17 pub result: EvaluatorResult<'a>,
18 pub nested_count: u16,
19 pub app_id: &'a Option<&'a DynamicValue>,
20 pub override_adapter: &'a Option<Arc<dyn OverrideAdapter>>,
21}
22
23impl<'a> EvaluatorContext<'a> {
24 pub fn new(
25 user: &'a StatsigUserInternal,
26 spec_store_data: &'a SpecStoreData,
27 hashing: &'a HashUtil,
28 app_id: &'a Option<&'a DynamicValue>,
29 override_adapter: &'a Option<Arc<dyn OverrideAdapter>>,
30 ) -> Self {
31 let result = EvaluatorResult::default();
32
33 Self {
34 user,
35 spec_store_data,
36 hashing,
37 app_id,
38 result,
39 override_adapter,
40 nested_count: 0,
41 }
42 }
43
44 pub fn reset_result(&mut self) {
45 self.result = EvaluatorResult::default();
46 }
47
48 pub fn finalize_evaluation(&mut self, spec: &Spec, rule: Option<&Rule>) {
49 self.result.sampling_rate = rule.and_then(|r| r.sampling_rate);
50 self.result.forward_all_exposures = spec.forward_all_exposures;
51
52 if self.nested_count > 0 {
53 self.nested_count -= 1;
54 return;
55 }
56
57 if self.result.secondary_exposures.is_empty() {
58 return;
59 }
60
61 if self.result.undelegated_secondary_exposures.is_some() {
62 return;
63 }
64
65 self.result.undelegated_secondary_exposures = Some(self.result.secondary_exposures.clone());
66 }
67
68 pub fn prep_for_nested_evaluation(&mut self) -> Result<(), StatsigErr> {
69 self.nested_count += 1;
70
71 self.result.bool_value = false;
72 self.result.json_value = None;
73
74 if self.nested_count > MAX_RECURSIVE_DEPTH {
75 return Err(StackOverflowError);
76 }
77
78 Ok(())
79 }
80}