orleans_rust_client/
request_context.rs1use std::collections::BTreeMap;
9
10#[derive(Debug, Clone, Default, PartialEq, Eq)]
12pub struct RequestContext {
13 entries: BTreeMap<String, String>,
14}
15
16impl RequestContext {
17 #[must_use]
19 pub fn new() -> Self {
20 Self::default()
21 }
22
23 #[must_use]
25 pub fn with(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
26 self.entries.insert(key.into(), value.into());
27 self
28 }
29
30 pub fn set(&mut self, key: impl Into<String>, value: impl Into<String>) -> &mut Self {
32 self.entries.insert(key.into(), value.into());
33 self
34 }
35
36 #[must_use]
38 pub fn get(&self, key: &str) -> Option<&str> {
39 self.entries.get(key).map(String::as_str)
40 }
41
42 #[must_use]
44 pub fn is_empty(&self) -> bool {
45 self.entries.is_empty()
46 }
47
48 #[must_use]
50 pub fn len(&self) -> usize {
51 self.entries.len()
52 }
53
54 pub fn iter(&self) -> impl Iterator<Item = (&str, &str)> {
56 self.entries.iter().map(|(k, v)| (k.as_str(), v.as_str()))
57 }
58
59 #[must_use]
62 pub fn merged_with(&self, other: &RequestContext) -> RequestContext {
63 let mut merged = self.clone();
64 for (k, v) in &other.entries {
65 merged.entries.insert(k.clone(), v.clone());
66 }
67 merged
68 }
69
70 pub(crate) fn into_map(self) -> std::collections::HashMap<String, String> {
71 self.entries.into_iter().collect()
72 }
73}
74
75impl<K, V> FromIterator<(K, V)> for RequestContext
76where
77 K: Into<String>,
78 V: Into<String>,
79{
80 fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
81 Self {
82 entries: iter
83 .into_iter()
84 .map(|(k, v)| (k.into(), v.into()))
85 .collect(),
86 }
87 }
88}
89
90#[cfg(test)]
91mod tests {
92 use super::*;
93
94 #[test]
95 fn builder_and_accessors() {
96 let ctx = RequestContext::new().with("a", "1").with("b", "2");
97 assert_eq!(ctx.len(), 2);
98 assert!(!ctx.is_empty());
99 assert_eq!(ctx.get("a"), Some("1"));
100 assert_eq!(ctx.get("missing"), None);
101 }
102
103 #[test]
104 fn iter_is_key_ordered() {
105 let ctx = RequestContext::new().with("z", "1").with("a", "2");
106 let keys: Vec<&str> = ctx.iter().map(|(k, _)| k).collect();
107 assert_eq!(keys, vec!["a", "z"]);
108 }
109
110 #[test]
111 fn merged_with_overlays_other() {
112 let base = RequestContext::new().with("a", "1").with("b", "1");
113 let over = RequestContext::new().with("b", "2").with("c", "3");
114 let merged = base.merged_with(&over);
115 assert_eq!(merged.get("a"), Some("1"));
116 assert_eq!(merged.get("b"), Some("2"));
117 assert_eq!(merged.get("c"), Some("3"));
118 }
119
120 #[test]
121 fn into_map_preserves_entries() {
122 let map = RequestContext::from_iter([("k", "v")]).into_map();
123 assert_eq!(map.get("k"), Some(&"v".to_owned()));
124 }
125
126 #[test]
127 fn set_mutates_in_place_and_overwrites() {
128 let mut ctx = RequestContext::new();
129 assert!(ctx.is_empty());
130 ctx.set("a", "1").set("b", "2").set("a", "overwritten");
131 assert_eq!(ctx.len(), 2);
132 assert_eq!(ctx.get("a"), Some("overwritten"));
133 assert_eq!(ctx.get("b"), Some("2"));
134 }
135}