liquid_core/error/
error.rs1use std::error;
2use std::fmt;
3use std::result;
4
5use super::ErrorClone;
6use super::Trace;
7
8pub type Result<T, E = Error> = result::Result<T, E>;
10
11type BoxedError = Box<dyn ErrorClone>;
12
13#[derive(Debug, Clone)]
15pub struct Error {
16 inner: Box<InnerError>,
17}
18
19#[derive(Debug, Clone)]
24struct InnerError {
25 msg: crate::model::KString,
26 user_backtrace: Vec<Trace>,
27 cause: Option<BoxedError>,
28}
29
30impl Error {
31 pub fn with_msg<S: Into<crate::model::KString>>(msg: S) -> Self {
33 Self::with_msg_cow(msg.into())
34 }
35
36 fn with_msg_cow(msg: crate::model::KString) -> Self {
37 let error = InnerError {
38 msg,
39 user_backtrace: vec![Trace::empty()],
40 cause: None,
41 };
42 Self {
43 inner: Box::new(error),
44 }
45 }
46
47 pub fn trace<T>(self, trace: T) -> Self
49 where
50 T: Into<crate::model::KString>,
51 {
52 self.trace_trace(trace.into())
53 }
54
55 fn trace_trace(mut self, trace: crate::model::KString) -> Self {
56 let trace = Trace::new(trace);
57 self.inner.user_backtrace.push(trace);
58 self
59 }
60
61 pub fn context<K, V>(self, key: K, value: V) -> Self
65 where
66 K: Into<crate::model::KString>,
67 V: Into<crate::model::KString>,
68 {
69 self.context_cow_string(key.into(), value.into())
70 }
71
72 fn context_cow_string(
73 mut self,
74 key: crate::model::KString,
75 value: crate::model::KString,
76 ) -> Self {
77 self.inner
78 .user_backtrace
79 .last_mut()
80 .expect("always a trace available")
81 .append_context(key, value);
82 self
83 }
84
85 pub fn cause<E: ErrorClone>(self, cause: E) -> Self {
87 let cause = Box::new(cause);
88 self.cause_error(cause)
89 }
90
91 fn cause_error(mut self, cause: BoxedError) -> Self {
92 let cause = Some(cause);
93 self.inner.cause = cause;
94 self
95 }
96
97 pub fn into_err<T, E>(self) -> ::std::result::Result<T, E>
99 where
100 Self: Into<E>,
101 {
102 let err = self.into();
103 Err(err)
104 }
105}
106
107const ERROR_DESCRIPTION: &str = "liquid";
108
109impl fmt::Display for Error {
110 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
111 writeln!(f, "{}: {}", ERROR_DESCRIPTION, self.inner.msg)?;
112 for trace in &self.inner.user_backtrace {
113 if let Some(trace) = trace.get_trace() {
114 writeln!(f, "from: {}", trace)?;
115 }
116 if !trace.get_context().is_empty() {
117 writeln!(f, " with:")?;
118 }
119 for (key, value) in trace.get_context() {
120 writeln!(f, " {}={}", key, value)?;
121 }
122 }
123 Ok(())
124 }
125}
126
127impl error::Error for Error {
128 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
129 self.inner.cause.as_ref().and_then(|e| e.source())
130 }
131}