1use std::convert::Infallible;
2use std::fmt::Display;
3use std::io;
4
5use thiserror::Error;
6
7use crate::hwmon::error::HwmonError;
8use crate::perf_regs::error::PerformanceCounterError;
9use crate::DeviceError::{IncompatibleDriver, UnexpectedValue};
10
11pub type DeviceResult<T> = Result<T, DeviceError>;
13
14#[derive(Debug, Error)]
16pub enum DeviceError {
17 #[error("Device {name} not found")]
18 DeviceNotFound { name: String },
19 #[error("Device {name} found but still in use")]
20 DeviceBusy { name: String },
21 #[error("IoError: {cause}")]
22 IoError { cause: io::Error },
23 #[error("PermissionDenied: {cause}")]
24 PermissionDenied { cause: io::Error },
25 #[error("Unknown architecture, arch: {arch}, rev: {rev}")]
26 UnknownArch { arch: String, rev: String },
27 #[error("Incompatible device driver: {cause}")]
28 IncompatibleDriver { cause: String },
29 #[error("HwmonError: [npu{device_index}] {cause}")]
30 HwmonError { device_index: u8, cause: HwmonError },
31 #[error("PerformanceCounterError: {cause}")]
32 PerformanceCounterError { cause: PerformanceCounterError },
33 #[error("Unexpected value: {message}")]
34 UnexpectedValue { message: String },
35 #[error("Failed to parse given message {message}: {cause}")]
36 ParseError { message: String, cause: String },
37}
38
39impl DeviceError {
40 pub(crate) fn device_not_found<D: Display>(name: D) -> DeviceError {
41 DeviceError::DeviceNotFound {
42 name: name.to_string(),
43 }
44 }
45
46 pub(crate) fn device_busy<D: Display>(name: D) -> DeviceError {
47 DeviceError::DeviceBusy {
48 name: name.to_string(),
49 }
50 }
51
52 pub(crate) fn unrecognized_file<F: Display>(file: F) -> DeviceError {
53 IncompatibleDriver {
54 cause: format!("{file} file cannot be recognized"),
55 }
56 }
57
58 pub(crate) fn invalid_device_file<F: Display>(file: F) -> DeviceError {
59 IncompatibleDriver {
60 cause: format!("{file} is not a valid device file"),
61 }
62 }
63
64 pub(crate) fn hwmon_error(device_index: u8, cause: HwmonError) -> DeviceError {
65 DeviceError::HwmonError {
66 device_index,
67 cause,
68 }
69 }
70
71 pub(crate) fn performance_counter_error(cause: PerformanceCounterError) -> DeviceError {
72 DeviceError::PerformanceCounterError { cause }
73 }
74
75 pub(crate) fn unexpected_value<S: ToString>(message: S) -> DeviceError {
76 UnexpectedValue {
77 message: message.to_string(),
78 }
79 }
80
81 pub(crate) fn parse_error<S: ToString, C: ToString>(message: S, cause: C) -> DeviceError {
82 DeviceError::ParseError {
83 message: message.to_string(),
84 cause: cause.to_string(),
85 }
86 }
87}
88
89impl From<io::Error> for DeviceError {
90 fn from(e: io::Error) -> Self {
91 if e.kind() == std::io::ErrorKind::PermissionDenied {
92 Self::PermissionDenied { cause: e }
93 } else {
94 Self::IoError { cause: e }
95 }
96 }
97}
98
99impl From<Infallible> for DeviceError {
100 fn from(_: Infallible) -> Self {
101 unreachable!()
102 }
103}