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}