dvcompute_dist/simulation/
error.rs1use std;
8use std::rc::Rc;
9use std::io;
10use std::ops::Deref;
11use std::fmt;
12use std::convert::From;
13
14#[cfg(feature="dist_mode")]
15use std::ffi::CString;
16
17#[cfg(feature="dist_mode")]
18use std::ffi::CStr;
19
20#[cfg(feature="dist_mode")]
21use std::ptr;
22
23#[cfg(feature="dist_mode")]
24use libc::*;
25
26#[doc(hidden)]
28#[derive(Debug, Clone)]
29pub enum Error {
30
31 Cancel,
33
34 Other(Rc<OtherError>)
36}
37
38#[doc(hidden)]
40#[derive(Debug)]
41pub enum OtherError {
42
43 Retry(String),
45
46 Panic(String),
48
49 IO(io::Error)
51}
52
53#[doc(hidden)]
54impl Error {
55
56 #[inline]
58 pub fn merge(&self, other: &Error) -> Error {
59 match (self, other) {
60 (&Error::Cancel, &Error::Cancel) => {
61 Error::Cancel
62 },
63 (&Error::Cancel, &Error::Other(ref y)) => {
64 match y.deref() {
65 &OtherError::Retry(_) => Error::Other(y.clone()),
66 _ => Error::Cancel
67 }
68 },
69 (&Error::Other(ref x), &Error::Cancel) => {
70 match x.deref() {
71 &OtherError::Retry(_) => Error::Other(x.clone()),
72 _ => Error::Cancel
73 }
74 },
75 (&Error::Other(ref x), &Error::Other(ref y)) => {
76 match (x.deref(), y.deref()) {
77 (&OtherError::Retry(_), _) => Error::Other(x.clone()),
78 (_, &OtherError::Retry(_)) => Error::Other(y.clone()),
79 (_, _) => Error::Other(x.clone())
80 }
81 }
82 }
83 }
84
85 #[inline]
87 pub fn retry(msg: String) -> Self {
88 Error::Other(OtherError::retry(msg))
89 }
90
91 #[inline]
93 pub fn panic(msg: String) -> Self {
94 Error::Other(OtherError::panic(msg))
95 }
96
97 #[inline]
99 pub fn io(err: io::Error) -> Self {
100 Error::Other(OtherError::io(err))
101 }
102}
103
104#[doc(hidden)]
105impl OtherError {
106
107 #[inline]
109 pub fn retry(msg: String) -> Rc<Self> {
110 Rc::new(OtherError::Retry(msg))
111 }
112
113 #[inline]
115 pub fn panic(msg: String) -> Rc<Self> {
116 Rc::new(OtherError::Panic(msg))
117 }
118
119 #[inline]
121 pub fn io(err: io::Error) -> Rc<Self> {
122 Rc::new(OtherError::IO(err))
123 }
124}
125
126impl fmt::Display for Error {
127
128 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
129 match self {
130 &Error::Cancel => write!(f, "Computation was canceled"),
131 &Error::Other(ref x) => x.fmt(f)
132 }
133 }
134}
135
136impl fmt::Display for OtherError {
137
138 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
139 match self {
140 &OtherError::Retry(ref x) => write!(f, "{}", x),
141 &OtherError::Panic(ref x) => write!(f, "{}", x),
142 &OtherError::IO(ref x) => x.fmt(f)
143 }
144 }
145}
146
147impl std::error::Error for Error {}
148
149impl std::error::Error for OtherError {}
150
151impl From<io::Error> for Error {
152
153 fn from(e: io::Error) -> Error {
154 Error::io(e)
155 }
156}
157
158#[cfg(feature="dist_mode")]
160const CANCEL_STATUS: c_int = 1;
161
162#[cfg(feature="dist_mode")]
164const RETRY_STATUS: c_int = 2;
165
166#[cfg(feature="dist_mode")]
168const PANIC_STATUS: c_int = 3;
169
170#[cfg(feature="dist_mode")]
172const IO_ERROR_STATUS: c_int = 4;
173
174#[cfg(feature="dist_mode")]
176#[repr(C)]
177pub struct ErrorRepr {
178
179 status: c_int,
181
182 message: *mut c_char,
184
185 delete_message: unsafe extern "C" fn(*mut c_char),
187
188 delete_error_repr: unsafe extern "C" fn(*mut ErrorRepr)
190}
191
192#[cfg(feature="dist_mode")]
193impl Drop for ErrorRepr {
194
195 fn drop(&mut self) {
196 unsafe {
197 (self.delete_message)(self.message);
198 }
199 }
200}
201
202#[cfg(feature="dist_mode")]
203impl ErrorRepr {
204
205 pub fn new(e: Error) -> Self {
207 let (status, message) = {
208 match e {
209 Error::Cancel => (CANCEL_STATUS, ptr::null_mut()),
210 Error::Other(x) => {
211 match x.deref() {
212 &OtherError::Retry(ref x) => {
213 let message = x.clone();
214 let message = CString::new(message).expect("NulError");
215 let message = CString::into_raw(message);
216 (RETRY_STATUS, message)
217 },
218 &OtherError::Panic(ref x) => {
219 let message = x.clone();
220 let message = CString::new(message).expect("NulError");
221 let message = CString::into_raw(message);
222 (PANIC_STATUS, message)
223 }
224 &OtherError::IO(ref x) => {
225 let message = format!("{}", x);
226 let message = CString::new(message).expect("NulError");
227 let message = CString::into_raw(message);
228 (IO_ERROR_STATUS, message)
229 }
230 }
231 }
232 }
233 };
234
235 ErrorRepr {
236 status: status,
237 message: message,
238 delete_message: delete_error_message,
239 delete_error_repr: delete_error_repr
240 }
241 }
242}
243
244#[cfg(feature="dist_mode")]
245unsafe extern "C" fn delete_error_message(message: *mut c_char) {
246 if message != ptr::null_mut() {
247 let _ = CString::from_raw(message);
248 }
249}
250
251#[cfg(feature="dist_mode")]
252unsafe extern "C" fn delete_error_repr(e: *mut ErrorRepr) {
253 if e != ptr::null_mut() {
254 let _ = Box::from_raw(e);
255 }
256}
257
258#[cfg(feature="dist_mode")]
260pub unsafe fn ffi_error_repr_into_error(e: *mut ErrorRepr) -> Error {
261 if (*e).status == CANCEL_STATUS {
262 ((*e).delete_error_repr)(e);
263 Error::Cancel
264 } else {
265 let message = CStr::from_ptr((*e).message);
266 let message = message.to_bytes().to_vec();
267 let message = String::from_utf8(message).expect("FromUtf8Error");
268 let status = (*e).status;
269 ((*e).delete_error_repr)(e);
270 match status {
271 RETRY_STATUS => {
272 Error::Other(Rc::new(OtherError::Retry(message)))
273 },
274 PANIC_STATUS => {
275 Error::Other(Rc::new(OtherError::Panic(message)))
276 },
277 IO_ERROR_STATUS => {
278 let e = io::Error::new(io::ErrorKind::Other, message);
279 Error::Other(Rc::new(OtherError::IO(e)))
280 },
281 x => {
282 panic!("Unexpected error status: {}", x);
283 }
284 }
285 }
286}