1use serde::Serialize;
4use tera::Context;
5
6pub struct ContextBuilder {
23 context: Context,
24}
25
26impl ContextBuilder {
27 pub fn new() -> Self {
29 Self {
30 context: Context::new(),
31 }
32 }
33
34 pub fn insert<T: Serialize + ?Sized>(mut self, key: impl Into<String>, value: &T) -> Self {
36 self.context.insert(key.into(), value);
37 self
38 }
39
40 pub fn insert_if<T: Serialize + ?Sized, F>(
42 self,
43 key: impl Into<String>,
44 value: &T,
45 condition: F,
46 ) -> Self
47 where
48 F: FnOnce(&T) -> bool,
49 {
50 if condition(value) {
51 self.insert(key, value)
52 } else {
53 self
54 }
55 }
56
57 pub fn insert_some<T: Serialize + ?Sized>(
59 self,
60 key: impl Into<String>,
61 value: Option<&T>,
62 ) -> Self {
63 if let Some(v) = value {
64 self.insert(key, v)
65 } else {
66 self
67 }
68 }
69
70 pub fn extend<T: Serialize>(mut self, value: &T) -> Result<Self, tera::Error> {
72 let additional = Context::from_serialize(value)?;
73 self.context.extend(additional);
74 Ok(self)
75 }
76
77 pub fn build(self) -> Context {
79 self.context
80 }
81}
82
83impl Default for ContextBuilder {
84 fn default() -> Self {
85 Self::new()
86 }
87}
88
89impl From<ContextBuilder> for Context {
90 fn from(builder: ContextBuilder) -> Self {
91 builder.build()
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[test]
100 fn test_context_builder() {
101 let context = ContextBuilder::new()
102 .insert("name", &"Alice")
103 .insert("age", &30)
104 .build();
105
106 assert!(context.contains_key("name"));
107 assert!(context.contains_key("age"));
108 }
109
110 #[test]
111 fn test_insert_if() {
112 let show = true;
113 let context = ContextBuilder::new()
114 .insert_if("visible", &"yes", |_| show)
115 .insert_if("hidden", &"no", |_| !show)
116 .build();
117
118 assert!(context.contains_key("visible"));
119 assert!(!context.contains_key("hidden"));
120 }
121
122 #[test]
123 fn test_insert_some() {
124 let name: Option<&str> = Some("Alice");
125 let missing: Option<&str> = None;
126
127 let context = ContextBuilder::new()
128 .insert_some("name", name)
129 .insert_some("missing", missing)
130 .build();
131
132 assert!(context.contains_key("name"));
133 assert!(!context.contains_key("missing"));
134 }
135}