ev3dev_lang_rust/
utils.rs

1//! Utility things.
2
3use std::{error::Error, fmt};
4
5/// Helper `Result` type for easy access.
6pub type Ev3Result<T> = Result<T, Ev3Error>;
7
8/// Custom error type for internal errors.
9#[derive(Debug)]
10pub enum Ev3Error {
11    /// Internal error with error `msg`.
12    InternalError {
13        /// Original error message.
14        msg: String,
15    },
16    /// No matching device found.
17    NotConnected {
18        /// Corresponding device
19        device: String,
20        /// Device was expected to be on this port (None if no port was specified)
21        port: Option<String>,
22    },
23    /// More than one matching device found.
24    MultipleMatches {
25        /// Corresponding device
26        device: String,
27        /// Devices of the requested type were found on this ports.
28        ports: Vec<String>,
29    },
30}
31
32impl fmt::Display for Ev3Error {
33    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34        match self {
35            Ev3Error::InternalError { msg } => write!(f, "InternalError: {msg}!"),
36            Ev3Error::NotConnected { device, port } => {
37                write!(f, "'{device}' not connected at port {port:?}!")
38            }
39            Ev3Error::MultipleMatches { device, ports } => {
40                write!(f, "Multiple '{device}' connected at ports {ports:?}!")
41            }
42        }
43    }
44}
45
46impl Error for Ev3Error {}
47
48impl From<std::io::Error> for Ev3Error {
49    fn from(err: std::io::Error) -> Self {
50        Ev3Error::InternalError {
51            msg: format!("{err}"),
52        }
53    }
54}
55
56impl From<std::string::FromUtf8Error> for Ev3Error {
57    fn from(err: std::string::FromUtf8Error) -> Self {
58        Ev3Error::InternalError {
59            msg: format!("{err}"),
60        }
61    }
62}
63
64impl From<std::num::ParseIntError> for Ev3Error {
65    fn from(err: std::num::ParseIntError) -> Self {
66        Ev3Error::InternalError {
67            msg: format!("{err}"),
68        }
69    }
70}
71
72#[cfg(feature = "screen")]
73impl From<framebuffer::FramebufferError> for Ev3Error {
74    fn from(err: framebuffer::FramebufferError) -> Self {
75        Ev3Error::InternalError {
76            msg: format!("{:?}", err),
77        }
78    }
79}
80
81/// EV3 ports
82pub trait Port {
83    /// Returns the name of the port.
84    fn address(&self) -> String;
85}
86
87/// Helper trait to convert an option to an error.
88/// Polyfill for the `Try` trait until it is stable.
89pub trait OrErr<T> {
90    /// Consumes the `Option<T>` and returns an `Ev3Result<T>`.
91    fn or_err(self) -> Ev3Result<T>;
92}
93
94impl<T> OrErr<T> for Option<T> {
95    fn or_err(self) -> Ev3Result<T> {
96        self.ok_or(Ev3Error::InternalError {
97            msg: "Cannot unwrap option".to_owned(),
98        })
99    }
100}