1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
mod template;
mod runtime;
mod engine;
use std::fmt;
use std::result;
pub use self::template::{ TemplateError, Received };
pub use self::runtime::{ RuntimeError, TracedRuntimeError, CastTarget, CastError };
pub use self::engine::{ EngineError };
#[derive(Clone, Debug)]
pub enum Error {
Template(At<TemplateError>),
Engine(Caused<EngineError>),
Runtime(TracedRuntimeError),
}
pub trait ExtensionError: fmt::Display {
fn boxed_clone(&self) -> Box<ExtensionError>;
}
impl Clone for Box<ExtensionError> {
fn clone(&self) -> Box<ExtensionError> {
self.boxed_clone()
}
}
impl fmt::Debug for Box<ExtensionError> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
(&**self).fmt(f)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Template(ref e) => e.fmt(f),
Error::Engine(ref e) => e.fmt(f),
Error::Runtime(ref e) => e.fmt(f),
}
}
}
#[derive(Clone, Debug)]
pub struct Caused<E: fmt::Display> {
pub err: E,
pub cause: Box<Option<Error>>,
}
impl<E: fmt::Display> Caused<E> {
pub fn new(err: E, cause: Option<Error>) -> Caused<E> {
Caused {
err: err,
cause: Box::new(cause),
}
}
}
impl<E: fmt::Display> fmt::Display for Caused<E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self.cause {
None => self.err.fmt(f),
Some(ref cause) => {
write!(f, "{}\ncaused by\n{}", self.err, cause)
},
}
}
}
#[derive(Copy, Clone, Debug)]
pub struct At<E: fmt::Display> {
pub loc: Location,
pub err: E,
}
impl<E: fmt::Display> At<E> {
pub fn new(err: E, loc: Location) -> At<E> {
At {
loc: loc,
err: err,
}
}
}
impl<E: fmt::Display> fmt::Display for At<E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let message = {
let raw_message = format!("{}", self.err);
let ends_with_dot = {
let len = raw_message.len();
if len > 0 {
if &raw_message[len - 1 ..] == "." {
true
} else {
false
}
} else {
false
}
};
if ends_with_dot {
let len = raw_message.len();
let without_dot = &raw_message[0 .. len - 1];
format!("{} at line {}.", without_dot, self.loc.line)
} else {
format!("{} at line {}", raw_message, self.loc.line)
}
};
write!(f, "{}", message)
}
}
#[derive(Debug, Copy, Clone)]
pub struct Location {
pub line: usize,
}
impl Location {
pub fn new(line: usize) -> Location {
Location { line: line }
}
}
pub type Result<T> = result::Result<T, Error>;
pub type TemplateResult<T> = result::Result<T, At<TemplateError>>;
pub type RuntimeResult<T> = result::Result<T, RuntimeError>;
pub type TracedRuntimeResult<T> = result::Result<T, RuntimeError>;