iam_rs/evaluation/
context.rs1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use std::collections::HashMap;
4
5#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
7#[serde(untagged)]
8pub enum ContextValue {
9 String(String),
11 Boolean(bool),
13 Number(f64),
15 DateTime(DateTime<Utc>),
17}
18
19impl ContextValue {
20 pub fn as_string(&self) -> Option<&String> {
22 match self {
23 ContextValue::String(s) => Some(s),
24 _ => None,
25 }
26 }
27
28 pub fn as_boolean(&self) -> Option<bool> {
30 match self {
31 ContextValue::Boolean(b) => Some(*b),
32 _ => None,
33 }
34 }
35
36 pub fn as_number(&self) -> Option<f64> {
38 match self {
39 ContextValue::Number(n) => Some(*n),
40 _ => None,
41 }
42 }
43}
44
45#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
47pub struct Context {
48 pub data: HashMap<String, ContextValue>,
50}
51
52impl Context {
53 pub fn new() -> Self {
55 Self {
56 data: HashMap::new(),
57 }
58 }
59
60 pub fn with_data(data: HashMap<String, ContextValue>) -> Self {
62 Self { data }
63 }
64
65 pub fn get(&self, key: &str) -> Option<&ContextValue> {
67 self.data.get(key)
68 }
69
70 pub fn insert(&mut self, key: String, value: ContextValue) {
72 self.data.insert(key, value);
73 }
74
75 pub fn with_string<K: Into<String>, V: Into<String>>(mut self, key: K, value: V) -> Self {
77 self.data
78 .insert(key.into(), ContextValue::String(value.into()));
79 self
80 }
81
82 pub fn with_boolean<K: Into<String>>(mut self, key: K, value: bool) -> Self {
84 self.data.insert(key.into(), ContextValue::Boolean(value));
85 self
86 }
87
88 pub fn with_number<K: Into<String>>(mut self, key: K, value: f64) -> Self {
90 self.data.insert(key.into(), ContextValue::Number(value));
91 self
92 }
93
94 pub fn has_key(&self, key: &str) -> bool {
96 self.data.contains_key(key)
97 }
98
99 pub fn keys(&self) -> Vec<&String> {
101 self.data.keys().collect()
102 }
103
104 pub fn extend(&mut self, other: Context) {
106 self.data.extend(other.data);
107 }
108}
109
110impl Default for Context {
111 fn default() -> Self {
112 Self::new()
113 }
114}
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn test_context_creation() {
122 let context = Context::new()
123 .with_string("key1", "value1")
124 .with_boolean("key2", true)
125 .with_number("key3", 42.0);
126
127 assert_eq!(context.get("key1").unwrap().as_string().unwrap(), "value1");
128 assert_eq!(context.get("key2").unwrap().as_boolean().unwrap(), true);
129 assert_eq!(context.get("key3").unwrap().as_number().unwrap(), 42.0);
130 }
131}