1use serde::Serialize;
4use serde_json;
5
6pub struct ForgeContext {
9 inner: tera::Context,
10}
11
12impl ForgeContext {
13 pub fn new() -> Self {
14 Self {
15 inner: tera::Context::new(),
16 }
17 }
18
19 pub fn insert<T: Serialize + ?Sized>(mut self, key: &str, value: &T) -> Self {
21 self.inner.insert(key, value);
22 self
23 }
24
25 pub fn insert_mut<T: Serialize + ?Sized>(&mut self, key: &str, value: &T) {
27 self.inner.insert(key, value);
28 }
29
30 pub fn slot(mut self, name: &str, content: &str) -> Self {
36 let mut current = self
39 .inner
40 .get("__slots__")
41 .and_then(|v| v.as_object().cloned())
42 .unwrap_or_default();
43 current.insert(
44 name.to_string(),
45 serde_json::Value::String(content.to_string()),
46 );
47 self.inner.insert("__slots__", ¤t);
48 self
49 }
50
51 pub fn provide(mut self, key: &str, value: &str) -> Self {
55 let mut current = self
56 .inner
57 .get("__provides__")
58 .and_then(|v| v.as_object().cloned())
59 .unwrap_or_default();
60 current.insert(
61 key.to_string(),
62 serde_json::Value::String(value.to_string()),
63 );
64 self.inner.insert("__provides__", ¤t);
65 self
66 }
67
68 pub(crate) fn provides(&self) -> Option<serde_json::Map<String, serde_json::Value>> {
70 self.inner
71 .get("__provides__")
72 .and_then(|v| v.as_object().cloned())
73 }
74
75 pub(crate) fn slots(&self) -> Option<serde_json::Map<String, serde_json::Value>> {
77 self.inner
78 .get("__slots__")
79 .and_then(|v| v.as_object().cloned())
80 }
81
82 pub fn from_serialize<T: Serialize>(data: &T) -> anyhow::Result<Self> {
84 let inner = tera::Context::from_serialize(data)
85 .map_err(|e| anyhow::anyhow!("Context serialization failed: {e}"))?;
86 Ok(Self { inner })
87 }
88
89 pub(crate) fn as_tera(&self) -> &tera::Context {
90 &self.inner
91 }
92}
93
94impl Default for ForgeContext {
95 fn default() -> Self {
96 Self::new()
97 }
98}