use std::string::FromUtf8Error;
use crate::{taxonomy::*, Entity, String255, Token, Value, ValueCreationError};
use thiserror::Error;
use time::OffsetDateTime;
use super::HGTPMessage;
#[derive(Error, Debug)]
pub enum UnpackError {
#[error("invalid command {0}")]
Command(u16),
#[error("invalid error code {0}: {1}")]
Error(u16, String),
#[error("invalid report {0}")]
Report(u16),
#[error("invalid method {0}")]
Method(u16),
#[error("invalid attribute {0}")]
Attribute(u16),
#[error("invalid event {0}")]
Event(u16),
#[error("invalid mode {0}")]
Mode(u16),
#[error("invalid category {0}")]
Category(u16),
#[error("invalid class {0}")]
Class(u16),
#[error("invalid context {0}")]
Context(u16),
#[error("invalid aspect {0}")]
Aspect(u16),
#[error("invalid state {0}")]
State(u16),
#[error("invalid condition {0}")]
Condition(u16),
#[error("invalid time: {0}")]
Time(time::error::ComponentRange),
#[error("invalid name: {0}")]
Name(FromUtf8Error),
#[error("invalid key: {0}")]
Key(FromUtf8Error),
#[error("invalid value: {0}")]
Value(#[from] UnpackValueError),
}
#[derive(Error, Debug)]
#[error("invalid tag {0}")]
pub struct UnpackTagError(pub u16);
#[derive(Error, Debug)]
pub enum UnpackValueError {
#[error(transparent)]
UnpackTag(#[from] UnpackTagError),
#[error("invalid bytes: {0}")]
InvalidBytes(FromUtf8Error),
#[error(transparent)]
ValueCreationError(#[from] ValueCreationError),
}
impl HGTPMessage {
pub fn unpack_command(&self) -> Result<Command, UnpackError> {
let raw = u16::from_le_bytes(self.frame[0..2].try_into().unwrap());
Command::try_from(raw).map_err(|_| UnpackError::Command(raw))
}
pub fn unpack_error_code(&self) -> Result<HGTPError, UnpackError> {
let raw = u16::from_le_bytes(self.frame[2..4].try_into().unwrap());
HGTPError::try_from(raw).map_err(|_| {
UnpackError::Error(
raw,
String::from_utf8_lossy(self.unpack_bytes()).to_string(),
)
})
}
pub fn unpack_version(&self) -> u16 {
u16::from_le_bytes(self.frame[4..6].try_into().unwrap())
}
pub fn unpack_report(&self) -> Result<Report, UnpackError> {
let raw = u16::from_le_bytes(self.frame[6..8].try_into().unwrap());
Report::try_from(raw).map_err(|_| UnpackError::Report(raw))
}
pub fn unpack_method(&self) -> Result<Method, UnpackError> {
let v = u16::from_le_bytes(self.frame[8..10].try_into().unwrap());
Method::try_from(v).map_err(|_| UnpackError::Method(v))
}
pub fn unpack_attribute(&self) -> Result<Attribute, UnpackError> {
let v = u16::from_le_bytes(self.frame[10..12].try_into().unwrap());
Attribute::try_from(v).map_err(|_| UnpackError::Attribute(v))
}
pub fn unpack_event(&self) -> Result<Event, UnpackError> {
let v = u16::from_le_bytes(self.frame[12..14].try_into().unwrap());
Event::try_from(v).map_err(|_| UnpackError::Event(v))
}
pub fn unpack_mode(&self) -> Result<Mode, UnpackError> {
let v = u16::from_le_bytes(self.frame[14..16].try_into().unwrap());
Mode::try_from(v).map_err(|_| UnpackError::Mode(v))
}
pub fn unpack_category(&self) -> Result<Category, UnpackError> {
let v = u16::from_le_bytes(self.frame[16..18].try_into().unwrap());
Category::try_from(v).map_err(|_| UnpackError::Category(v))
}
pub fn unpack_class(&self) -> Result<Class, UnpackError> {
let v = u16::from_le_bytes(self.frame[18..20].try_into().unwrap());
Class::try_from(v).map_err(|_| UnpackError::Class(v))
}
pub fn unpack_context(&self) -> Result<Context, UnpackError> {
let v = u16::from_le_bytes(self.frame[20..22].try_into().unwrap());
Context::try_from(v).map_err(|_| UnpackError::Context(v))
}
pub fn unpack_aspect(&self) -> Result<Aspect, UnpackError> {
let v = u16::from_le_bytes(self.frame[22..24].try_into().unwrap());
Aspect::try_from(v).map_err(|_| UnpackError::Aspect(v))
}
pub fn unpack_state(&self) -> Result<State, UnpackError> {
let v = u16::from_le_bytes(self.frame[24..26].try_into().unwrap());
State::try_from(v).map_err(|_| UnpackError::State(v))
}
pub fn unpack_precedence(&self) -> u16 {
u16::from_le_bytes(self.frame[26..28].try_into().unwrap())
}
pub fn unpack_tag(&self) -> Result<Tag, UnpackTagError> {
let v = u16::from_le_bytes(self.frame[28..30].try_into().unwrap());
Tag::try_from(v).map_err(|_| UnpackTagError(v))
}
pub fn unpack_condition(&self) -> Result<Condition, UnpackError> {
let v = u16::from_le_bytes(self.frame[30..32].try_into().unwrap());
Condition::try_from(v).map_err(|_| UnpackError::Condition(v))
}
pub fn unpack_instance(&self) -> i32 {
i32::from_le_bytes(self.frame[32..36].try_into().unwrap())
}
pub fn unpack_offset(&self) -> i32 {
i32::from_le_bytes(self.frame[36..40].try_into().unwrap())
}
pub fn unpack_time(&self) -> Result<OffsetDateTime, UnpackError> {
let timestamp = i64::from_le_bytes(self.frame[40..48].try_into().unwrap());
OffsetDateTime::from_unix_timestamp(timestamp).map_err(|e| UnpackError::Time(e))
}
pub fn unpack_index(&self) -> i64 {
i64::from_le_bytes(self.frame[48..56].try_into().unwrap())
}
pub fn unpack_count(&self) -> i64 {
i64::from_le_bytes(self.frame[56..64].try_into().unwrap())
}
pub fn unpack_extension(&self) -> i64 {
i64::from_le_bytes(self.frame[64..72].try_into().unwrap())
}
pub fn unpack_parameter(&self) -> i64 {
i64::from_le_bytes(self.frame[72..80].try_into().unwrap())
}
pub fn unpack_resultant(&self) -> i64 {
i64::from_le_bytes(self.frame[80..88].try_into().unwrap())
}
pub fn unpack_timeout(&self) -> i64 {
i64::from_le_bytes(self.frame[88..96].try_into().unwrap())
}
pub fn unpack_entity(&self) -> Entity {
Entity {
pid: u32::from_le_bytes(self.frame[160..164].try_into().unwrap()),
hid: u32::from_le_bytes(self.frame[164..168].try_into().unwrap()),
uid: u64::from_le_bytes(self.frame[168..176].try_into().unwrap()),
}
}
pub fn unpack_outlet(&self) -> Entity {
Entity {
pid: u32::from_le_bytes(self.frame[176..180].try_into().unwrap()),
hid: u32::from_le_bytes(self.frame[180..184].try_into().unwrap()),
uid: u64::from_le_bytes(self.frame[184..192].try_into().unwrap()),
}
}
pub fn unpack_auxiliary(&self) -> Entity {
Entity {
pid: u32::from_le_bytes(self.frame[192..196].try_into().unwrap()),
hid: u32::from_le_bytes(self.frame[196..200].try_into().unwrap()),
uid: u64::from_le_bytes(self.frame[200..208].try_into().unwrap()),
}
}
pub fn unpack_ancillary(&self) -> Entity {
Entity {
pid: u32::from_le_bytes(self.frame[208..212].try_into().unwrap()),
hid: u32::from_le_bytes(self.frame[212..216].try_into().unwrap()),
uid: u64::from_le_bytes(self.frame[216..224].try_into().unwrap()),
}
}
pub fn unpack_authorization(&self) -> Token {
Token::from_bytes(self.frame[224..240].try_into().unwrap())
}
pub fn unpack_authority(&self) -> Token {
Token::from_bytes(self.frame[240..256].try_into().unwrap())
}
pub fn unpack_name(&self) -> Result<String255, UnpackError> {
let len = self.frame[256];
let bytes = &self.frame[257..257 + len as usize];
match String::from_utf8(bytes.to_vec()) {
Ok(s) => Ok(String255::unchecked(&s)),
Err(e) => Err(UnpackError::Name(e)),
}
}
pub fn unpack_key(&self) -> Result<String255, UnpackError> {
let len = self.frame[512];
let bytes = &self.frame[513..513 + len as usize];
match String::from_utf8(bytes.to_vec()) {
Ok(s) => Ok(String255::unchecked(&s)),
Err(e) => Err(UnpackError::Key(e)),
}
}
pub fn unpack_bytes(&self) -> &[u8] {
let extension = self.unpack_extension();
if extension == 0 {
let len = self.frame[768] as usize;
&self.frame[769..769 + len]
} else {
&self.unbounded
}
}
pub fn unpack_value(&self) -> Result<Value, UnpackError> {
let t = self.unpack_tag().map_err(UnpackValueError::UnpackTag)?;
let b = self.unpack_bytes().to_vec();
let s = String::from_utf8(b).map_err(UnpackValueError::InvalidBytes)?;
Ok(Value::new(t, s).map_err(UnpackValueError::ValueCreationError)?)
}
}