Skip to main content

singe_nvml/
error.rs

1#![allow(deprecated)]
2
3use std::{
4    ffi::{CStr, NulError},
5    fmt::{self, Display, Formatter},
6};
7
8use num_enum::{IntoPrimitive, TryFromPrimitive};
9use singe_core::impl_enum_conversion;
10use singe_nvml_sys as sys;
11use thiserror::Error;
12
13#[derive(Error, Debug, Clone, PartialEq, Eq)]
14pub enum Error {
15    #[error("nvml error ({code}): {message}")]
16    Nvml { code: Status, message: String },
17
18    #[error("string contains interior nul byte")]
19    InteriorNul,
20
21    #[error("unknown field value type ({0})")]
22    UnknownFieldValueType(u32),
23
24    #[error("unexpected {name} field value type ({value})")]
25    UnexpectedFieldValueType { name: String, value: String },
26
27    #[error("unknown {name} value ({value})")]
28    UnknownEnumValue { name: String, value: u32 },
29
30    #[error("negative {name} value ({value})")]
31    NegativeValue { name: String, value: i64 },
32
33    #[error("{name} returned no values")]
34    EmptyOutput { name: String },
35}
36
37pub type Result<T> = std::result::Result<T, Error>;
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive, IntoPrimitive)]
40#[repr(u32)]
41pub enum Status {
42    Success = sys::nvmlReturn_t::NVML_SUCCESS as _,
43    Uninitialized = sys::nvmlReturn_t::NVML_ERROR_UNINITIALIZED as _,
44    InvalidArgument = sys::nvmlReturn_t::NVML_ERROR_INVALID_ARGUMENT as _,
45    NotSupported = sys::nvmlReturn_t::NVML_ERROR_NOT_SUPPORTED as _,
46    NoPermission = sys::nvmlReturn_t::NVML_ERROR_NO_PERMISSION as _,
47    #[deprecated]
48    AlreadyInitialized = sys::nvmlReturn_t::NVML_ERROR_ALREADY_INITIALIZED as _,
49    NotFound = sys::nvmlReturn_t::NVML_ERROR_NOT_FOUND as _,
50    InsufficientSize = sys::nvmlReturn_t::NVML_ERROR_INSUFFICIENT_SIZE as _,
51    InsufficientPower = sys::nvmlReturn_t::NVML_ERROR_INSUFFICIENT_POWER as _,
52    DriverNotLoaded = sys::nvmlReturn_t::NVML_ERROR_DRIVER_NOT_LOADED as _,
53    Timeout = sys::nvmlReturn_t::NVML_ERROR_TIMEOUT as _,
54    IrqIssue = sys::nvmlReturn_t::NVML_ERROR_IRQ_ISSUE as _,
55    LibraryNotFound = sys::nvmlReturn_t::NVML_ERROR_LIBRARY_NOT_FOUND as _,
56    FunctionNotFound = sys::nvmlReturn_t::NVML_ERROR_FUNCTION_NOT_FOUND as _,
57    CorruptedInforom = sys::nvmlReturn_t::NVML_ERROR_CORRUPTED_INFOROM as _,
58    GpuIsLost = sys::nvmlReturn_t::NVML_ERROR_GPU_IS_LOST as _,
59    ResetRequired = sys::nvmlReturn_t::NVML_ERROR_RESET_REQUIRED as _,
60    OperatingSystem = sys::nvmlReturn_t::NVML_ERROR_OPERATING_SYSTEM as _,
61    LibRmVersionMismatch = sys::nvmlReturn_t::NVML_ERROR_LIB_RM_VERSION_MISMATCH as _,
62    InUse = sys::nvmlReturn_t::NVML_ERROR_IN_USE as _,
63    Memory = sys::nvmlReturn_t::NVML_ERROR_MEMORY as _,
64    NoData = sys::nvmlReturn_t::NVML_ERROR_NO_DATA as _,
65    VgpuEccNotSupported = sys::nvmlReturn_t::NVML_ERROR_VGPU_ECC_NOT_SUPPORTED as _,
66    InsufficientResources = sys::nvmlReturn_t::NVML_ERROR_INSUFFICIENT_RESOURCES as _,
67    FreqNotSupported = sys::nvmlReturn_t::NVML_ERROR_FREQ_NOT_SUPPORTED as _,
68    ArgumentVersionMismatch = sys::nvmlReturn_t::NVML_ERROR_ARGUMENT_VERSION_MISMATCH as _,
69    Deprecated = sys::nvmlReturn_t::NVML_ERROR_DEPRECATED as _,
70    NotReady = sys::nvmlReturn_t::NVML_ERROR_NOT_READY as _,
71    GpuNotFound = sys::nvmlReturn_t::NVML_ERROR_GPU_NOT_FOUND as _,
72    InvalidState = sys::nvmlReturn_t::NVML_ERROR_INVALID_STATE as _,
73    ResetTypeNotSupported = sys::nvmlReturn_t::NVML_ERROR_RESET_TYPE_NOT_SUPPORTED as _,
74    Unknown = sys::nvmlReturn_t::NVML_ERROR_UNKNOWN as _,
75}
76
77impl_enum_conversion!(sys::nvmlReturn_t, Status);
78
79impl Status {
80    pub fn description(self) -> String {
81        unsafe {
82            let ptr = sys::nvmlErrorString(self.into());
83            if ptr.is_null() {
84                String::from("unknown nvml error")
85            } else {
86                CStr::from_ptr(ptr).to_string_lossy().into_owned()
87            }
88        }
89    }
90}
91
92impl Display for Status {
93    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
94        match self {
95            Self::Success => write!(f, "NVML_SUCCESS"),
96            Self::Uninitialized => write!(f, "NVML_ERROR_UNINITIALIZED"),
97            Self::InvalidArgument => write!(f, "NVML_ERROR_INVALID_ARGUMENT"),
98            Self::NotSupported => write!(f, "NVML_ERROR_NOT_SUPPORTED"),
99            Self::NoPermission => write!(f, "NVML_ERROR_NO_PERMISSION"),
100            Self::AlreadyInitialized => write!(f, "NVML_ERROR_ALREADY_INITIALIZED"),
101            Self::NotFound => write!(f, "NVML_ERROR_NOT_FOUND"),
102            Self::InsufficientSize => write!(f, "NVML_ERROR_INSUFFICIENT_SIZE"),
103            Self::InsufficientPower => write!(f, "NVML_ERROR_INSUFFICIENT_POWER"),
104            Self::DriverNotLoaded => write!(f, "NVML_ERROR_DRIVER_NOT_LOADED"),
105            Self::Timeout => write!(f, "NVML_ERROR_TIMEOUT"),
106            Self::IrqIssue => write!(f, "NVML_ERROR_IRQ_ISSUE"),
107            Self::LibraryNotFound => write!(f, "NVML_ERROR_LIBRARY_NOT_FOUND"),
108            Self::FunctionNotFound => write!(f, "NVML_ERROR_FUNCTION_NOT_FOUND"),
109            Self::CorruptedInforom => write!(f, "NVML_ERROR_CORRUPTED_INFOROM"),
110            Self::GpuIsLost => write!(f, "NVML_ERROR_GPU_IS_LOST"),
111            Self::ResetRequired => write!(f, "NVML_ERROR_RESET_REQUIRED"),
112            Self::OperatingSystem => write!(f, "NVML_ERROR_OPERATING_SYSTEM"),
113            Self::LibRmVersionMismatch => {
114                write!(f, "NVML_ERROR_LIB_RM_VERSION_MISMATCH")
115            }
116            Self::InUse => write!(f, "NVML_ERROR_IN_USE"),
117            Self::Memory => write!(f, "NVML_ERROR_MEMORY"),
118            Self::NoData => write!(f, "NVML_ERROR_NO_DATA"),
119            Self::VgpuEccNotSupported => write!(f, "NVML_ERROR_VGPU_ECC_NOT_SUPPORTED"),
120            Self::InsufficientResources => write!(f, "NVML_ERROR_INSUFFICIENT_RESOURCES"),
121            Self::FreqNotSupported => write!(f, "NVML_ERROR_FREQ_NOT_SUPPORTED"),
122            Self::ArgumentVersionMismatch => {
123                write!(f, "NVML_ERROR_ARGUMENT_VERSION_MISMATCH")
124            }
125            Self::Deprecated => write!(f, "NVML_ERROR_DEPRECATED"),
126            Self::NotReady => write!(f, "NVML_ERROR_NOT_READY"),
127            Self::GpuNotFound => write!(f, "NVML_ERROR_GPU_NOT_FOUND"),
128            Self::InvalidState => write!(f, "NVML_ERROR_INVALID_STATE"),
129            Self::ResetTypeNotSupported => write!(f, "NVML_ERROR_RESET_TYPE_NOT_SUPPORTED"),
130            Self::Unknown => write!(f, "NVML_ERROR_UNKNOWN"),
131        }
132    }
133}
134
135impl From<NulError> for Error {
136    fn from(_: NulError) -> Self {
137        Self::InteriorNul
138    }
139}
140
141impl From<sys::nvmlReturn_t> for Error {
142    fn from(code: sys::nvmlReturn_t) -> Self {
143        let message = unsafe {
144            let c_ptr = sys::nvmlErrorString(code);
145            if c_ptr.is_null() {
146                String::from("unknown nvml error")
147            } else {
148                CStr::from_ptr(c_ptr).to_string_lossy().into_owned()
149            }
150        };
151
152        Self::Nvml {
153            code: code.into(),
154            message,
155        }
156    }
157}
158
159impl From<Status> for Error {
160    fn from(status: Status) -> Self {
161        sys::nvmlReturn_t::from(status).into()
162    }
163}
164
165#[macro_export]
166macro_rules! try_ffi {
167    ($expr:expr) => {{
168        let err = { $expr };
169        if err != singe_nvml_sys::nvmlReturn_t::NVML_SUCCESS {
170            Err($crate::error::Error::from(err))
171        } else {
172            Ok(())
173        }
174    }};
175}