1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#[allow(clippy::module_name_repetitions)]
#[derive(Debug)]
#[non_exhaustive]
/// An error type that can describe atspi and `std` and different `zbus` errors.
pub enum AtspiError {
	/// Converting one type into another failure
	Conversion(&'static str),

	/// When testing on either variant, we might find the we are not interested in.
	CacheVariantMismatch,

	/// On specific types, if the event / message member does not match the Event's name.
	MemberMatch(String),

	/// On specific types, if the event / message member does not match the Event's name.
	InterfaceMatch(String),

	/// To indicate a match or equality test on a signal body signature failed.
	UnknownBusSignature(String),

	/// When matching on an unknown interface
	UnknownInterface,

	/// No interface on event.
	MissingInterface,

	/// No member on event.
	MissingMember,

	/// When matching on an unknown role
	UnknownRole(u32),

	/// No name on bus.
	MissingName,

	/// The signal that was encountered is unknown.
	UnknownSignal,

	/// Other errors.
	Owned(String),

	/// A `zbus` or `zbus::Fdo` error. variant.
	Zbus(String),

	/// A `zbus_names` error variant
	ZBusNames(zbus_names::Error),

	/// A `zbus_names` error variant
	Zvariant(zvariant::Error),

	/// Failed to parse a string into an enum variant
	ParseError(&'static str),

	/// Failed to get the ID of a path.
	PathConversionError(ObjectPathConversionError),

	/// Std i/o error variant.
	IO(std::io::Error),

	/// Failed to convert an integer into another type of integer (usually i32 -> usize).
	IntConversionError(std::num::TryFromIntError),

	/// An infallible error; this is just something to satisfy the compiler.
	Infallible,
}

impl std::error::Error for AtspiError {}

impl std::fmt::Display for AtspiError {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		match self {
			Self::Conversion(e) => f.write_str(&format!("atspi: conversion failure: {e}")),
			Self::MemberMatch(e) => {
				f.write_str(format!("atspi: member mismatch in conversion: {e}").as_str())
			}
			Self::InterfaceMatch(e) => {
				f.write_str(format!("atspi: interface mismatch in conversion: {e}").as_str())
			}
			Self::UnknownBusSignature(e) => {
				f.write_str(format!("atspi: Unknown bus body signature: {e:?}").as_str())
			}
			Self::UnknownInterface => f.write_str("Unknown interface."),
			Self::MissingInterface => f.write_str("Missing interface."),
			Self::MissingMember => f.write_str("Missing member."),
			Self::UnknownRole(e) => f.write_str(&format!("atspi: Unknown role: {e}")),
			Self::UnknownSignal => f.write_str("atspi: Unknown signal"),
			Self::CacheVariantMismatch => f.write_str("atspi: Cache variant mismatch"),
			Self::Owned(e) => f.write_str(&format!("atspi: other error: {e}")),
			Self::Zbus(e) => f.write_str(&format!("ZBus Error: {e}")),
			Self::Zvariant(e) => f.write_str(&format!("Zvariant error: {e}")),
			Self::ZBusNames(e) => f.write_str(&format!("ZBus_names Error: {e}")),
			Self::ParseError(e) => f.write_str(e),
			Self::PathConversionError(e) => {
				f.write_str(&format!("ID cannot be extracted from the path: {e}"))
			}
			Self::IO(e) => f.write_str(&format!("std IO Error: {e}")),
			Self::IntConversionError(e) => f.write_str(&format!("Integer conversion error: {e}")),
			Self::MissingName => f.write_str("Missing name for a bus."),
			Self::Infallible => {
				f.write_str("Infallible; only to trick the compiler. This should never happen.")
			}
		}
	}
}

impl From<std::convert::Infallible> for AtspiError {
	fn from(_e: std::convert::Infallible) -> Self {
		Self::Infallible
	}
}
impl From<std::num::TryFromIntError> for AtspiError {
	fn from(e: std::num::TryFromIntError) -> Self {
		Self::IntConversionError(e)
	}
}

#[cfg(feature = "zbus")]
impl From<zbus::fdo::Error> for AtspiError {
	fn from(e: zbus::fdo::Error) -> Self {
		Self::Zbus(format!("{e:?}"))
	}
}

#[cfg(feature = "zbus")]
impl From<zbus::Error> for AtspiError {
	fn from(e: zbus::Error) -> Self {
		Self::Zbus(format!("{e:?}"))
	}
}

impl From<zbus_names::Error> for AtspiError {
	fn from(e: zbus_names::Error) -> Self {
		Self::ZBusNames(e)
	}
}

impl From<zvariant::Error> for AtspiError {
	fn from(e: zvariant::Error) -> Self {
		Self::Zvariant(e)
	}
}

impl From<std::io::Error> for AtspiError {
	fn from(e: std::io::Error) -> Self {
		Self::IO(e)
	}
}

impl From<ObjectPathConversionError> for AtspiError {
	fn from(e: ObjectPathConversionError) -> AtspiError {
		Self::PathConversionError(e)
	}
}

#[allow(clippy::module_name_repetitions)]
#[derive(Clone, Debug)]
pub enum ObjectPathConversionError {
	NoIdAvailable,
	ParseError(<i64 as std::str::FromStr>::Err),
}
impl std::fmt::Display for ObjectPathConversionError {
	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
		match self {
			Self::NoIdAvailable => f.write_str("No ID available in the path."),
			Self::ParseError(e) => f.write_str(&format!("Failure to parse: {e}")),
		}
	}
}
impl std::error::Error for ObjectPathConversionError {}