1use std::result::Result;
5use ::rdll::*;
6use std::error::*;
7use std::result::Result::Err;
8pub type RResult<T> = Result<T, RError>;
9pub type SEXPResult = RResult<SEXP>;
10use self::REKind::*;
11use std::fmt;
12use std::convert::From;
13use util::*;
14use ::protect::stackp::*;
15
16use ::traits::*;
17
18use ::rtype::*;
19
20
21#[derive(Debug)]
22pub struct RError {
23 pub kind: REKind,
24}
25
26macro_rules! gen_fmt {
27 ($($x:ident),*) => (
28
29 impl fmt::Display for RError{
30 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
31 match *self.kind() {
32 UnknownError(ref info) => write!(fmt,"UnknownError: {}",info),
33 UnreachableError(ref info) => write!(fmt,"UnreachableError: {}",info),
34 ForceStopError(ref info) => write!(fmt,"ForceStopError: {}",info),
35 Other(ref c) => write!(fmt, "rustr error: {}",c.to_string()),
36 $($x(ref c) => write!(fmt, "{}: {}", stringify!($x), c.to_string()))
37 ,*
38
39 }
40
41 }
42 }
43
44 impl RError {
45 pub fn kind_info(&self) -> &str {
46 match *self.kind() {
47 UnknownError(..) => "UnknownError",
48 UnreachableError(..) => "UnreachableError",
49 ForceStopError(..) => "ForceStopError",
50 Other(ref c) => c.description(),
51 $($x(..) => stringify!($x))
52 ,*
53 }
54 }
55 }
56
57 impl Error for RError {
58
59 fn description(&self) -> &str {
60 match *self.kind() {
61 UnknownError(..) => "UnknownError",
62 UnreachableError(..) => "UnreachableError",
63 ForceStopError(..) => "ForceStopError",
64 Other(ref c) => c.description(),
65 $($x(ref c) => c.description())
66 ,*
67
68 }
69
70 }
71
72 fn cause(&self) -> Option<&dyn Error> {
73 match *self.kind() {
74 UnknownError(..) => None,
75 UnreachableError(..) => None,
76 ForceStopError(..) => None,
77 Other(ref c) => c.source(),
78 $($x(ref c))
79 |* => c.source(),
80 }
81
82 }
83 }
84
85 #[derive(Debug)]
86 pub enum REKind{
87 $($x(Box<dyn Error+Send+Sync>)),*
88 ,UnknownError(String), UnreachableError(String), ForceStopError(String),Other(Box<dyn Error+Send+Sync>)
89
90 }
91 )
92}
93
94gen_fmt!(Interrupted,
95 NotAMatrix,
96 IndexOutOfBounds,
97 ParseError,
98 NotS4,
99 NotReference,
100 NotInitialized,
101 NoSuchSlot,
102 NoSuchField,
103 NotAClosure,
104 NoSuchFunction,
105 UnevaluatedPromise,
106 NoSuchEnv,
107 FileIoError,
108 FileNotFound,
109 FileExists,
110 NotCompatible,
111 S4CreationError,
112 ReferenceCreationError,
113 NoSuchBinding,
114 BindingNotFound,
115 BindingIsLocked,
116 NoSuchNamespace,
117 FunctionNotExported,
118 EvalError);
119
120
121impl From<::std::ffi::NulError> for RError {
122 fn from(x: ::std::ffi::NulError) -> Self {
123 RError::new(REKind::Other(x.into()))
124 }
125}
126
127
128impl RError {
129 #[inline]
139 pub fn new(kind_: REKind) -> RError {
140 RError { kind: kind_ }
141 }
142 #[inline]
143 pub fn unknown(x: String) -> RError {
144 RError { kind: REKind::UnknownError(x) }
145 }
146 #[inline]
147 pub fn forcestop(x: String) -> RError {
148 RError { kind: REKind::ForceStopError(x) }
149 }
150 #[inline]
151 pub fn unreachable(x: String) -> RError {
152 RError { kind: REKind::UnreachableError(x) }
153 }
154 #[inline]
155 pub fn other<E>(x: E) -> RError
156 where E: Into<Box<dyn Error + Send + Sync>>
157 {
158 RError { kind: REKind::Other(x.into()) }
159 }
160 pub fn kind(&self) -> &REKind {
161 &(self.kind)
162 }
163}
164
165
166#[inline]
167pub fn rraise<T, E>(error: E) -> RResult<T>
168 where E: Into<Box<dyn Error + Send + Sync>>
169{
170
171 Err(RError::other(error))
172
173}
174
175#[inline]
176pub fn rerror<T>(kind_: REKind) -> RResult<T> {
177 Err(RError { kind: kind_ })
178}
179
180#[inline]
181pub fn rerr<T, E>(x: E) -> RResult<T>
182 where E: Into<Box<dyn Error + Send + Sync>>
183{
184 Err(RError { kind: REKind::Other(x.into()) })
185}
186
187pub fn get_current_call() -> SEXP {
188 unsafe {
189 let sys_calls_symbol = Rf_install(c_str("sys.calls").as_ptr());
190 let sys_calls_expr = Shield::new(Rf_lang1(sys_calls_symbol));
191 let calls = Shield::new(Rf_eval(sys_calls_expr.s(), R_GlobalEnv));
192 let mut res = calls.s();
193 while CDR(res) != R_NilValue {
194 res = CDR(res);
195 }
196 CAR(res)
197 }
198
199}
200
201pub fn get_exception_classes(ex: &RError) -> SEXP {
202 unsafe {
203
204 let kind_info_c = c_str(ex.kind_info());
205
206 let res = Shield::new(Rf_allocVector(STRSXP as ::std::os::raw::c_uint, 4));
207 SET_STRING_ELT(res.s(), 0, Rf_mkChar(kind_info_c.as_ptr()));
208 SET_STRING_ELT(res.s(), 1, Rf_mkChar(c_str("RustError").as_ptr()));
209 SET_STRING_ELT(res.s(), 2, Rf_mkChar(c_str("error").as_ptr()));
210 SET_STRING_ELT(res.s(), 3, Rf_mkChar(c_str("condition").as_ptr()));
211 res.s()
212 }
213
214}
215
216pub fn error_to_r_condition(x: RError) -> SEXP {
217 unsafe {
219 let class_sym = Shield::new(get_exception_classes(&x));
220
221 let cond = Shield::new(Rf_allocVector(VECSXP as ::std::os::raw::c_uint, 2));
222
223 let mess_c = c_str(format!("{}", x).as_ref());
224
225 let message = Shield::new(Rf_mkString(mess_c.as_ptr()));
226
227 SET_VECTOR_ELT(cond.s(), 0, message.s());
228 SET_VECTOR_ELT(cond.s(), 1, get_current_call());
229
230 let names = Shield::new(Rf_allocVector(STRSXP, 2));
231
232 SET_STRING_ELT(names.s(), 0, Rf_mkChar(c_str("message").as_ptr()));
233 SET_STRING_ELT(names.s(), 1, Rf_mkChar(c_str("call").as_ptr()));
234
235 Rf_setAttrib(cond.s(), R_NamesSymbol, names.s());
236 Rf_setAttrib(cond.s(), R_ClassSymbol, class_sym.s());
237
238 cond.s()
239 }
240
241}
242
243pub fn forward_exception_to_r(ex: RError) -> SEXP {
244 unsafe {
245
246 let stop_sym = cstr_sym("stop");
247 let condition = Shield::new(error_to_r_condition(ex));
248
249 let expr = Shield::new(Rf_lang2(stop_sym, condition.s()));
250
251 Rf_eval(expr.s(), R_GlobalEnv);
252 R_NilValue
253 }
254}
255
256
257impl From<::std::ffi::IntoStringError> for RError {
261 fn from(x: ::std::ffi::IntoStringError) -> RError {
262 RError::new(REKind::Other(x.into()))
263 }
264}