1#![allow(clippy::missing_const_for_fn)]
2
3use super::{lib_header::AbiHeader, root_mod_trait::RootModule};
4
5use crate::{
6 sabi_types::{ParseVersionError, VersionNumber, VersionStrings},
7 std_types::{RBoxError, RResult, RVec},
8};
9
10use std::{
11 fmt::{self, Display},
12 path::PathBuf,
13};
14
15#[allow(unused_imports)]
16use core_extensions::SelfOps;
17
18#[derive(Debug)]
21pub enum LibraryError {
22 OpenError {
24 path: PathBuf,
26 err: Box<libloading::Error>,
28 },
29 GetSymbolError {
31 library: PathBuf,
33 symbol: Vec<u8>,
35 err: Box<libloading::Error>,
37 },
38 ParseVersionError(ParseVersionError),
40 IncompatibleVersionNumber {
42 library_name: &'static str,
44 expected_version: VersionNumber,
46 actual_version: VersionNumber,
48 },
49 RootModule {
51 err: RootModuleError,
53 module_name: &'static str,
55 version: VersionStrings,
57 },
58 AbiInstability(RBoxError),
62 InvalidAbiHeader(AbiHeader),
65 InvalidCAbi {
67 expected: RBoxError,
69 found: RBoxError,
71 },
72 Many(RVec<Self>),
74}
75
76impl From<ParseVersionError> for LibraryError {
77 fn from(v: ParseVersionError) -> LibraryError {
78 LibraryError::ParseVersionError(v)
79 }
80}
81
82impl Display for LibraryError {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 f.write_str("\n")?;
85 match self {
86 LibraryError::OpenError { path, err } => writeln!(
87 f,
88 "Could not open library at:\n\t{}\nbecause:\n\t{}",
89 path.display(),
90 err
91 ),
92 LibraryError::GetSymbolError {
93 library,
94 symbol,
95 err,
96 } => writeln!(
97 f,
98 "Could load symbol:\n\t{}\nin library:\n\t{}\nbecause:\n\t{}",
99 String::from_utf8_lossy(symbol),
100 library.display(),
101 err
102 ),
103 LibraryError::ParseVersionError(x) => fmt::Display::fmt(x, f),
104 LibraryError::IncompatibleVersionNumber {
105 library_name,
106 expected_version,
107 actual_version,
108 } => writeln!(
109 f,
110 "\n'{}' library version mismatch:\nuser:{}\nlibrary:{}",
111 library_name, expected_version, actual_version,
112 ),
113 LibraryError::RootModule {
114 err,
115 module_name,
116 version,
117 } => {
118 writeln!(
119 f,
120 "An error ocurred while loading this library:\t\n{}",
121 module_name
122 )?;
123 writeln!(f, "version:\n\t{}", version)?;
124 f.write_str("the error:\n\n")?;
125 fmt::Display::fmt(err, f)
126 }
127 LibraryError::AbiInstability(x) => fmt::Display::fmt(x, f),
128 LibraryError::InvalidAbiHeader(found) => write!(
129 f,
130 "The abi of the library was:\n{:#?}\n\
131 When this library expected:\n{:#?}",
132 found,
133 AbiHeader::VALUE,
134 ),
135 LibraryError::InvalidCAbi { expected, found } => {
136 write! {
137 f,
138 "The C abi of the library is different than expected:\n\
139 While running tests on the library:\n\
140 Found:\n {found}\n\
141 Expected:\n {expected}\n\
142 ",
143 found=found,
144 expected=expected,
145 }
146 }
147 LibraryError::Many(list) => {
148 for e in list {
149 Display::fmt(e, f)?;
150 }
151 Ok(())
152 }
153 }?;
154 f.write_str("\n")?;
155 Ok(())
156 }
157}
158
159impl ::std::error::Error for LibraryError {}
160
161#[repr(u8)]
165#[derive(Debug, StableAbi)]
166pub enum RootModuleError {
167 Returned(RBoxError),
169 Unwound,
171}
172
173impl RootModuleError {
174 pub fn reallocate(&mut self) {
177 match self {
178 Self::Returned(e) => {
179 *e = e.to_formatted_error();
180 }
181 Self::Unwound => {}
182 }
183 }
184
185 pub fn into_library_error<M: RootModule>(self) -> LibraryError {
188 LibraryError::RootModule {
189 err: self,
190 module_name: M::NAME,
191 version: M::VERSION_STRINGS,
192 }
193 }
194}
195
196impl Display for RootModuleError {
197 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
198 f.write_str("\n")?;
199 match self {
200 Self::Returned(e) => Display::fmt(e, f)?,
201 Self::Unwound => f.write_str("the root module loader panicked")?,
202 }
203 f.write_str("\n")?;
204 Ok(())
205 }
206}
207
208impl ::std::error::Error for RootModuleError {}
209
210pub trait IntoRootModuleResult {
215 type Module: RootModule;
217
218 fn into_root_module_result(self) -> Result<Self::Module, RootModuleError>;
220}
221
222impl<M: RootModule> IntoRootModuleResult for Result<M, RBoxError> {
223 type Module = M;
224
225 fn into_root_module_result(self) -> Result<M, RootModuleError> {
226 self.map_err(RootModuleError::Returned)
227 }
228}
229
230impl<M: RootModule> IntoRootModuleResult for RResult<M, RBoxError> {
231 type Module = M;
232
233 fn into_root_module_result(self) -> Result<M, RootModuleError> {
234 self.into_result().map_err(RootModuleError::Returned)
235 }
236}
237
238impl<M: RootModule> IntoRootModuleResult for M {
239 type Module = M;
240
241 fn into_root_module_result(self) -> Result<M, RootModuleError> {
242 Ok(self)
243 }
244}
245
246#[cfg(test)]
247mod tests {
248 use super::*;
249
250 use crate::{
251 for_examples::{Module, Module_Ref},
252 prefix_type::WithMetadata,
253 std_types::{RBox, RErr, ROk, RSome},
254 };
255
256 use std::fmt::Error as FmtError;
257
258 const MOD_WM: &WithMetadata<Module> = &WithMetadata::new(Module {
259 first: RSome(5),
260 second: rstr!(""),
261 third: 13,
262 });
263
264 static PREFIX: Module_Ref = Module_Ref(MOD_WM.static_as_prefix());
267
268 #[test]
269 fn into_root_module_result_test() {
270 type Res = Result<Module_Ref, RBoxError>;
271 type RRes = RResult<Module_Ref, RBoxError>;
272
273 {
274 assert_eq!(
275 PREFIX.into_root_module_result().unwrap().0.to_raw_ptr() as usize,
276 PREFIX.0.to_raw_ptr() as usize,
277 );
278 }
279
280 fn test_case(
281 ok: Result<Module_Ref, RootModuleError>,
282 err: Result<Module_Ref, RootModuleError>,
283 ) {
284 assert_eq!(
285 ok.unwrap().0.to_raw_ptr() as usize,
286 PREFIX.0.to_raw_ptr() as usize
287 );
288
289 let downcasted = match err.err().unwrap() {
290 RootModuleError::Returned(x) => x.downcast::<FmtError>().unwrap(),
291 RootModuleError::Unwound => unreachable!(),
292 };
293 assert_eq!(downcasted, RBox::new(FmtError));
294 }
295
296 {
298 let ok: Res = Ok(PREFIX);
299 let err: Res = Err(RBoxError::new(FmtError));
300
301 test_case(ok.into_root_module_result(), err.into_root_module_result());
302 }
303
304 {
306 let ok: RRes = ROk(PREFIX);
307 let err: RRes = RErr(RBoxError::new(FmtError));
308
309 test_case(ok.into_root_module_result(), err.into_root_module_result());
310 }
311 }
312}