use core::{fmt, num::ParseIntError};
use thiserror::Error;
use crate::response::TrapResponse;
use crate::word::Word;
#[derive(Error, Debug, Clone, PartialEq, Eq)]
pub enum DecodeError {
#[error("invalid length prefix byte: 0x{0:02x}")]
InvalidLengthPrefix(u8),
}
#[derive(Error, Debug, PartialEq, Clone)]
pub enum SentenceError {
#[error("Word error: {0}")]
WordError(#[from] crate::word::WordError),
#[error("Invalid prefix length")]
PrefixLength,
}
#[derive(Error, Debug, Clone)]
pub enum ProtocolError {
#[error("Sentence error: {0}")]
Sentence(#[from] SentenceError),
#[error("Incomplete response: {0}")]
Incomplete(#[from] MissingWord),
#[error("Unexpected word type: found {word:?}, expected one of {expected:?}")]
WordSequence {
word: WordType,
expected: alloc::vec::Vec<WordType>,
},
#[error("Trap category error: {0}")]
TrapCategory(#[from] TrapCategoryError),
}
#[derive(Error, Debug, Clone, Copy)]
pub enum MissingWord {
#[error("missing tag")]
Tag,
#[error("missing category")]
Category,
#[error("missing message")]
Message,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum WordType {
Tag,
Category,
Attribute,
Message,
}
impl fmt::Display for WordType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
WordType::Tag => write!(f, "tag"),
WordType::Category => write!(f, "category"),
WordType::Attribute => write!(f, "attribute"),
WordType::Message => write!(f, "message"),
}
}
}
impl From<Word<'_>> for WordType {
fn from(word: Word) -> Self {
match word {
Word::Tag(_) => WordType::Tag,
Word::Category(_) => WordType::Category,
Word::Attribute(_) => WordType::Attribute,
Word::Message(_) => WordType::Message,
}
}
}
#[derive(Error, Debug, Clone)]
pub enum TrapCategoryError {
#[error("Invalid trap category value: {0}")]
Invalid(#[source] ParseIntError),
#[error("Trap category out of range: {0} (valid range: 0-7)")]
OutOfRange(u8),
#[error("Invalid trap attribute: key={key}, value={value:?}")]
InvalidAttribute {
key: alloc::string::String,
value: Option<alloc::string::String>,
},
#[error("Missing message attribute in trap response")]
MissingMessageAttribute,
}
#[derive(Error, Debug, Clone)]
pub enum ConnectionError {
#[error("decode error: {0}")]
Decode(#[from] DecodeError),
#[error("protocol error: {0}")]
Protocol(#[from] ProtocolError),
#[error("connection is closed")]
Closed,
}
#[derive(Error, Debug, Clone)]
pub enum LoginError {
#[error("authentication failed: {0}")]
Authentication(TrapResponse),
#[error("fatal error during login: {0}")]
Fatal(alloc::string::String),
#[error("protocol error during login: {0}")]
Protocol(#[from] ProtocolError),
#[error("connection error during login: {0}")]
Connection(#[from] ConnectionError),
}