use alloc::string::String;
use core::fmt;
use thiserror::Error;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum HeaderSection {
Graph,
Channel(u16),
Foreign,
ChannelDtype(u16),
Marker,
Journal,
Data,
Compressed(u16),
}
impl fmt::Display for HeaderSection {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Graph => write!(f, "Graph"),
Self::Channel(n) => write!(f, "Channel({n})"),
Self::Foreign => write!(f, "Foreign"),
Self::ChannelDtype(n) => write!(f, "ChannelDtype({n})"),
Self::Marker => write!(f, "Marker"),
Self::Journal => write!(f, "Journal"),
Self::Data => write!(f, "Data"),
Self::Compressed(n) => write!(f, "Compressed({n})"),
}
}
}
#[derive(Debug, Error)]
#[error(
"parse error at byte 0x{byte_offset:X} in {section} header: \
expected {expected}, got {actual}"
)]
pub struct ParseError {
pub byte_offset: u64,
pub expected: String,
pub actual: String,
pub section: HeaderSection,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_error_display_includes_hex_offset() {
let e = ParseError {
byte_offset: 0x1A3C,
expected: String::from("nChanHeaderLen >= 252"),
actual: String::from("180"),
section: HeaderSection::Channel(2),
};
let s = alloc::format!("{e}");
assert!(s.contains("0x1A3C"), "should contain hex offset: {s}");
assert!(s.contains("Channel(2)"), "should name the section: {s}");
assert!(s.contains("252"), "should mention expected: {s}");
assert!(s.contains("180"), "should mention actual: {s}");
}
#[test]
fn all_section_variants_display() {
let sections = [
HeaderSection::Graph,
HeaderSection::Channel(0),
HeaderSection::Foreign,
HeaderSection::ChannelDtype(3),
HeaderSection::Marker,
HeaderSection::Journal,
HeaderSection::Data,
HeaderSection::Compressed(1),
];
for s in §ions {
let _ = alloc::format!("{s}");
}
}
}