tera_v1/
errors.rs

1use serde_json;
2use std::convert::Into;
3use std::error::Error as StdError;
4use std::fmt;
5
6/// The kind of an error (non-exhaustive)
7#[derive(Debug)]
8pub enum ErrorKind {
9    /// Generic error
10    Msg(String),
11    /// A loop was found while looking up the inheritance chain
12    CircularExtend {
13        /// Name of the template with the loop
14        tpl: String,
15        /// All the parents templates we found so far
16        inheritance_chain: Vec<String>,
17    },
18    /// A template is extending a template that wasn't found in the Tera instance
19    MissingParent {
20        /// The template we are currently looking at
21        current: String,
22        /// The missing template
23        parent: String,
24    },
25    /// A template was missing (more generic version of MissingParent)
26    TemplateNotFound(String),
27    /// A filter wasn't found
28    FilterNotFound(String),
29    /// A test wasn't found
30    TestNotFound(String),
31    /// A macro was defined in a normal template
32    InvalidMacroDefinition(String),
33    /// A function wasn't found
34    FunctionNotFound(String),
35    /// An error happened while serializing JSON
36    Json(serde_json::Error),
37    /// This enum may grow additional variants, so this makes sure clients
38    /// don't count on exhaustive matching. (Otherwise, adding a new variant
39    /// could break existing code.)
40    #[doc(hidden)]
41    __Nonexhaustive,
42}
43
44/// The Error type
45#[derive(Debug)]
46pub struct Error {
47    /// Kind of error
48    pub kind: ErrorKind,
49    source: Option<Box<dyn StdError>>,
50}
51
52impl fmt::Display for Error {
53    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54        match self.kind {
55            ErrorKind::Msg(ref message) => write!(f, "{}", message),
56            ErrorKind::CircularExtend { ref tpl, ref inheritance_chain } => write!(
57                f,
58                "Circular extend detected for template '{}'. Inheritance chain: `{:?}`",
59                tpl, inheritance_chain
60            ),
61            ErrorKind::MissingParent { ref current, ref parent } => write!(
62                f,
63                "Template '{}' is inheriting from '{}', which doesn't exist or isn't loaded.",
64                current, parent
65            ),
66            ErrorKind::TemplateNotFound(ref name) => write!(f, "Template '{}' not found", name),
67            ErrorKind::FilterNotFound(ref name) => write!(f, "Filter '{}' not found", name),
68            ErrorKind::TestNotFound(ref name) => write!(f, "Test '{}' not found", name),
69            ErrorKind::FunctionNotFound(ref name) => write!(f, "Function '{}' not found", name),
70            ErrorKind::InvalidMacroDefinition(ref info) => write!(f, "Invalid macro definition: `{}`", info),
71            ErrorKind::Json(ref e) => write!(f, "{}", e),
72            ErrorKind::__Nonexhaustive => write!(f, "Nonexhaustive"),
73        }
74    }
75}
76
77impl StdError for Error {
78    fn source(&self) -> Option<&(dyn StdError + 'static)> {
79        self.source.as_ref().map(|c| &**c)
80    }
81}
82
83impl Error {
84    /// Creates generic error
85    pub fn msg(value: impl ToString) -> Self {
86        Self { kind: ErrorKind::Msg(value.to_string()), source: None }
87    }
88
89    /// Creates a circular extend error
90    pub fn circular_extend(tpl: impl ToString, inheritance_chain: Vec<String>) -> Self {
91        Self {
92            kind: ErrorKind::CircularExtend { tpl: tpl.to_string(), inheritance_chain },
93            source: None,
94        }
95    }
96
97    /// Creates a missing parent error
98    pub fn missing_parent(current: impl ToString, parent: impl ToString) -> Self {
99        Self {
100            kind: ErrorKind::MissingParent {
101                current: current.to_string(),
102                parent: parent.to_string(),
103            },
104            source: None,
105        }
106    }
107
108    /// Creates a template not found error
109    pub fn template_not_found(tpl: impl ToString) -> Self {
110        Self { kind: ErrorKind::TemplateNotFound(tpl.to_string()), source: None }
111    }
112
113    /// Creates a filter not found error
114    pub fn filter_not_found(name: impl ToString) -> Self {
115        Self { kind: ErrorKind::FilterNotFound(name.to_string()), source: None }
116    }
117
118    /// Creates a test not found error
119    pub fn test_not_found(name: impl ToString) -> Self {
120        Self { kind: ErrorKind::TestNotFound(name.to_string()), source: None }
121    }
122
123    /// Creates a function not found error
124    pub fn function_not_found(name: impl ToString) -> Self {
125        Self { kind: ErrorKind::FunctionNotFound(name.to_string()), source: None }
126    }
127
128    /// Creates generic error with a source
129    pub fn chain(value: impl ToString, source: impl Into<Box<dyn StdError>>) -> Self {
130        Self { kind: ErrorKind::Msg(value.to_string()), source: Some(source.into()) }
131    }
132
133    /// Creates JSON error
134    pub fn json(value: serde_json::Error) -> Self {
135        Self { kind: ErrorKind::Json(value), source: None }
136    }
137
138    /// Creates an invalid macro definition error
139    pub fn invalid_macro_def(name: impl ToString) -> Self {
140        Self { kind: ErrorKind::InvalidMacroDefinition(name.to_string()), source: None }
141    }
142}
143
144impl From<&str> for Error {
145    fn from(e: &str) -> Self {
146        Self::msg(e)
147    }
148}
149impl From<String> for Error {
150    fn from(e: String) -> Self {
151        Self::msg(e)
152    }
153}
154impl From<serde_json::Error> for Error {
155    fn from(e: serde_json::Error) -> Self {
156        Self::json(e)
157    }
158}
159/// Convenient wrapper around std::Result.
160pub type Result<T> = ::std::result::Result<T, Error>;