tokio_dbus_codegen/
error.rs1use std::error;
2use std::fmt;
3use std::io;
4use std::path::{Path, PathBuf};
5
6use tokio_dbus_core::signature::{SignatureBuf, SignatureError};
7
8pub type Result<T, E = Error> = std::result::Result<T, E>;
10
11#[derive(Debug)]
13pub struct Error {
14 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 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}