]> git.proxmox.com Git - rustc.git/blob - src/vendor/handlebars/src/error.rs
New upstream version 1.31.0+dfsg1
[rustc.git] / src / vendor / handlebars / src / error.rs
1 use std::io::Error as IOError;
2 use std::error::Error;
3 use std::fmt;
4
5 use serde_json::error::Error as SerdeError;
6
7 use template::Parameter;
8
9 /// Error when rendering data on template.
10 #[derive(Debug)]
11 pub struct RenderError {
12 pub desc: String,
13 pub template_name: Option<String>,
14 pub line_no: Option<usize>,
15 pub column_no: Option<usize>,
16 cause: Option<Box<Error + Send + Sync>>,
17 }
18
19 impl fmt::Display for RenderError {
20 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
21 match (self.line_no, self.column_no) {
22 (Some(line), Some(col)) => write!(
23 f,
24 "Error rendering \"{}\" line {}, col {}: {}",
25 self.template_name
26 .as_ref()
27 .unwrap_or(&"Unnamed template".to_owned(),),
28 line,
29 col,
30 self.desc
31 ),
32 _ => write!(f, "{}", self.desc),
33 }
34 }
35 }
36
37 impl Error for RenderError {
38 fn description(&self) -> &str {
39 &self.desc[..]
40 }
41
42 fn cause(&self) -> Option<&Error> {
43 self.cause.as_ref().map(|e| &**e as &Error)
44 }
45 }
46
47 impl From<IOError> for RenderError {
48 fn from(e: IOError) -> RenderError {
49 RenderError::with(e)
50 }
51 }
52
53 impl From<SerdeError> for RenderError {
54 fn from(e: SerdeError) -> RenderError {
55 RenderError::with(e)
56 }
57 }
58
59 impl RenderError {
60 pub fn new<T: AsRef<str>>(desc: T) -> RenderError {
61 RenderError {
62 desc: desc.as_ref().to_owned(),
63 template_name: None,
64 line_no: None,
65 column_no: None,
66 cause: None,
67 }
68 }
69
70 pub fn with<E>(cause: E) -> RenderError
71 where
72 E: Error + Send + Sync + 'static,
73 {
74 let mut e = RenderError::new(cause.description());
75 e.cause = Some(Box::new(cause));
76
77 e
78 }
79 }
80
81 quick_error! {
82 /// Template parsing error
83 #[derive(PartialEq, Debug, Clone)]
84 pub enum TemplateErrorReason {
85 MismatchingClosedHelper(open: String, closed: String) {
86 display("helper {:?} was opened, but {:?} is closing",
87 open, closed)
88 description("wrong name of closing helper")
89 }
90 MismatchingClosedDirective(open: Parameter, closed: Parameter) {
91 display("directive {:?} was opened, but {:?} is closing",
92 open, closed)
93 description("wrong name of closing directive")
94 }
95 InvalidSyntax {
96 display("invalid handlebars syntax.")
97 description("invalid handlebars syntax")
98 }
99 InvalidParam (param: String) {
100 display("invalid parameter {:?}", param)
101 description("invalid parameter")
102 }
103 NestedSubexpression {
104 display("nested subexpression is not supported")
105 description("nested subexpression is not supported")
106 }
107 }
108 }
109
110 /// Error on parsing template.
111 #[derive(Debug, PartialEq)]
112 pub struct TemplateError {
113 pub reason: TemplateErrorReason,
114 pub template_name: Option<String>,
115 pub line_no: Option<usize>,
116 pub column_no: Option<usize>,
117 segment: Option<String>,
118 }
119
120 impl TemplateError {
121 pub fn of(e: TemplateErrorReason) -> TemplateError {
122 TemplateError {
123 reason: e,
124 template_name: None,
125 line_no: None,
126 column_no: None,
127 segment: None,
128 }
129 }
130
131 pub fn at(mut self, template_str: &str, line_no: usize, column_no: usize) -> TemplateError {
132 self.line_no = Some(line_no);
133 self.column_no = Some(column_no);
134 self.segment = Some(template_segment(template_str, line_no, column_no));
135 self
136 }
137
138 pub fn in_template(mut self, name: String) -> TemplateError {
139 self.template_name = Some(name);
140 self
141 }
142 }
143
144 impl Error for TemplateError {
145 fn description(&self) -> &str {
146 self.reason.description()
147 }
148 }
149
150 fn template_segment(template_str: &str, line: usize, col: usize) -> String {
151 let range = 3;
152 let line_start = if line >= range { line - range } else { 0 };
153 let line_end = line + range;
154
155 let mut buf = String::new();
156 for (line_count, line_content) in template_str.lines().enumerate() {
157 if line_count >= line_start && line_count <= line_end {
158 buf.push_str(&format!("{:4} | {}\n", line_count, line_content));
159 if line_count == line - 1 {
160 buf.push_str(" |");
161 for c in 0..line_content.len() {
162 if c != col {
163 buf.push_str("-");
164 } else {
165 buf.push_str("^");
166 }
167 }
168 buf.push_str("\n");
169 }
170 }
171 }
172
173 buf
174 }
175
176 impl fmt::Display for TemplateError {
177 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
178 match (self.line_no, self.column_no, &self.segment) {
179 (Some(line), Some(col), &Some(ref seg)) => write!(
180 f,
181 "Template error: {}\n --> Template error in \"{}\":{}:{}\n |\n{} |\n = reason: {}\n",
182 self.reason,
183 self.template_name
184 .as_ref()
185 .unwrap_or(&"Unnamed template".to_owned()),
186 line,
187 col,
188 seg,
189 self.reason
190 ),
191 _ => write!(f, "{}", self.reason),
192 }
193 }
194 }
195
196 quick_error! {
197 #[derive(Debug)]
198 pub enum TemplateFileError {
199 TemplateError(err: TemplateError) {
200 from()
201 cause(err)
202 description(err.description())
203 display("{}", err)
204 }
205 IOError(err: IOError, name: String) {
206 cause(err)
207 description(err.description())
208 display("Template \"{}\": {}", name, err)
209 }
210 }
211 }
212
213 quick_error! {
214 #[derive(Debug)]
215 pub enum TemplateRenderError {
216 TemplateError(err: TemplateError) {
217 from()
218 cause(err)
219 description(err.description())
220 display("{}", err)
221 }
222 RenderError(err: RenderError) {
223 from()
224 cause(err)
225 description(err.description())
226 display("{}", err)
227 }
228 IOError(err: IOError, name: String) {
229 cause(err)
230 description(err.description())
231 display("Template \"{}\": {}", name, err)
232 }
233 }
234 }
235
236 impl TemplateRenderError {
237 pub fn as_render_error(&self) -> Option<&RenderError> {
238 if let &TemplateRenderError::RenderError(ref e) = self {
239 Some(&e)
240 } else {
241 None
242 }
243 }
244 }