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)]
32#[non_exhaustive]
33pub enum Error {
34 Panic(Robj),
35 NotFound(Robj),
36 EvalError(Robj),
37 ParseError {
38 status: ParseStatus,
39 code: Robj,
40 },
41 NamesLengthMismatch(Robj),
42
43 ExpectedNull(Robj),
44 ExpectedSymbol(Robj),
45 ExpectedPairlist(Robj),
46 ExpectedFunction(Robj),
47 ExpectedEnvironment(Robj),
48 ExpectedPromise(Robj),
49 ExpectedLanguage(Robj),
50 ExpectedSpecial(Robj),
51 ExpectedBuiltin(Robj),
52 ExpectedRstr(Robj),
53 ExpectedLogical(Robj),
54 ExpectedInteger(Robj),
55 ExpectedReal(Robj),
56 ExpectedComplex(Robj),
57 ExpectedString(Robj),
58 ExpectedDot(Robj),
59 ExpectedAny(Robj),
60 ExpectedList(Robj),
61 ExpectedExpression(Robj),
62 ExpectedBytecode(Robj),
63 ExpectedExternalPtr(Robj),
64 ExpectedWeakRef(Robj),
65 ExpectedRaw(Robj),
66 ExpectedS4(Robj),
67 ExpectedPrimitive(Robj),
68
69 ExpectedScalar(Robj),
70 ExpectedVector(Robj),
71 ExpectedMatrix(Robj),
72 ExpectedMatrix3D(Robj),
73 ExpectedMatrix4D(Robj),
74 ExpectedMatrix5D(Robj),
75 ExpectedNumeric(Robj),
76 ExpectedAltrep(Robj),
77 ExpectedDataframe(Robj),
78
79 OutOfRange(Robj),
80 MustNotBeNA(Robj),
81 ExpectedWholeNumber(Robj, ConversionError),
82 ExpectedNonZeroLength(Robj),
83 ExpectedLength(usize),
84 OutOfLimits(Robj),
85 TypeMismatch(Robj),
86 NamespaceNotFound(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::TryFromSliceError(std_error) => write!(f, "Rust error: {}", std_error),
193 Error::Other(str) => write!(f, "{}", str),
194
195 Error::ExpectedWholeNumber(robj, conversion_error) => {
196 write!(
197 f,
198 "Failed to convert a float to a whole number: {}. Actual value received: {:?}",
199 conversion_error, robj
200 )
201 }
202
203 #[cfg(feature = "ndarray")]
204 Error::NDArrayShapeError(shape_error) => {
205 write!(f, "NDArray failed with error: {}.", shape_error)
206 }
207
208 #[cfg(feature = "either")]
209 Error::EitherError(left_err, right_err) => {
210 write!(
211 f,
212 "Both cases of Either errored. Left: '{}'; Right: '{}'.",
213 left_err, right_err
214 )
215 }
216 }
217 }
218}
219pub type Result<T> = std::result::Result<T, Error>;
220
221impl std::error::Error for Error {
228 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
229 None
230 }
231}
232
233impl From<Box<dyn std::error::Error>> for Error {
234 fn from(err: Box<dyn std::error::Error>) -> Error {
235 Error::Other(format!("{}", err))
236 }
237}
238
239impl From<&str> for Error {
240 fn from(err: &str) -> Error {
241 Error::Other(err.to_string())
242 }
243}
244
245impl From<String> for Error {
246 fn from(err: String) -> Error {
247 Error::Other(err)
248 }
249}
250
251impl From<Infallible> for Error {
260 fn from(_: Infallible) -> Self {
261 Error::Other("".to_string())
262 }
263}