1use std::collections::{HashMap, BTreeMap};
2use crate::renderer::RenderValue;
3use crate::template::Template;
4
5
6#[derive(Clone, Debug)]
7pub enum ContextValue {
8 Integer(i64),
9 Boolean(bool),
10 String(String),
11 Vec(Vec<ContextValue>),
12 Object(RenderContext),
13 Template(Template),
14}
15
16impl From<&str> for ContextValue {
17 fn from(other: &str) -> Self {
18 ContextValue::String(other.into())
19 }
20}
21
22impl From<String> for ContextValue {
23 fn from(other: String) -> Self {
24 ContextValue::String(other)
25 }
26}
27
28impl From<&String> for ContextValue {
29 fn from(other: &String) -> Self {
30 ContextValue::String(other.clone())
31 }
32}
33
34impl<T: Into<ContextValue>> From<Vec<T>> for ContextValue {
35 fn from(other: Vec<T>) -> Self {
36 ContextValue::Vec(other.into_iter().map(|k| k.into()).collect())
37 }
38}
39
40impl From<RenderContext> for ContextValue {
41 fn from(other: RenderContext) -> Self {
42 ContextValue::Object(other)
43 }
44}
45
46impl From<BTreeMap<String, ContextValue>> for ContextValue {
47 fn from(other: BTreeMap<String, ContextValue>) -> Self {
48 ContextValue::Object(RenderContext(other))
49 }
50}
51
52impl From<HashMap<String, ContextValue>> for ContextValue {
53 fn from(other: HashMap<String, ContextValue>) -> Self {
54 ContextValue::Object(RenderContext(other.into_iter().collect()))
55 }
56}
57
58impl From<Template> for ContextValue {
59 fn from(other: Template) -> Self {
60 ContextValue::Template(other)
61 }
62}
63
64impl From<bool> for ContextValue {
65 fn from(other: bool) -> Self {
66 ContextValue::Boolean(other)
67 }
68}
69
70impl From<usize> for ContextValue {
72 fn from(other: usize) -> Self {
73 ContextValue::Integer(other as i64)
74 }
75}
76
77impl From<i32> for ContextValue {
78 fn from(other: i32) -> Self {
79 ContextValue::Integer(other as i64)
80 }
81}
82
83impl From<i64> for ContextValue {
84 fn from(other: i64) -> Self {
85 ContextValue::Integer(other)
86 }
87}
88
89impl From<u32> for ContextValue {
90 fn from(other: u32) -> Self {
91 ContextValue::Integer(other as i64)
92 }
93}
94
95impl PartialEq for ContextValue {
96 fn eq(&self, other: &ContextValue) -> bool {
97 match (self, other) {
98 (ContextValue::Integer(a), ContextValue::Integer(b)) => a == b,
99 (ContextValue::Boolean(a), ContextValue::Boolean(b)) => a == b,
100 (ContextValue::String(a), ContextValue::String(b)) => a == b,
101 (ContextValue::Vec(a), ContextValue::Vec(b)) => a == b,
102 _ => false,
103 }
104 }
105}
106
107impl PartialOrd for ContextValue {
108 fn partial_cmp(&self, other: &ContextValue) -> Option<std::cmp::Ordering> {
109 match (self, other) {
110 (ContextValue::Integer(a), ContextValue::Integer(b)) => a.partial_cmp(b),
111 (ContextValue::Boolean(a), ContextValue::Boolean(b)) => a.partial_cmp(b),
112 (ContextValue::String(a), ContextValue::String(b)) => a.partial_cmp(b),
113 (ContextValue::Vec(a), ContextValue::Vec(b)) => a.partial_cmp(b),
114 _ => None,
115 }
116 }
117}
118
119impl From<&RenderValue> for ContextValue {
120 fn from(other: &RenderValue) -> ContextValue {
121 match other {
122 RenderValue::String(s) => ContextValue::String(s.clone()),
123 RenderValue::Integer(i) => ContextValue::Integer(*i),
124 RenderValue::Boolean(b) => ContextValue::Boolean(*b),
125 RenderValue::Vec(v) => ContextValue::Vec(v.iter().map(|e| e.into()).collect()),
126 RenderValue::Object(o) => ContextValue::Object(RenderContext(o.iter().map(|(k, v)| (k.clone(), v.into())).collect())),
127 RenderValue::Template(t) => ContextValue::Template(t.clone()),
128 RenderValue::Empty => ContextValue::String("".into()),
129 }
130 }
131}
132
133impl From<RenderValue> for ContextValue {
134 fn from(other: RenderValue) -> ContextValue {
135 match other {
136 RenderValue::String(s) => ContextValue::String(s.clone()),
137 RenderValue::Integer(i) => ContextValue::Integer(i),
138 RenderValue::Boolean(b) => ContextValue::Boolean(b),
139 RenderValue::Vec(v) => ContextValue::Vec(v.iter().map(|e| e.into()).collect()),
140 RenderValue::Object(o) => ContextValue::Object(RenderContext(o.iter().map(|(k, v)| (k.clone(), v.into())).collect())),
141 RenderValue::Template(t) => ContextValue::Template(t),
142 RenderValue::Empty => ContextValue::String("".into()),
143 }
144 }
145}
146
147
148#[derive(Default, Clone, Debug)]
149pub struct RenderContext(pub(crate) BTreeMap<String, ContextValue>);
150
151
152impl RenderContext {
153 pub fn builder() -> RenderContextBuilder {
154 RenderContextBuilder::default()
155 }
156
157 pub fn insert<K, V>(&mut self, key: K, value: V)
158 where
159 K: std::convert::Into<String>,
160 V: std::convert::Into<ContextValue>,
161 {
162 self.0.insert(key.into().trim_start_matches('$').into(), value.into());
163 }
164
165 pub fn get<K>(&self, key: K) -> Option<&ContextValue>
166 where
167 K: std::convert::Into<String>,
168 {
169 self.0.get(key.into().trim_start_matches('$'))
170 }
171}
172
173
174#[derive(Default, Clone)]
175pub struct RenderContextBuilder(pub(crate) BTreeMap<String, ContextValue>);
176
177impl RenderContextBuilder {
178 pub fn insert<K, V>(mut self, key: K, value: V) -> Self
179 where
180 K: std::convert::Into<String>,
181 V: std::convert::Into<ContextValue>,
182 {
183 self.0.insert(key.into(), value.into());
184 self
185 }
186
187 pub fn build(self) -> RenderContext {
188 RenderContext(self.0)
189 }
190}