use bacnet_types::enums::{ErrorClass, ErrorCode, RejectReason};
use bacnet_types::error::Error;
mod device;
mod discovery;
mod file;
mod object;
mod summary;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Kind {
Decodes,
Malformed,
Short,
Reject(RejectReason),
Protocol(ErrorClass, ErrorCode),
Other,
}
use Kind::{Decodes, Malformed, Short};
impl Kind {
fn of(result: &Result<(), Error>) -> Self {
match result {
Ok(()) => Decodes,
Err(Error::Decoding(_)) => Malformed,
Err(Error::BufferTooShort { .. }) => Short,
Err(Error::Reject { reason }) => Kind::Reject(*reason),
Err(Error::Protocol { class, code }) => Kind::Protocol(*class, *code),
Err(_) => Kind::Other,
}
}
}
type Decode = fn(&[u8]) -> Result<(), Error>;
type Row<'a> = (&'a str, &'a [u8], Kind);
macro_rules! decoder {
($ty:ty) => {
(
stringify!($ty),
(|d: &[u8]| <$ty>::decode(d).map(drop)) as Decode,
)
};
}
use decoder;
fn check((name, decode): (&str, Decode), rows: &[Row<'_>]) {
let failures: Vec<String> = rows
.iter()
.filter_map(|&(row, input, expected)| {
let result = decode(input);
(Kind::of(&result) != expected).then(|| {
format!("{name} {row} {input:02X?}: expected {expected:?}, got {result:?}")
})
})
.collect();
assert!(failures.is_empty(), "\n{}", failures.join("\n"));
}
fn cat(parts: &[&[u8]]) -> Vec<u8> {
parts.concat()
}