Coverage Report

Created: 2025-10-29 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tinytemplate-1.2.1/src/error.rs
Line
Count
Source
1
//! Module containing the error type returned by TinyTemplate if an error occurs.
2
3
use instruction::{path_to_str, PathSlice};
4
use serde_json::Error as SerdeJsonError;
5
use serde_json::Value;
6
use std::error::Error as StdError;
7
use std::fmt;
8
9
/// Enum representing the potential errors that TinyTemplate can encounter.
10
#[derive(Debug)]
11
pub enum Error {
12
    ParseError {
13
        msg: String,
14
        line: usize,
15
        column: usize,
16
    },
17
    RenderError {
18
        msg: String,
19
        line: usize,
20
        column: usize,
21
    },
22
    SerdeError {
23
        err: SerdeJsonError,
24
    },
25
    GenericError {
26
        msg: String,
27
    },
28
    StdFormatError {
29
        err: fmt::Error,
30
    },
31
    CalledTemplateError {
32
        name: String,
33
        err: Box<Error>,
34
        line: usize,
35
        column: usize,
36
    },
37
    CalledFormatterError {
38
        name: String,
39
        err: Box<Error>,
40
        line: usize,
41
        column: usize,
42
    },
43
44
    #[doc(hidden)]
45
    __NonExhaustive,
46
}
47
impl From<SerdeJsonError> for Error {
48
0
    fn from(err: SerdeJsonError) -> Error {
49
0
        Error::SerdeError { err }
50
0
    }
51
}
52
impl From<fmt::Error> for Error {
53
0
    fn from(err: fmt::Error) -> Error {
54
0
        Error::StdFormatError { err }
55
0
    }
56
}
57
impl fmt::Display for Error {
58
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
59
0
        match self {
60
0
            Error::ParseError { msg, line, column } => write!(
61
0
                f,
62
0
                "Failed to parse the template (line {}, column {}). Reason: {}",
63
                line, column, msg
64
            ),
65
0
            Error::RenderError { msg, line, column } => {
66
0
                write!(
67
0
                    f,
68
0
                    "Encountered rendering error on line {}, column {}. Reason: {}",
69
                    line, column, msg
70
                )
71
            }
72
0
            Error::SerdeError { err } => {
73
0
                write!(f, "Unexpected serde error while converting the context to a serde_json::Value. Error: {}", err)
74
            }
75
0
            Error::GenericError { msg } => {
76
0
                write!(f, "{}", msg)
77
            }
78
0
            Error::StdFormatError { err } => {
79
0
                write!(f, "Unexpected formatting error: {}", err)
80
            }
81
            Error::CalledTemplateError {
82
0
                name,
83
0
                err,
84
0
                line,
85
0
                column,
86
            } => {
87
0
                write!(
88
0
                    f,
89
0
                    "Call to sub-template \"{}\" on line {}, column {} failed. Reason: {}",
90
                    name, line, column, err
91
                )
92
            }
93
            Error::CalledFormatterError {
94
0
                name,
95
0
                err,
96
0
                line,
97
0
                column,
98
            } => {
99
0
                write!(
100
0
                    f,
101
0
                    "Call to value formatter \"{}\" on line {}, column {} failed. Reason: {}",
102
                    name, line, column, err
103
                )
104
            }
105
0
            Error::__NonExhaustive => unreachable!(),
106
        }
107
0
    }
