cpdb_rs/error.rs
1//! Crate-wide error type and `Result` alias.
2
3use std::ffi::NulError;
4use std::str::Utf8Error;
5use thiserror::Error;
6
7/// Errors that originate from the cpdb-rs bindings.
8///
9/// This type is `#[non_exhaustive]` — match arms must include a wildcard
10/// so adding variants in future minor releases is not a breaking change.
11#[non_exhaustive]
12#[derive(Error, Debug)]
13pub enum CpdbError {
14 /// A C function returned `NULL` where a valid pointer was required.
15 #[error("Null pointer encountered")]
16 NullPointer,
17
18 /// A printer object pointer is invalid or has been released.
19 #[error("Invalid printer object")]
20 InvalidPrinter,
21
22 /// A lookup (printer, option, media, translation, ...) returned no result.
23 #[error("Not found: {0}")]
24 NotFound(String),
25
26 /// A printer-side operation failed (set default, accept jobs, ...).
27 #[error("Printer error: {0}")]
28 PrinterError(String),
29
30 /// A print job submission failed.
31 #[error("Print job failed: {0}")]
32 JobFailed(String),
33
34 /// A backend-side operation failed.
35 #[error("Backend error: {0}")]
36 BackendError(String),
37
38 /// A frontend-side operation failed (D-Bus, lifecycle, ...).
39 #[error("Frontend error: {0}")]
40 FrontendError(String),
41
42 /// A printer option could not be parsed or applied.
43 #[error("Option error: {0}")]
44 OptionError(String),
45
46 /// A byte sequence returned by the backend (cpdb-libs C string or a
47 /// D-Bus payload) contained invalid UTF-8.
48 #[error("Invalid UTF-8 string: {0}")]
49 Utf8Error(#[from] Utf8Error),
50
51 /// A Rust string contained an interior NUL byte.
52 #[error("Nul byte in string: {0}")]
53 NulError(#[from] NulError),
54
55 /// An I/O error bubbled up from std::io.
56 #[error("IO error: {0}")]
57 IoError(#[from] std::io::Error),
58
59 /// An unexpected status code was returned.
60 #[error("Invalid status code: {0}")]
61 InvalidStatus(i32),
62
63 /// The requested operation is not supported.
64 #[error("Unsupported operation")]
65 Unsupported,
66
67 /// A D-Bus protocol error occurred. The inner string is a
68 /// human-readable rendering (typically starts with the D-Bus error
69 /// name, e.g. `"org.freedesktop.DBus.Error.UnknownMethod: ..."`).
70 ///
71 /// The variant is exposed even when the `zbus-backend` feature is
72 /// disabled so downstream match arms remain valid across every
73 /// feature combination.
74 #[error("D-Bus error: {0}")]
75 DbusError(String),
76
77 /// A D-Bus FDO (freedesktop.org) standard error occurred. See
78 /// [`DbusError`](Self::DbusError) for the rationale on the unconditional
79 /// `String` payload.
80 #[error("D-Bus FDO error: {0}")]
81 FdoError(String),
82}
83
84/// Converts a `zbus::Error` into a [`CpdbError::DbusError`] by rendering it
85/// with `Display`. Only compiled when the `zbus-backend` feature is enabled.
86#[cfg(feature = "zbus-backend")]
87impl From<zbus::Error> for CpdbError {
88 fn from(e: zbus::Error) -> Self {
89 Self::DbusError(e.to_string())
90 }
91}
92
93/// Converts a `zbus::fdo::Error` into a [`CpdbError::FdoError`] by rendering
94/// it with `Display`. Only compiled when the `zbus-backend` feature is
95/// enabled.
96#[cfg(feature = "zbus-backend")]
97impl From<zbus::fdo::Error> for CpdbError {
98 fn from(e: zbus::fdo::Error) -> Self {
99 Self::FdoError(e.to_string())
100 }
101}
102
103/// Shorthand `Result` alias used throughout the crate.
104pub type Result<T> = std::result::Result<T, CpdbError>;
105
106/// Convert a `cpdb_sys` FFI error into the crate-wide `CpdbError`.
107///
108/// This allows `?` to work across the FFI boundary when calling functions
109/// from `cpdb_sys` modules (e.g. `util`, `printer`) inside `cpdb_rs` code.
110#[cfg(feature = "ffi")]
111impl From<cpdb_sys::error::CpdbError> for CpdbError {
112 fn from(e: cpdb_sys::error::CpdbError) -> Self {
113 match e {
114 cpdb_sys::error::CpdbError::NullPointer => Self::NullPointer,
115 cpdb_sys::error::CpdbError::InvalidPrinter => Self::InvalidPrinter,
116 cpdb_sys::error::CpdbError::NotFound(s) => Self::NotFound(s),
117 cpdb_sys::error::CpdbError::PrinterError(s) => Self::PrinterError(s),
118 cpdb_sys::error::CpdbError::JobFailed(s) => Self::JobFailed(s),
119 cpdb_sys::error::CpdbError::BackendError(s) => Self::BackendError(s),
120 cpdb_sys::error::CpdbError::FrontendError(s) => Self::FrontendError(s),
121 cpdb_sys::error::CpdbError::OptionError(s) => Self::OptionError(s),
122 cpdb_sys::error::CpdbError::Utf8Error(e) => Self::Utf8Error(e),
123 cpdb_sys::error::CpdbError::NulError(e) => Self::NulError(e),
124 cpdb_sys::error::CpdbError::IoError(e) => Self::IoError(e),
125 cpdb_sys::error::CpdbError::InvalidStatus(c) => Self::InvalidStatus(c),
126 cpdb_sys::error::CpdbError::Unsupported => Self::Unsupported,
127 _ => Self::FrontendError(format!("cpdb-sys error: {e}")),
128 }
129 }
130}