Skip to main content

template/
context.rs

1#[cfg(feature = "std")]
2use serde::ser::Serialize;
3
4#[cfg(feature = "std")]
5use crate::value::to_value;
6use crate::{SerdeError, value::Value};
7
8/// A template rendering context.
9///
10/// Constructed via the [`context!`](crate::context) macro or through the
11/// [`IntoContext`] trait (implemented for all `Serialize` types when the
12/// `std` feature is enabled).
13pub struct Context(pub(crate) Value);
14
15impl From<Context> for Value {
16    fn from(ctx: Context) -> Value {
17        ctx.0
18    }
19}
20
21/// Trait for types that can be converted into a [`Context`] for template rendering.
22///
23/// Implemented for [`Context`] directly and, with the `std` feature, for all
24/// types that implement [`Serialize`](serde::Serialize).
25///
26/// The `std` blanket impl requires the result to be a map-like value
27/// (i.e. [`Value::Map`](crate::value::Value::Map)). Non-map values such as
28/// plain strings or numbers return an error.
29pub trait IntoContext {
30    fn into_context(self) -> Result<Context, SerdeError>;
31}
32
33impl IntoContext for Context {
34    /// Returns itself
35    fn into_context(self) -> Result<Context, SerdeError> {
36        Ok(self)
37    }
38}
39
40#[cfg(feature = "std")]
41impl<T: Serialize + ?Sized> IntoContext for &T {
42    fn into_context(self) -> Result<Context, SerdeError> {
43        let v = to_value(self)?;
44        match v {
45            Value::Map(_) => Ok(Context(v)),
46            _ => Err(SerdeError("context must be a map-like value".into())),
47        }
48    }
49}