1use std::ffi::CString;
2
3pub struct DlDescription(pub(crate) CString);
4
5impl std::fmt::Debug for DlDescription {
6 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
7 std::fmt::Debug::fmt(&self.0, f)
8 }
9}
10
11pub struct WindowsError(pub(crate) std::io::Error);
12
13impl std::fmt::Debug for WindowsError {
14 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
15 std::fmt::Debug::fmt(&self.0, f)
16 }
17}
18
19#[derive(Debug)]
20#[non_exhaustive]
21pub enum Error {
22 DlOpen { desc: DlDescription },
24 DlOpenUnknown,
26 DlSym { desc: DlDescription },
28 DlSymUnknown,
30 DlClose { desc: DlDescription },
32 DlCloseUnknown,
34 LoadLibraryW { source: WindowsError },
36 LoadLibraryWUnknown,
38 GetProcAddress { source: WindowsError },
40 GetProcAddressUnknown,
42 FreeLibrary { source: WindowsError },
44 FreeLibraryUnknown,
46 IncompatibleSize,
48 CreateCString { source: std::ffi::NulError },
50 CreateCStringWithTrailing { source: std::ffi::FromBytesWithNulError },
52}
53
54impl std::error::Error for Error {
55 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
56 use Error::*;
57 match *self {
58 CreateCString { ref source } => Some(source),
59 CreateCStringWithTrailing { ref source } => Some(source),
60 LoadLibraryW { ref source } => Some(&source.0),
61 GetProcAddress { ref source } => Some(&source.0),
62 FreeLibrary { ref source } => Some(&source.0),
63 _ => None,
64 }
65 }
66}
67
68impl std::fmt::Display for Error {
69 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
70 use Error::*;
71 match *self {
72 DlOpen { ref desc } => write!(f, "{}", desc.0.to_string_lossy()),
73 DlOpenUnknown => write!(f, "dlopen failed, but system did not report the error"),
74 DlSym { ref desc } => write!(f, "{}", desc.0.to_string_lossy()),
75 DlSymUnknown => write!(f, "dlsym failed, but system did not report the error"),
76 DlClose { ref desc } => write!(f, "{}", desc.0.to_string_lossy()),
77 DlCloseUnknown => write!(f, "dlclose failed, but system did not report the error"),
78 LoadLibraryW { .. } => write!(f, "LoadLibraryW failed"),
79 LoadLibraryWUnknown =>
80 write!(f, "LoadLibraryW failed, but system did not report the error"),
81 GetProcAddress { .. } => write!(f, "GetProcAddress failed"),
82 GetProcAddressUnknown =>
83 write!(f, "GetProcAddress failed, but system did not report the error"),
84 FreeLibrary { .. } => write!(f, "FreeLibrary failed"),
85 FreeLibraryUnknown =>
86 write!(f, "FreeLibrary failed, but system did not report the error"),
87 CreateCString { .. } => write!(f, "could not create a C string from bytes"),
88 CreateCStringWithTrailing { .. } =>
89 write!(f, "could not create a C string from bytes with trailing null"),
90 IncompatibleSize => write!(f, "requested type cannot possibly work"),
91 }
92 }
93}
94
95#[cfg(test)]
96mod tests {
97 #[test]
98 fn error_send() {
99 fn assert_send<T: Send>() {}
100 assert_send::<super::Error>();
101 }
102
103 #[test]
104 fn error_sync() {
105 fn assert_sync<T: Sync>() {}
106 assert_sync::<super::Error>();
107 }
108
109 #[test]
110 fn error_display() {
111 fn assert_display<T: std::fmt::Display>() {}
112 assert_display::<super::Error>();
113 }
114}