amdgpu_sysfs/error/
mod.rs

1//! SysFS errors
2mod context;
3
4pub(crate) use context::ErrorContext;
5
6use std::{
7    fmt::Display,
8    num::{ParseFloatError, ParseIntError},
9};
10
11#[derive(Debug, PartialEq)]
12/// An error that can happen when working with the SysFs
13pub struct Error {
14    context: Option<String>,
15    /// The error kind
16    pub kind: ErrorKind,
17}
18
19/// Possible types of errors
20#[derive(Debug)]
21pub enum ErrorKind {
22    /// It is not allowed to perform the given action
23    NotAllowed(String),
24    /// Something is potentially unsupported by this library
25    Unsupported(String),
26    /// The given path is not a valid SysFs
27    InvalidSysFS,
28    /// An error that happens during parsing
29    ParseError {
30        /// What went wrong during parsing
31        msg: String,
32        /// The line where the error occured
33        line: usize,
34    },
35    /// An IO error
36    IoError(std::io::Error),
37}
38
39impl Error {
40    pub(crate) fn unexpected_eol<T: Display>(expected_item: T, line: usize) -> Self {
41        ErrorKind::ParseError {
42            msg: format!("Unexpected EOL, expected {expected_item}"),
43            line,
44        }
45        .into()
46    }
47
48    pub(crate) fn basic_parse_error(msg: impl Into<String>) -> Self {
49        ErrorKind::ParseError {
50            msg: msg.into(),
51            line: 1,
52        }
53        .into()
54    }
55
56    pub(crate) fn not_allowed(msg: String) -> Self {
57        ErrorKind::NotAllowed(msg).into()
58    }
59
60    /// If the error means that the file doesn't exist
61    pub fn is_not_found(&self) -> bool {
62        matches!(&self.kind, ErrorKind::IoError(io_err) if io_err.kind() == std::io::ErrorKind::NotFound)
63    }
64}
65
66impl Display for Error {
67    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68        match &self.kind {
69            ErrorKind::NotAllowed(info) => write!(f, "not allowed: {info}")?,
70            ErrorKind::InvalidSysFS => write!(f, "invalid SysFS")?,
71            ErrorKind::ParseError { msg, line } => write!(f, "parse error: {msg} at line {line}")?,
72            ErrorKind::IoError(error) => write!(f, "io error: {error}")?,
73            ErrorKind::Unsupported(err) => write!(f, "unsupported: {err}")?,
74        }
75
76        if let Some(ctx) = &self.context {
77            write!(f, "\n{ctx}")?;
78        }
79
80        Ok(())
81    }
82}
83
84impl std::error::Error for Error {}
85
86impl From<ErrorKind> for Error {
87    fn from(kind: ErrorKind) -> Self {
88        Self {
89            context: None,
90            kind,
91        }
92    }
93}
94
95impl From<std::io::Error> for Error {
96    fn from(err: std::io::Error) -> Self {
97        Self {
98            context: None,
99            kind: ErrorKind::IoError(err),
100        }
101    }
102}
103
104impl From<ParseIntError> for Error {
105    fn from(err: ParseIntError) -> Self {
106        Self::basic_parse_error(err.to_string())
107    }
108}
109
110impl From<ParseFloatError> for Error {
111    fn from(err: ParseFloatError) -> Self {
112        Self::basic_parse_error(err.to_string())
113    }
114}
115
116impl PartialEq for ErrorKind {
117    fn eq(&self, other: &Self) -> bool {
118        match (self, other) {
119            (Self::IoError(l0), Self::IoError(r0)) => l0.kind() == r0.kind(),
120            _ => core::mem::discriminant(self) == core::mem::discriminant(other),
121        }
122    }
123}