switchkit 0.2.0

Vendor-neutral abstraction for smart-plug devices (Shelly, Tasmota).
Documentation
use thiserror::Error;

pub type Result<T> = std::result::Result<T, Error>;

/// A vendor-neutral device error. Vendor cores map their transport/protocol errors
/// onto these kinds so consumers handle failure uniformly.
/// Non-exhaustive: new error kinds are added over time and this must not become
/// a breaking change for downstream `match` expressions.
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum Error {
    /// The device could not be reached / did not answer (a genuine no-answer).
    #[error("{host}: network: {message}")]
    Network { host: String, message: String },
    /// The device answered but rejected the command / requires auth.
    #[error("{host}: rejected: {message}")]
    Rejected { host: String, message: String },
    /// The device requires authentication that was missing or wrong.
    #[error("{host}: auth: {message}")]
    Auth { host: String, message: String },
    /// The response could not be parsed into the expected shape.
    #[error("{host}: parse: {message}")]
    Parse { host: String, message: String },
    /// The operation is not supported by this device/vendor.
    #[error("{host}: unsupported: {message}")]
    Unsupported { host: String, message: String },
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn network_error_message_contains_host() {
        let err = Error::Network {
            host: "192.0.2.1".to_string(),
            message: "connection refused".to_string(),
        };

        assert!(err.to_string().contains("192.0.2.1"));
    }
}