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}