Skip to main content

mountpoint_s3_crt/common/
error.rs

1//! Common error handing tools for the CRT
2
3use std::ffi::CStr;
4
5use mountpoint_s3_crt_sys::{AWS_OP_SUCCESS, aws_error_debug_str, aws_last_error};
6
7/// An error reported by the AWS Common Runtime
8#[derive(Clone, Copy, PartialEq, Eq)]
9pub struct Error(i32);
10
11impl Error {
12    /// Return the last error raised on the current thread
13    ///
14    /// # Safety
15    /// This reads a thread local, so the caller must ensure no other CRT code has run on
16    /// the same thread since the error was last set, otherwise the result will be the wrong error.
17    pub(crate) unsafe fn last_error() -> Self {
18        // SAFETY: Must be guaranteed by the caller.
19        Self(unsafe { aws_last_error() })
20    }
21
22    /// Return whether this error is an error or a successful result
23    pub fn is_err(&self) -> bool {
24        self.0 != AWS_OP_SUCCESS
25    }
26
27    /// Return the raw CRT error code
28    pub fn raw_error(&self) -> i32 {
29        self.0
30    }
31}
32
33/// Return a formatted description of this error suitable for debugging
34fn err_code_to_debug_str(code: i32) -> &'static str {
35    // SAFETY: we trust the CRT's `aws_error_debug_str` to return valid ASCII
36    // C strings (null-terminated), that live for the life of the program, and it also promises
37    // never to return a null pointer.
38    unsafe {
39        let s = CStr::from_ptr(aws_error_debug_str(code));
40        s.to_str().expect("aws_error_debug_str should return valid ASCII")
41    }
42}
43
44impl From<i32> for Error {
45    fn from(err: i32) -> Self {
46        Self(err)
47    }
48}
49
50impl std::fmt::Display for Error {
51    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
52        write!(f, "CRT error {}: {}", self.0, err_code_to_debug_str(self.0))
53    }
54}
55
56impl std::fmt::Debug for Error {
57    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58        f.debug_tuple("Error")
59            .field(&self.0)
60            .field(&err_code_to_debug_str(self.0))
61            .finish()
62    }
63}
64
65impl std::error::Error for Error {}