Skip to main content

feature_flag/
subject.rs

1//! The thing flags are evaluated against.
2
3use std::collections::HashMap;
4
5use serde::{Deserialize, Serialize};
6use serde_json::Value;
7
8/// The entity a flag is being evaluated for. `id` is the only required field
9/// and is used as the sticky-bucketing key. Arbitrary string-keyed attributes
10/// (`country`, `plan`, `email`, …) are supported by the [`crate::Predicate`] DSL.
11#[derive(Clone, Debug, Default, Deserialize, Serialize)]
12pub struct Subject {
13    /// Stable identifier for sticky bucketing. Usually a user/tenant/device id.
14    pub id: String,
15    /// Free-form string attributes for targeting (`{"country": "US", ...}`).
16    #[serde(default)]
17    pub attrs: HashMap<String, Value>,
18}
19
20impl Subject {
21    /// Build a new subject with the given id.
22    pub fn new<S: Into<String>>(id: S) -> Self {
23        Self {
24            id: id.into(),
25            attrs: HashMap::new(),
26        }
27    }
28
29    /// Builder helper: attach an attribute and return `self`.
30    #[must_use]
31    pub fn with_attr<K, V>(mut self, key: K, value: V) -> Self
32    where
33        K: Into<String>,
34        V: Into<Value>,
35    {
36        self.attrs.insert(key.into(), value.into());
37        self
38    }
39
40    /// Look up an attribute by name.
41    pub fn attr(&self, key: &str) -> Option<&Value> {
42        self.attrs.get(key)
43    }
44}