1use cudarc::driver::DriverError;
4use cuest_ffi::status::{status_to_str, CuestStatus};
5use std::fmt;
6
7#[derive(Debug)]
12#[non_exhaustive]
13pub enum CuestError {
14 Status {
18 status: CuestStatus,
20 context: &'static str,
22 },
23 Cuda(DriverError),
25 Rust(String),
28 UnsupportedVersion { needed: (u32, u32, u32), found: (u32, u32, u32) },
34}
35
36impl fmt::Display for CuestError {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 match self {
39 CuestError::Status { status, context } => {
40 write!(
41 f,
42 "{context} failed: {} (cuEST status {})",
43 status_to_str(*status),
44 status.0
45 )
46 },
47 CuestError::Cuda(err) => write!(f, "cudarc error: {err}"),
48 CuestError::Rust(msg) => write!(f, "{msg}"),
49 CuestError::UnsupportedVersion { needed, found } => write!(
50 f,
51 "these bindings require cuEST {}.{}.{}, but the loaded library is {}.{}.{}",
52 needed.0, needed.1, needed.2, found.0, found.1, found.2
53 ),
54 }
55 }
56}
57
58impl std::error::Error for CuestError {
59 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
60 match self {
61 CuestError::Cuda(err) => Some(err),
62 _ => None,
63 }
64 }
65}
66
67impl From<DriverError> for CuestError {
68 fn from(err: DriverError) -> Self {
69 CuestError::Cuda(err)
70 }
71}
72
73pub(crate) fn status_check(status: CuestStatus, context: &'static str) -> Result<(), CuestError> {
75 if status == cuest_ffi::ffi::CUEST_STATUS_SUCCESS {
76 Ok(())
77 } else {
78 Err(CuestError::Status { status, context })
79 }
80}
81
82#[cfg(test)]
83mod tests {
84 use super::*;
85 use cuest_ffi::ffi::{CUEST_STATUS_INVALID_ARGUMENT, CUEST_STATUS_SUCCESS};
86
87 #[test]
88 fn cpu_status_check() {
89 assert!(status_check(CUEST_STATUS_SUCCESS, "f").is_ok());
90 let err = status_check(CUEST_STATUS_INVALID_ARGUMENT, "cuestF").unwrap_err();
91 match err {
92 CuestError::Status { status, context } => {
93 assert_eq!(status, CUEST_STATUS_INVALID_ARGUMENT);
94 assert_eq!(context, "cuestF");
95 },
96 _ => panic!("unexpected variant"),
97 }
98 }
99
100 #[test]
101 fn cpu_display() {
102 let err = CuestError::Status {
103 status: CUEST_STATUS_INVALID_ARGUMENT,
104 context: "cuestAOBasisCreate",
105 };
106 assert_eq!(err.to_string(), "cuestAOBasisCreate failed: invalid argument (cuEST status 3)");
107 let err = CuestError::UnsupportedVersion { needed: (0, 2, 2), found: (0, 3, 0) };
108 assert_eq!(
109 err.to_string(),
110 "these bindings require cuEST 0.2.2, but the loaded library is 0.3.0"
111 );
112 assert!(std::error::Error::source(&err).is_none());
113 }
114}