Skip to main content

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}