1use std::convert::Infallible;
4
5use crate::conversions::try_into_int::ConversionError;
6use crate::robj::Types;
7use crate::{throw_r_error, Robj};
8use extendr_ffi::ParseStatus;
9
10#[doc(hidden)]
12pub fn unwrap_or_throw<T>(r: std::result::Result<T, &'static str>) -> T {
13 match r {
14 Err(e) => {
15 throw_r_error(e);
16 }
17 Ok(v) => v,
18 }
19}
20
21#[doc(hidden)]
22pub fn unwrap_or_throw_error<T>(r: std::result::Result<T, Error>) -> T {
23 match r {
24 Err(e) => {
25 throw_r_error(e.to_string());
26 }
27 Ok(v) => v,
28 }
29}
30
31#[derive(Debug, PartialEq)]
32pub enum Error {
33 Panic(Robj),
34 NotFound(Robj),
35 EvalError(Robj),
36 ParseError {
37 status: ParseStatus,
38 code: Robj,
39 },
40 NamesLengthMismatch(Robj),
41
42 ExpectedNull(Robj),
43 ExpectedSymbol(Robj),
44 ExpectedPairlist(Robj),
45 ExpectedFunction(Robj),
46 ExpectedEnvironment(Robj),
47 ExpectedPromise(Robj),
48 ExpectedLanguage(Robj),
49 ExpectedSpecial(Robj),
50 ExpectedBuiltin(Robj),
51 ExpectedRstr(Robj),
52 ExpectedLogical(Robj),
53 ExpectedInteger(Robj),
54 ExpectedReal(Robj),
55 ExpectedComplex(Robj),
56 ExpectedString(Robj),
57 ExpectedDot(Robj),
58 ExpectedAny(Robj),
59 ExpectedList(Robj),
60 ExpectedExpression(Robj),
61 ExpectedBytecode(Robj),
62 ExpectedExternalPtr(Robj),
63 ExpectedWeakRef(Robj),
64 ExpectedRaw(Robj),
65 ExpectedS4(Robj),
66 ExpectedPrimitive(Robj),
67
68 ExpectedScalar(Robj),
69 ExpectedVector(Robj),
70 ExpectedMatrix(Robj),
71 ExpectedMatrix3D(Robj),
72 ExpectedMatrix4D(Robj),
73 ExpectedMatrix5D(Robj),
74 ExpectedNumeric(Robj),
75 ExpectedAltrep(Robj),
76 ExpectedDataframe(Robj),
77
78 OutOfRange(Robj),
79 MustNotBeNA(Robj),
80 ExpectedWholeNumber(Robj, ConversionError),
81 ExpectedNonZeroLength(Robj),
82 ExpectedLength(usize),
83 OutOfLimits(Robj),
84 TypeMismatch(Robj),
85 NamespaceNotFound(Robj),
86 NoGraphicsDevices(Robj),
87
88 ExpectedExternalPtrType(Robj, String),
89 ExpectedExternalNonNullPtr(Robj),
90 ExpectedExternalPtrReference,
91 Other(String),
92
93 #[cfg(feature = "ndarray")]
94 NDArrayShapeError(ndarray::ShapeError),
95
96 #[cfg(feature = "either")]
97 EitherError(Box<Error>, Box<Error>),
98 TryFromSliceError(String),
100}
101
102impl std::fmt::Display for Error {
103 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104 match self {
105 Error::Panic(robj) => write!(f, "Panic detected {:?}.", robj),
106 Error::NotFound(robj) => write!(f, "Not found. {:?}", robj),
107 Error::EvalError(robj) => write!(f, "Evaluation error in {:?}.", robj),
108 Error::ParseError { status, code } => {
109 let reason = match status {
110 ParseStatus::PARSE_NULL => "no statement to parse",
111 ParseStatus::PARSE_OK => "no parse error",
112 ParseStatus::PARSE_INCOMPLETE => "incomplete statement",
113 ParseStatus::PARSE_ERROR => "syntax error",
114 ParseStatus::PARSE_EOF => "unexpected end of file",
115 };
116 write!(f, "Parse error ({reason}) in {:?}.", code)
117 }
118 Error::NamesLengthMismatch(robj) => {
119 write!(f, "Length of names does not match vector. {:?}", robj)
120 }
121
122 Error::ExpectedNull(robj) => write!(f, "Expected Null got {:?}", robj.rtype()),
123 Error::ExpectedSymbol(robj) => write!(f, "Expected Symbol got {:?}", robj.rtype()),
124 Error::ExpectedPairlist(robj) => write!(f, "Expected Pairlist got {:?}", robj.rtype()),
125 Error::ExpectedFunction(robj) => write!(f, "Expected Function got {:?}", robj.rtype()),
126 Error::ExpectedEnvironment(robj) => {
127 write!(f, "Expected Environment got {:?}", robj.rtype())
128 }
129 Error::ExpectedPromise(robj) => write!(f, "Expected Promise got {:?}", robj.rtype()),
130 Error::ExpectedLanguage(robj) => write!(f, "Expected Language got {:?}", robj.rtype()),
131 Error::ExpectedSpecial(robj) => write!(f, "Expected Special got {:?}", robj.rtype()),
132 Error::ExpectedBuiltin(robj) => write!(f, "Expected Builtin got {:?}", robj.rtype()),
133 Error::ExpectedRstr(robj) => {
134 write!(f, "Expected Rstr got {:?}", robj.rtype())
135 }
136 Error::ExpectedLogical(robj) => write!(f, "Expected Logicals got {:?}", robj.rtype()),
137 Error::ExpectedInteger(robj) => write!(f, "Expected Integers got {:?}", robj.rtype()),
138 Error::ExpectedReal(robj) => write!(f, "Expected Doubles got {:?}", robj.rtype()),
139 Error::ExpectedComplex(robj) => write!(f, "Expected Complexes got {:?}", robj.rtype()),
140 Error::ExpectedString(robj) => write!(f, "Expected Strings got {:?}", robj.rtype()),
141 Error::ExpectedDot(robj) => write!(f, "Expected Dot got {:?}", robj.rtype()),
142 Error::ExpectedAny(robj) => write!(f, "Expected Any got {:?}", robj.rtype()),
143 Error::ExpectedList(robj) => write!(f, "Expected List got {:?}", robj.rtype()),
144 Error::ExpectedExpression(robj) => {
145 write!(f, "Expected Expression got {:?}", robj.rtype())
146 }
147 Error::ExpectedBytecode(robj) => write!(f, "Expected Bytecode got {:?}", robj.rtype()),
148 Error::ExpectedExternalPtr(robj) => {
149 write!(f, "Expected ExternalPtr got {:?}", robj.rtype())
150 }
151 Error::ExpectedWeakRef(robj) => write!(f, "Expected WeakRef got {:?}", robj.rtype()),
152 Error::ExpectedRaw(robj) => write!(f, "Expected Raw got {:?}", robj.rtype()),
153 Error::ExpectedS4(robj) => write!(f, "Expected S4 got {:?}", robj.rtype()),
154 Error::ExpectedPrimitive(robj) => {
155 write!(f, "Expected Primitive got {:?}", robj.rtype())
156 }
157
158 Error::ExpectedScalar(robj) => write!(f, "Expected Scalar, got {:?}", robj.rtype()),
159 Error::ExpectedVector(robj) => write!(f, "Expected Vector, got {:?}", robj.rtype()),
160 Error::ExpectedMatrix(robj) => write!(f, "Expected Matrix, got {:?}", robj.rtype()),
161 Error::ExpectedMatrix3D(robj) => write!(f, "Expected Matrix3D, got {:?}", robj.rtype()),
162 Error::ExpectedMatrix4D(robj) => write!(f, "Expected Matrix4D, got {:?}", robj.rtype()),
163 Error::ExpectedMatrix5D(robj) => write!(f, "Expected Matrix5D, got {:?}", robj.rtype()),
164 Error::ExpectedNumeric(robj) => write!(f, "Expected Numeric, got {:?}", robj.rtype()),
165 Error::ExpectedAltrep(robj) => write!(f, "Expected Altrep, got {:?}", robj.rtype()),
166 Error::ExpectedDataframe(robj) => {
167 write!(f, "Expected Dataframe, got {:?}", robj.rtype())
168 }
169
170 Error::OutOfRange(_robj) => write!(f, "Out of range."),
171 Error::MustNotBeNA(_robj) => write!(f, "Must not be NA."),
172 Error::ExpectedNonZeroLength(_robj) => write!(f, "Expected non zero length"),
173 Error::ExpectedLength(len) => write!(f, "Expected length: {len}"),
174 Error::OutOfLimits(robj) => write!(f, "The value is too big: {:?}", robj),
175 Error::TypeMismatch(_robj) => write!(f, "Type mismatch"),
176
177 Error::NamespaceNotFound(robj) => write!(f, "Namespace {:?} not found", robj),
178 Error::ExpectedExternalPtrType(_robj, type_name) => {
179 write!(f, "Incorrect external pointer type {}", type_name)
180 }
181 Error::ExpectedExternalNonNullPtr(robj) => {
182 write!(
183 f,
184 "expected non-null pointer in externalptr, instead {:?}",
185 robj
186 )
187 }
188 Error::ExpectedExternalPtrReference => {
189 write!(f, "It is only possible to return a reference to self.")
190 }
191 Error::NoGraphicsDevices(_robj) => write!(f, "No graphics devices active."),
192 Error::TryFromSliceError(std_error) => write!(f, "Rust error: {}", std_error),
194 Error::Other(str) => write!(f, "{}", str),
195
196 Error::ExpectedWholeNumber(robj, conversion_error) => {
197 write!(
198 f,
199 "Failed to convert a float to a whole number: {}. Actual value received: {:?}",
200 conversion_error, robj
201 )
202 }
203
204 #[cfg(feature = "ndarray")]
205 Error::NDArrayShapeError(shape_error) => {
206 write!(f, "NDArray failed with error: {}.", shape_error)
207 }
208
209 #[cfg(feature = "either")]
210 Error::EitherError(left_err, right_err) => {
211 write!(
212 f,
213 "Both cases of Either errored. Left: '{}'; Right: '{}'.",
214 left_err, right_err
215 )
216 }
217 }
218 }
219}
220pub type Result<T> = std::result::Result<T, Error>;
221
222impl std::error::Error for Error {
229 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
230 None
231 }
232}
233
234impl From<Box<dyn std::error::Error>> for Error {
235 fn from(err: Box<dyn std::error::Error>) -> Error {
236 Error::Other(format!("{}", err))
237 }
238}
239
240impl From<&str> for Error {
241 fn from(err: &str) -> Error {
242 Error::Other(err.to_string())
243 }
244}
245
246impl From<String> for Error {
247 fn from(err: String) -> Error {
248 Error::Other(err)
249 }
250}
251
252impl From<Infallible> for Error {
261 fn from(_: Infallible) -> Self {
262 Error::Other("".to_string())
263 }
264}