108
}
109
impl StdError for Error {
110
0
    fn description(&self) -> &str {
111
0
        match self {
112
0
            Error::ParseError { .. } => "ParseError",
113
0
            Error::RenderError { .. } => "RenderError",
114
0
            Error::SerdeError { .. } => "SerdeError",
115
0
            Error::GenericError { msg } => &msg,
116
0
            Error::StdFormatError { .. } => "StdFormatError",
117
0
            Error::CalledTemplateError { .. } => "CalledTemplateError",
118
0
            Error::CalledFormatterError { .. } => "CalledFormatterError",
119
0
            Error::__NonExhaustive => unreachable!(),
120
        }
121
0
    }
122
}
123
124
pub type Result<T> = ::std::result::Result<T, Error>;
125
126
0
pub(crate) fn lookup_error(source: &str, step: &str, path: PathSlice, current: &Value) -> Error {
127
0
    let avail_str = if let Value::Object(object_map) = current {
128
0
        let mut avail_str = " Available values at this level are ".to_string();
129
0
        for (i, key) in object_map.keys().enumerate() {
130
0
            if i > 0 {
131
0
                avail_str.push_str(", ");
132
0
            }
133
0
            avail_str.push('\'');
134
0
            avail_str.push_str(key);
135
0
            avail_str.push('\'');
136
        }
137
0
        avail_str
138
    } else {
139
0
        "".to_string()
140
    };
141
142
0
    let (line, column) = get_offset(source, step);
143
144
0
    Error::RenderError {
145
0
        msg: format!(
146
0
            "Failed to find value '{}' from path '{}'.{}",
147
0
            step,
148
0
            path_to_str(path),
149
0
            avail_str
150
0
        ),
151
0
        line,
152
0
        column,
153
0
    }
154
0
}
155
156
0
pub(crate) fn truthiness_error(source: &str, path: PathSlice) -> Error {
157
0
    let (line, column) = get_offset(source, path.last().unwrap());
158
0
    Error::RenderError {
159
0
        msg: format!(
160
0
            "Path '{}' produced a value which could not be checked for truthiness.",
161
0
            path_to_str(path)
162
0
        ),
163
0
        line,
164
0
        column,
165
0
    }
166
0
}
167
168
0
pub(crate) fn unprintable_error() -> Error {
169
0
    Error::GenericError {
170
0
        msg: "Expected a printable value but found array or object.".to_string(),
171
0
    }
172
0
}
173
174
0
pub(crate) fn not_iterable_error(source: &str, path: PathSlice) -> Error {
175
0
    let (line, column) = get_offset(source, path.last().unwrap());
176
0
    Error::RenderError {
177
0
        msg: format!(
178
0
            "Expected an array for path '{}' but found a non-iterable value.",
179
0
            path_to_str(path)
180
0
        ),
181
0
        line,
182
0
        column,
183
0
    }
184
0
}
185
186
0
pub(crate) fn unknown_template(source: &str, name: &str) -> Error {
187
0
    let (line, column) = get_offset(source, name);
188
0
    Error::RenderError {
189
0
        msg: format!("Tried to call an unknown template '{}'", name),
190
0
        line,
191
0
        column,
192
0
    }
193
0
}
194
195
0
pub(crate) fn unknown_formatter(source: &str, name: &str) -> Error {
196
0
    let (line, column) = get_offset(source, name);
197
0
    Error::RenderError {
198
0
        msg: format!("Tried to call an unknown formatter '{}'", name),
199
0
        line,
200
0
        column,
201
0
    }
202
0
}
203
204
0
pub(crate) fn called_template_error(source: &str, template_name: &str, err: Error) -> Error {
205
0
    let (line, column) = get_offset(source, template_name);
206
0
    Error::CalledTemplateError {
207
0
        name: template_name.to_string(),
208
0
        err: Box::new(err),
209
0
        line,
210
0
        column,
211
0
    }
212
0
}
213
214
0
pub(crate) fn called_formatter_error(source: &str, formatter_name: &str, err: Error) -> Error {
215
0
    let (line, column) = get_offset(source, formatter_name);
216
0
    Error::CalledFormatterError {
217
0
        name: formatter_name.to_string(),
218
0
        err: Box::new(err),
219
0
        line,
220
0
        column,
221
0
    }
222
0
}
223
224
/// Find the line number and column of the target string within the source string. Will panic if
225
/// target is not a substring of source.
226
0
pub(crate) fn get_offset(source: &str, target: &str) -> (usize, usize) {
227
0
    let offset = target.as_ptr() as isize - source.as_ptr() as isize;
228
0
    let to_scan = &source[0..(offset as usize)];
229
230
0
    let mut line = 1;
231
0
    let mut column = 0;
232
233
0
    for byte in to_scan.bytes() {
234
0
        match byte as char {
235
0
            '\n' => {
236
0
                line += 1;
237
0
                column = 0;
238
0
            }
239
0
            _ => {
240
0
                column += 1;
241
0
            }
242
        }
243
    }
244
245
0
    (line, column)
246
0
}