Skip to main content

tokio_dbus_codegen/
error.rs

1use std::error;
2use std::fmt;
3use std::io;
4use std::path::{Path, PathBuf};
5
6use tokio_dbus_core::signature::{SignatureBuf, SignatureError};
7
8/// Result alias defaulting to the error type of this crate.
9pub type Result<T, E = Error> = std::result::Result<T, E>;
10
11/// An error raised while generating code.
12#[derive(Debug)]
13pub struct Error {
14    // NB: Boxed so that a `Result` carrying this error stays small, since the
15    // generator threads it through every type mapping.
16    kind: Box<ErrorKind>,
17    context: Option<Box<str>>,
18}
19
20impl Error {
21    pub(crate) fn new(kind: ErrorKind) -> Self {
22        Self {
23            kind: Box::new(kind),
24            context: None,
25        }
26    }
27
28    /// Attach the element the error concerns, so that a failure points at the
29    /// interface file rather than at the generator.
30    pub(crate) fn context(mut self, context: impl fmt::Display) -> Self {
31        if self.context.is_none() {
32            self.context = Some(context.to_string().into());
33        }
34
35        self
36    }
37
38    pub(crate) fn io(path: &Path, error: io::Error) -> Self {
39        Self::new(ErrorKind::Io(path.to_owned(), error))
40    }
41}
42
43impl From<SignatureError> for Error {
44    #[inline]
45    fn from(error: SignatureError) -> Self {
46        Self::new(ErrorKind::Signature(error))
47    }
48}
49
50impl From<tokio_dbus_xml::Error> for Error {
51    #[inline]
52    fn from(error: tokio_dbus_xml::Error) -> Self {
53        Self::new(ErrorKind::Xml(error))
54    }
55}
56
57impl From<genco::fmt::Error> for Error {
58    #[inline]
59    fn from(error: genco::fmt::Error) -> Self {
60        Self::new(ErrorKind::Format(error))
61    }
62}
63
64impl fmt::Display for Error {
65    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
66        if let Some(context) = &self.context {
67            write!(f, "{context}: ")?;
68        }
69
70        match &*self.kind {
71            ErrorKind::Io(path, ..) => write!(f, "{}: I/O error", path.display()),
72            ErrorKind::Xml(..) => write!(f, "Could not parse interface file"),
73            ErrorKind::Signature(..) => write!(f, "Invalid signature"),
74            ErrorKind::Format(..) => write!(f, "Could not format generated code"),
75            ErrorKind::MissingOutDir => write!(
76                f,
77                "OUT_DIR is not set, which means this is not running from a build script. \
78                 Use `write_to` to name an output path instead"
79            ),
80            ErrorKind::MissingInterface(name) => {
81                write!(f, "No interface named `{name}` in any of the files read")
82            }
83            ErrorKind::EmptyType => write!(f, "Expected a type, but the signature was empty"),
84            ErrorKind::CompoundType(signature) => write!(
85                f,
86                "Expected a single type, but `{signature}` names more than one"
87            ),
88            ErrorKind::LooseDictEntry => write!(
89                f,
90                "A dict entry is only legal as the element type of an array"
91            ),
92            ErrorKind::UnknownType(signature) => write!(f, "Unknown type `{signature}`"),
93            ErrorKind::UnixFd => write!(
94                f,
95                "Passing a file descriptor (`h`) is not supported, since it requires \
96                 sending it out of band"
97            ),
98        }
99    }
100}
101
102impl error::Error for Error {
103    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
104        match &*self.kind {
105            ErrorKind::Io(_, error) => Some(error),
106            ErrorKind::Xml(error) => Some(error),
107            ErrorKind::Signature(error) => Some(error),
108            ErrorKind::Format(error) => Some(error),
109            _ => None,
110        }
111    }
112}
113
114#[derive(Debug)]
115pub(crate) enum ErrorKind {
116    Io(PathBuf, io::Error),
117    Xml(tokio_dbus_xml::Error),
118    Signature(SignatureError),
119    Format(genco::fmt::Error),
120    MissingOutDir,
121    MissingInterface(Box<str>),
122    EmptyType,
123    CompoundType(SignatureBuf),
124    LooseDictEntry,
125    UnknownType(SignatureBuf),
126    UnixFd,
127}