1use serde_json;
2use std::convert::Into;
3use std::error::Error as StdError;
4use std::fmt;
5
6#[derive(Debug)]
8pub enum ErrorKind {
9 Msg(String),
11 CircularExtend {
13 tpl: String,
15 inheritance_chain: Vec<String>,
17 },
18 MissingParent {
20 current: String,
22 parent: String,
24 },
25 TemplateNotFound(String),
27 FilterNotFound(String),
29 TestNotFound(String),
31 InvalidMacroDefinition(String),
33 FunctionNotFound(String),
35 Json(serde_json::Error),
37 #[doc(hidden)]
41 __Nonexhaustive,
42}
43
44#[derive(Debug)]
46pub struct Error {
47 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 pub fn msg(value: impl ToString) -> Self {
86 Self { kind: ErrorKind::Msg(value.to_string()), source: None }
87 }
88
89 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 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 pub fn template_not_found(tpl: impl ToString) -> Self {
110 Self { kind: ErrorKind::TemplateNotFound(tpl.to_string()), source: None }
111 }
112
113 pub fn filter_not_found(name: impl ToString) -> Self {
115 Self { kind: ErrorKind::FilterNotFound(name.to_string()), source: None }
116 }
117
118 pub fn test_not_found(name: impl ToString) -> Self {
120 Self { kind: ErrorKind::TestNotFound(name.to_string()), source: None }
121 }
122
123 pub fn function_not_found(name: impl ToString) -> Self {
125 Self { kind: ErrorKind::FunctionNotFound(name.to_string()), source: None }
126 }
127
128 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 pub fn json(value: serde_json::Error) -> Self {
135 Self { kind: ErrorKind::Json(value), source: None }
136 }
137
138 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}
159pub type Result<T> = ::std::result::Result<T, Error>;