1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
use std::sync::Arc;
use crate::Str;
use crate::{AttributeValue, Attributes};
/// `Subject` is a bundle of subject attributes and a key.
#[derive(Debug)]
pub(super) struct Subject {
/// Subject key encoded as attribute value. Known to be `AttributeValue::String`. This is
/// done to allow returning subject key as an attribute when rule references "id".
key: AttributeValue,
attributes: Arc<Attributes>,
}
impl Subject {
pub fn new(key: Str, attributes: Arc<Attributes>) -> Subject {
Subject {
key: AttributeValue::from(key),
attributes,
}
}
pub fn key(&self) -> &Str {
let Some(s) = self.key.as_str() else {
unreachable!("Subject::key is always encoded as categorical string attribute");
};
s
}
/// Get subject attribute.
///
/// If attribute `name` is `"id"` and there's no explicit attribute with this name, return
/// subject key instead. This is a standard Eppo behavior when evaluation rules.
pub fn get_attribute(&self, name: &str) -> Option<&AttributeValue> {
let value = self.attributes.get(name);
if value.is_some() {
return value;
}
if name == "id" {
return Some(&self.key);
}
None
}
}