use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Error, Debug)]
pub enum Error {
#[error("invalid magic byte: expected 0x53, got 0x{0:02x}")]
InvalidMagic(u8),
#[error("payload too large: {0} bytes (max 65535)")]
PayloadTooLarge(usize),
#[error("buffer too small: need {needed} bytes, have {have}")]
BufferTooSmall { needed: usize, have: usize },
#[error("encode error: {0}")]
EncodeError(String),
#[error("decode error: {0}")]
DecodeError(String),
#[error("unknown message type: 0x{0:02x}")]
UnknownMessageType(u8),
#[error("unknown signal type: {0}")]
UnknownSignalType(String),
#[error("invalid address: {0}")]
InvalidAddress(String),
#[error("invalid pattern: {0}")]
InvalidPattern(String),
#[error("state conflict: revision {expected} expected, got {actual}")]
RevisionConflict { expected: u64, actual: u64 },
#[error("lock held by {holder}")]
LockHeld { holder: String },
#[error("permission denied: {0}")]
PermissionDenied(String),
#[error("connection error: {0}")]
ConnectionError(String),
#[error("operation timed out")]
Timeout,
#[error("protocol error: {0}")]
Protocol(String),
}
impl From<rmp_serde::encode::Error> for Error {
fn from(e: rmp_serde::encode::Error) -> Self {
Error::EncodeError(e.to_string())
}
}
impl From<rmp_serde::decode::Error> for Error {
fn from(e: rmp_serde::decode::Error) -> Self {
Error::DecodeError(e.to_string())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)]
pub enum ErrorCode {
InvalidFrame = 100,
InvalidMessage = 101,
UnsupportedVersion = 102,
InvalidAddress = 200,
AddressNotFound = 201,
PatternError = 202,
Unauthorized = 300,
Forbidden = 301,
TokenExpired = 302,
RevisionConflict = 400,
LockHeld = 401,
InvalidValue = 402,
InternalError = 500,
ServiceUnavailable = 501,
Timeout = 502,
}
impl ErrorCode {
pub fn from_u16(code: u16) -> Option<Self> {
match code {
100 => Some(ErrorCode::InvalidFrame),
101 => Some(ErrorCode::InvalidMessage),
102 => Some(ErrorCode::UnsupportedVersion),
200 => Some(ErrorCode::InvalidAddress),
201 => Some(ErrorCode::AddressNotFound),
202 => Some(ErrorCode::PatternError),
300 => Some(ErrorCode::Unauthorized),
301 => Some(ErrorCode::Forbidden),
302 => Some(ErrorCode::TokenExpired),
400 => Some(ErrorCode::RevisionConflict),
401 => Some(ErrorCode::LockHeld),
402 => Some(ErrorCode::InvalidValue),
500 => Some(ErrorCode::InternalError),
501 => Some(ErrorCode::ServiceUnavailable),
502 => Some(ErrorCode::Timeout),
_ => None,
}
}
}