#![allow(missing_docs)]
macro_rules! trivial_message {
(
$(#[$meta:meta])*
pub struct $name:ident;
) => {
$(#[$meta])*
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct $name;
impl $name {
pub const STRUCTURE_SIZE: u16 = 4;
}
impl crate::pack::Pack for $name {
fn pack(&self, cursor: &mut crate::pack::WriteCursor) {
cursor.write_u16_le(Self::STRUCTURE_SIZE);
cursor.write_u16_le(0);
}
}
impl crate::pack::Unpack for $name {
fn unpack(cursor: &mut crate::pack::ReadCursor<'_>) -> crate::error::Result<Self> {
let structure_size = cursor.read_u16_le()?;
if structure_size != Self::STRUCTURE_SIZE {
return Err(crate::Error::invalid_data(format!(
"invalid {} structure size: expected {}, got {}",
stringify!($name),
Self::STRUCTURE_SIZE,
structure_size
)));
}
let _reserved = cursor.read_u16_le()?;
Ok($name)
}
}
};
}
pub(crate) use trivial_message;
#[cfg(test)]
macro_rules! trivial_message_tests {
($type:ident, $known:ident, $roundtrip:ident, $wrong_size:ident, $short:ident) => {
#[test]
fn $known() {
let msg = $type;
let mut cursor = crate::pack::WriteCursor::new();
crate::pack::Pack::pack(&msg, &mut cursor);
let bytes = cursor.into_inner();
assert_eq!(bytes, [0x04, 0x00, 0x00, 0x00]);
}
#[test]
fn $roundtrip() {
let original = $type;
let mut w = crate::pack::WriteCursor::new();
crate::pack::Pack::pack(&original, &mut w);
let bytes = w.into_inner();
let mut r = crate::pack::ReadCursor::new(&bytes);
let decoded = <$type as crate::pack::Unpack>::unpack(&mut r).unwrap();
assert_eq!(decoded, original);
}
#[test]
fn $wrong_size() {
let bytes = [0x08, 0x00, 0x00, 0x00];
let mut cursor = crate::pack::ReadCursor::new(&bytes);
let result = <$type as crate::pack::Unpack>::unpack(&mut cursor);
assert!(result.is_err());
let err = result.unwrap_err().to_string();
assert!(err.contains("structure size"), "error was: {err}");
}
#[test]
fn $short() {
let bytes = [0x04, 0x00];
let mut cursor = crate::pack::ReadCursor::new(&bytes);
let result = <$type as crate::pack::Unpack>::unpack(&mut cursor);
assert!(result.is_err());
}
};
}
#[cfg(test)]
pub(crate) use trivial_message_tests;
pub mod cancel;
pub mod change_notify;
pub mod close;
pub mod create;
pub mod dfs;
pub mod echo;
pub mod flush;
pub mod header;
pub mod ioctl;
pub mod lock;
pub mod logoff;
pub mod negotiate;
pub mod oplock_break;
pub mod query_directory;
pub mod query_info;
pub mod read;
pub mod session_setup;
pub mod set_info;
pub mod transform;
pub mod tree_connect;
pub mod tree_disconnect;
pub mod write;
pub use header::{ErrorResponse, Header, PROTOCOL_ID};