statsig-rust 0.19.1-beta.2604130314

Statsig Rust SDK for usage in multi-user server environments.
Documentation
use std::collections::HashMap;

use crate::{
    evaluation::evaluator_context::EvaluatorContext,
    gcir::gcir_formatter::GCIRHashable,
    hashing,
    specs_response::param_store_types::{
        DynamicConfigParameter, ExperimentParameter, GateParameter, LayerParameter, Parameter,
        ParameterStore, StaticValueParameter,
    },
    ClientInitResponseOptions, HashAlgorithm,
};

use super::target_app_id_utils::should_filter_config_for_app;

type SerializeableParamStore = HashMap<String, HashMap<String, Parameter>>;

pub(crate) fn get_serializeable_param_stores(
    context: &mut EvaluatorContext,
    options: &ClientInitResponseOptions,
) -> SerializeableParamStore {
    let stores = match &context.specs_data.param_stores {
        Some(stores) => stores,
        None => {
            if options.previous_response_hash.is_some() {
                context.gcir_hashes.push(0);
            }
            return HashMap::new();
        }
    };

    let mut hash_array: Vec<u64> = Vec::new();

    let mut param_stores = HashMap::new();

    for (name, store) in stores {
        if should_filter_config_for_app(
            store.target_app_ids.as_ref(),
            &context.app_id,
            &options.client_sdk_key,
        ) {
            continue;
        }

        if let Some(param_store_filter) = &options.param_store_filter {
            if !param_store_filter.contains(name.as_str()) {
                continue;
            }
        }

        if options.previous_response_hash.is_some() {
            hash_array.push(store.create_hash(name));
        }

        let hash_algorithm = options.get_hash_algorithm();
        let hashed_name = context.hashing.hash(name, hash_algorithm);
        let parameters = get_parameters_from_store(store, hash_algorithm, context);
        param_stores.insert(hashed_name, parameters);
    }
    if options.previous_response_hash.is_some() {
        context.gcir_hashes.push(hashing::hash_one(hash_array));
    }

    param_stores
}

fn get_parameters_from_store(
    store: &ParameterStore,
    hash_used: &HashAlgorithm,
    context: &EvaluatorContext,
) -> HashMap<String, Parameter> {
    // todo: what the heck is this mess?
    let mut parameters: HashMap<String, Parameter> = HashMap::new();
    for (param_name, param) in &store.parameters {
        match param {
            Parameter::StaticValue(static_value) => {
                let new_param = StaticValueParameter {
                    name: param_name.clone().into(),
                    param_type: static_value.param_type.clone(),
                    ref_type: static_value.ref_type.clone(),
                    value: static_value.value.clone(),
                };
                parameters.insert(param_name.clone(), Parameter::StaticValue(new_param));
            }

            Parameter::Gate(gate) => {
                let new_param = GateParameter {
                    name: param_name.clone().into(),
                    ref_type: gate.ref_type.clone(),
                    param_type: gate.param_type.clone(),
                    gate_name: context.hashing.hash(&gate.gate_name, hash_used),
                    pass_value: gate.pass_value.clone(),
                    fail_value: gate.fail_value.clone(),
                };
                parameters.insert(param_name.clone(), Parameter::Gate(new_param));
            }

            Parameter::DynamicConfig(dynamic_config) => {
                let new_param = DynamicConfigParameter {
                    name: param_name.clone().into(),
                    ref_type: dynamic_config.ref_type.clone(),
                    param_type: dynamic_config.param_type.clone(),
                    config_name: context.hashing.hash(&dynamic_config.config_name, hash_used),
                    param_name: dynamic_config.param_name.clone(),
                };
                parameters.insert(param_name.clone(), Parameter::DynamicConfig(new_param));
            }

            Parameter::Experiment(experiment) => {
                let new_param = ExperimentParameter {
                    name: param_name.clone().into(),
                    ref_type: experiment.ref_type.clone(),
                    param_type: experiment.param_type.clone(),
                    experiment_name: context.hashing.hash(&experiment.experiment_name, hash_used),
                    param_name: experiment.param_name.clone(),
                };
                parameters.insert(param_name.clone(), Parameter::Experiment(new_param));
            }

            Parameter::Layer(layer) => {
                let new_param = LayerParameter {
                    name: param_name.clone().into(),
                    ref_type: layer.ref_type.clone(),
                    param_type: layer.param_type.clone(),
                    layer_name: context.hashing.hash(&layer.layer_name, hash_used),
                    param_name: layer.param_name.clone(),
                };
                parameters.insert(param_name.clone(), Parameter::Layer(new_param));
            }
        }
    }
    parameters
}