1use std::fmt;
8
9#[derive(Debug)]
14pub enum RenderError {
15 TemplateError(String),
17
18 TemplateNotFound(String),
20
21 SerializationError(String),
23
24 StyleError(String),
26
27 IoError(std::io::Error),
29
30 OperationError(String),
32
33 ContextError(String),
35}
36
37impl fmt::Display for RenderError {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 match self {
40 RenderError::TemplateError(msg) => write!(f, "template error: {}", msg),
41 RenderError::TemplateNotFound(name) => write!(f, "template not found: {}", name),
42 RenderError::SerializationError(msg) => write!(f, "serialization error: {}", msg),
43 RenderError::StyleError(msg) => write!(f, "style error: {}", msg),
44 RenderError::IoError(err) => write!(f, "I/O error: {}", err),
45 RenderError::OperationError(msg) => write!(f, "{}", msg),
46 RenderError::ContextError(msg) => write!(f, "context error: {}", msg),
47 }
48 }
49}
50
51impl std::error::Error for RenderError {
52 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
53 match self {
54 RenderError::IoError(err) => Some(err),
55 _ => None,
56 }
57 }
58}
59
60impl From<std::io::Error> for RenderError {
61 fn from(err: std::io::Error) -> Self {
62 RenderError::IoError(err)
63 }
64}
65
66impl From<serde_json::Error> for RenderError {
67 fn from(err: serde_json::Error) -> Self {
68 RenderError::SerializationError(err.to_string())
69 }
70}
71
72impl From<serde_yaml::Error> for RenderError {
73 fn from(err: serde_yaml::Error) -> Self {
74 RenderError::SerializationError(err.to_string())
75 }
76}
77
78impl From<quick_xml::DeError> for RenderError {
79 fn from(err: quick_xml::DeError) -> Self {
80 RenderError::SerializationError(err.to_string())
81 }
82}
83
84impl From<csv::Error> for RenderError {
85 fn from(err: csv::Error) -> Self {
86 RenderError::SerializationError(err.to_string())
87 }
88}
89
90impl From<csv::IntoInnerError<csv::Writer<Vec<u8>>>> for RenderError {
91 fn from(err: csv::IntoInnerError<csv::Writer<Vec<u8>>>) -> Self {
92 RenderError::SerializationError(err.to_string())
93 }
94}
95
96impl From<std::string::FromUtf8Error> for RenderError {
97 fn from(err: std::string::FromUtf8Error) -> Self {
98 RenderError::SerializationError(err.to_string())
99 }
100}
101
102impl From<minijinja::Error> for RenderError {
104 fn from(err: minijinja::Error) -> Self {
105 use minijinja::ErrorKind;
106
107 match err.kind() {
108 ErrorKind::TemplateNotFound => RenderError::TemplateNotFound(err.to_string()),
109 ErrorKind::SyntaxError
110 | ErrorKind::BadEscape
111 | ErrorKind::UndefinedError
112 | ErrorKind::UnknownTest
113 | ErrorKind::UnknownFunction
114 | ErrorKind::UnknownFilter
115 | ErrorKind::UnknownMethod => RenderError::TemplateError(err.to_string()),
116 ErrorKind::BadSerialization => RenderError::SerializationError(err.to_string()),
117 _ => RenderError::OperationError(err.to_string()),
118 }
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125
126 #[test]
127 fn test_error_display() {
128 let err = RenderError::TemplateNotFound("foo".to_string());
129 assert!(err.to_string().contains("template not found"));
130 assert!(err.to_string().contains("foo"));
131 }
132
133 #[test]
134 fn test_from_io_error() {
135 let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "file not found");
136 let render_err: RenderError = io_err.into();
137 assert!(matches!(render_err, RenderError::IoError(_)));
138 }
139
140 #[test]
141 fn test_from_minijinja_template_not_found() {
142 let mj_err = minijinja::Error::new(
143 minijinja::ErrorKind::TemplateNotFound,
144 "template 'foo' not found",
145 );
146 let render_err: RenderError = mj_err.into();
147 assert!(matches!(render_err, RenderError::TemplateNotFound(_)));
148 }
149}