1use std::error;
2use std::fmt::{self, Display};
3
4#[derive(Debug, PartialEq, Eq, Clone, Copy)]
5pub enum RollbackType {
6 Fail = 0,
7 Stop,
8}
9
10#[derive(Debug, PartialEq, Clone)]
12pub struct RollbackRecord {
13 pub name: String,
14 pub position: usize,
15 pub typ: RollbackType,
16 pub inner: Option<Box<Error>>,
17 pub previous_tracks: Vec<RollbackRecord>,
18}
19
20impl RollbackRecord {
21 fn fmt_with_indent(&self, f: &mut fmt::Formatter, indent: usize) -> fmt::Result {
22 let idnt = " ".repeat(indent);
23 match &self.previous_tracks[..] {
24 [] => {}
25 [prev] => prev.fmt_with_indent(f, indent)?,
26 _ => {
27 writeln!(f, "{}Fork: {{", idnt)?;
28 for prev in &self.previous_tracks {
29 writeln!(f, "{}>><<", idnt)?;
30 prev.fmt_with_indent(f, indent + 1)?;
31 }
32 writeln!(f, "{}}}", idnt)?;
33 }
34 }
35 let rollback_type = match self.typ {
36 RollbackType::Fail => "failed",
37 RollbackType::Stop => "stopped",
38 };
39 match &self.inner {
40 Some(ref inner) => writeln!(
41 f,
42 "{}{} {} at {}, (inner: {})",
43 idnt, &self.name, rollback_type, &self.position, inner
44 )?,
45 None => writeln!(
46 f,
47 "{}{} {} at {}",
48 idnt, &self.name, rollback_type, &self.position
49 )?,
50 }
51 Ok(())
52 }
53}
54
55impl Display for RollbackRecord {
56 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
57 self.fmt_with_indent(f, 0)
58 }
59}
60
61#[derive(Debug, PartialEq, Clone)]
63pub enum Error {
64 Incomplete,
65 Mismatch {
66 message: String,
67 position: usize,
68 continuation_error: Option<Box<Error>>,
69 },
70 Conversion {
71 message: String,
72 position: usize,
73 },
74 Expect {
75 message: String,
76 position: usize,
77 inner: Box<Error>,
78 },
79 Custom {
80 message: String,
81 position: usize,
82 inner: Option<Box<Error>>,
83 },
84 Rollback {
85 rollbacks: RollbackRecord,
86 },
87}
88
89impl error::Error for Error {
90 fn description(&self) -> &'static str {
91 "Parse error"
92 }
93}
94
95impl Display for Error {
96 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97 match self {
98 Error::Incomplete => write!(f, "Incomplete"),
99 Error::Mismatch {
100 ref message,
101 ref position,
102 continuation_error: None,
103 } => write!(f, "Mismatch at {}: {}", position, message),
104 Error::Mismatch {
105 ref message,
106 ref position,
107 continuation_error: Some(ref continuation_error),
108 } => write!(
109 f,
110 "Mismatch at {}: {}, (cont. error: {})",
111 position, message, continuation_error
112 ),
113 Error::Conversion {
114 ref message,
115 ref position,
116 } => write!(f, "Conversion failed at {}: {}", position, message),
117 Error::Expect {
118 ref message,
119 ref position,
120 ref inner,
121 } => write!(f, "{} at {}: {}", message, position, inner),
122 Error::Custom {
123 ref message,
124 ref position,
125 inner: Some(ref inner),
126 } => write!(f, "{} at {}, (inner: {})", message, position, inner),
127 Error::Custom {
128 ref message,
129 ref position,
130 inner: None,
131 } => write!(f, "{} at {}", message, position),
132 Error::Rollback { ref rollbacks } => {
133 writeln!(f, "Rollback log:")?;
134 write!(f, "{}", rollbacks)?;
135 Ok(())
136 }
137 }
138 }
139}
140
141pub type Result<O> = ::std::result::Result<O, Error>;