use std::fmt::Debug;
use crate::{
Aspect, Attribute, Category, Class, Command, Condition, Context, Entity, Event, HGTPError,
Method, Mode, Report, State, Tag, Token,
};
pub struct HGTPMessage {
pub frame: [u8; 1024],
pub unbounded: Vec<u8>,
}
impl Default for HGTPMessage {
fn default() -> Self {
Self {
frame: [0; 1024],
unbounded: Vec::new(),
}
}
}
mod packer;
mod unpacker;
pub use unpacker::*;
impl Debug for HGTPMessage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let bytes_raw_field_name = format!("bytes (hex , len={})", self.unpack_bytes().len());
let bytes_str = String::from_utf8_lossy(self.unpack_bytes());
let bytes_str_field_name = format!("bytes (utf-8, len={})", bytes_str.len());
f.debug_struct("HGTPMessage")
.field("command", &self.unpack_command())
.field("error", &self.unpack_error_code())
.field("version", &self.unpack_version())
.field("report", &self.unpack_report())
.field("method", &self.unpack_method())
.field("attribute", &self.unpack_attribute())
.field("event", &self.unpack_event())
.field("mode", &self.unpack_mode())
.field("category", &self.unpack_category())
.field("class", &self.unpack_class())
.field("context", &self.unpack_context())
.field("aspect", &self.unpack_aspect())
.field("state", &self.unpack_state())
.field("precedence", &self.unpack_precedence())
.field("tag", &self.unpack_tag())
.field("condition", &self.unpack_condition())
.field("instance", &self.unpack_instance())
.field("offset", &self.unpack_offset())
.field("time", &self.unpack_time())
.field("index", &self.unpack_index())
.field("count", &self.unpack_count())
.field("parameter", &self.unpack_parameter())
.field("resultant", &self.unpack_resultant())
.field("timeout", &self.unpack_timeout())
.field("entity", &self.unpack_entity())
.field("outlet", &self.unpack_outlet())
.field("auxiliary", &self.unpack_auxiliary())
.field("ancillary", &self.unpack_ancillary())
.field("authorization", &self.unpack_authorization())
.field("authority", &self.unpack_authority())
.field("name", &self.unpack_name())
.field("key", &self.unpack_key())
.field("extension", &self.unpack_extension())
.field(&bytes_raw_field_name, &hex::encode(self.unpack_bytes()))
.field(&bytes_str_field_name, &bytes_str)
.finish()
}
}
impl HGTPMessage {
pub fn pretty_print(&self) -> String {
let mut res = String::new();
match self.unpack_command() {
Ok(Command::Bye) => {}
Ok(command) => res.push_str(&format!("Command: {:?}\n", command)),
Err(e) => res.push_str(&e.to_string()),
}
let mut did_print_error = false;
match self.unpack_error_code() {
Ok(HGTPError::Ok) => {}
Ok(error) => {
res.push_str(&format!("Error: {:?}\n", error));
res.push_str(&format!("Extension: {}\n", self.unpack_extension()));
res.push_str(&format!(
"Error msg: {}\n",
String::from_utf8_lossy(self.unpack_bytes())
));
did_print_error = true
}
Err(e) => res.push_str(&e.to_string()),
}
match self.unpack_version() {
0 => {}
version => res.push_str(&format!("Version: {}\n", version)),
}
match self.unpack_report() {
Ok(Report::Null) => {}
Ok(report) => res.push_str(&format!("Report: {:?}\n", report)),
Err(e) => res.push_str(&e.to_string()),
}
match self.unpack_method() {
Ok(Method::Null) => {}
Ok(method) => res.push_str(&format!("Method: {:?}\n", method)),
Err(e) => res.push_str(&e.to_string()),
}
match self.unpack_attribute() {
Ok(Attribute::Null) => {}
Ok(attribute) => res.push_str(&format!("Attribute: {:?}\n", attribute)),
Err(e) => res.push_str(&e.to_string()),
}
match self.unpack_event() {
Ok(Event::Null) => {}
Ok(event) => res.push_str(&format!("Event: {:?}\n", event)),
Err(e) => res.push_str(&e.to_string()),
}
match self.unpack_mode() {
Ok(Mode::Null) => {}
Ok(mode) => res.push_str(&format!("Mode: {:?}\n", mode)),
Err(e) => res.push_str(&e.to_string()),
}
match self.unpack_category() {
Ok(Category::Null) => {}
Ok(category) => res.push_str(&format!("Category: {:?}\n", category)),
Err(e) => res.push_str(&e.to_string()),
}
match self.unpack_class() {
Ok(Class::Null) => {}
Ok(class) => res.push_str(&format!("Class: {:?}\n", class)),
Err(e) => res.push_str(&e.to_string()),
}
match self.unpack_context() {
Ok(Context::Null) => {}
Ok(context) => res.push_str(&format!("Context: {:?}\n", context)),
Err(e) => res.push_str(&e.to_string()),
}
match self.unpack_aspect() {
Ok(Aspect::Null) => {}
Ok(aspect) => res.push_str(&format!("Aspect: {:?}\n", aspect)),
Err(e) => res.push_str(&e.to_string()),
}
match self.unpack_state() {
Ok(State::Null) => {}
Ok(state) => res.push_str(&format!("State: {:?}\n", state)),
Err(e) => res.push_str(&e.to_string()),
}
match self.unpack_precedence() {
0 => {}
precedence => res.push_str(&format!("Precedence: {}\n", precedence)),
}
match self.unpack_condition() {
Ok(Condition::Null) => {}
Ok(condition) => res.push_str(&format!("Condition: {:?}\n", condition)),
Err(e) => res.push_str(&e.to_string()),
}
match self.unpack_instance() {
0 => {}
instance => res.push_str(&format!("Instance: {}\n", instance)),
}
match self.unpack_offset() {
0 => {}
offset => res.push_str(&format!("Offset: {}\n", offset)),
}
match self.unpack_time() {
Ok(time) => {
if time.unix_timestamp() != 0 {
res.push_str(&format!("Time: {}\n", time))
}
}
Err(e) => res.push_str(&e.to_string()),
}
match self.unpack_index() {
0 => {}
index => res.push_str(&format!("Index: {}\n", index)),
}
match self.unpack_count() {
0 => {}
count => res.push_str(&format!("Count: {}\n", count)),
}
match self.unpack_parameter() {
0 => {}
parameter => res.push_str(&format!("Parameter: {}\n", parameter)),
}
match self.unpack_resultant() {
0 => {}
resultant => res.push_str(&format!("Resultant: {}\n", resultant)),
}
match self.unpack_timeout() {
0 => {}
timeout => res.push_str(&format!("Timeout: {}\n", timeout)),
}
match self.unpack_entity() {
Entity::NULL => {}
entity => res.push_str(&format!("Entity: {}\n", entity)),
}
match self.unpack_outlet() {
Entity::NULL => {}
outlet => res.push_str(&format!("Outlet: {}\n", outlet)),
}
match self.unpack_auxiliary() {
Entity::NULL => {}
auxiliary => res.push_str(&format!("Auxiliary: {}\n", auxiliary)),
}
match self.unpack_ancillary() {
Entity::NULL => {}
ancillary => res.push_str(&format!("Ancillary: {}\n", ancillary)),
}
match self.unpack_authorization() {
Token::NULL => {}
authorization => res.push_str(&format!("Authorization: {:?}\n", authorization)),
}
match self.unpack_authority() {
Token::NULL => {}
authority => res.push_str(&format!("Authority: {:?}\n", authority)),
}
match self.unpack_name() {
Ok(name) => {
if !name.is_null() {
res.push_str(&format!("Name: {}\n", name))
}
}
Err(e) => res.push_str(&e.to_string()),
}
match self.unpack_key() {
Ok(key) => {
if !key.is_null() {
res.push_str(&format!("Key: {}\n", key))
}
}
Err(e) => res.push_str(&e.to_string()),
}
if !did_print_error {
match self.unpack_value() {
Ok(value) => {
if value.get_tag() != Tag::Null || !value.get_bytes().is_empty() {
res.push_str(&format!("Value: {}\n", value))
}
}
Err(e) => res.push_str(&e.to_string()),
}
}
if res.is_empty() {
res.push_str("< All fields are null >\n")
}
res
}
}