use core::num::NonZeroU32;
pub const TRACE_FRAME_START: u32 = 0xf0;
pub const TRACE_FRAME_END: u32 = 0xfc;
pub const TRACE_PRINT_LN: u32 = 0x50_52_4e_54;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u32)]
pub enum TraceEvent {
FrameStart,
FrameEnd,
PrintLn,
AssertionFailed(Option<NonZeroU32>),
Unknown(u32),
}
impl TraceEvent {
#[inline(always)]
pub fn is_frame_start(&self) -> bool {
matches!(self, Self::FrameStart)
}
#[inline(always)]
pub fn is_frame_end(&self) -> bool {
matches!(self, Self::FrameEnd)
}
pub fn as_u32(self) -> u32 {
match self {
Self::FrameStart => TRACE_FRAME_START,
Self::FrameEnd => TRACE_FRAME_END,
Self::PrintLn => TRACE_PRINT_LN,
Self::AssertionFailed(None) => 0,
Self::AssertionFailed(Some(code)) => code.get(),
Self::Unknown(event) => event,
}
}
}
impl core::fmt::Display for TraceEvent {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::FrameStart => f.write_str("FRAME_START"),
Self::FrameEnd => f.write_str("FRAME_END"),
Self::PrintLn => f.write_str("PRNT"),
Self::AssertionFailed(None) => write!(f, "ASSERT_FAILED"),
Self::AssertionFailed(Some(id)) => write!(f, "ASSERT_FAILED({id})"),
Self::Unknown(id) => write!(f, "{id}"),
}
}
}
impl From<u32> for TraceEvent {
fn from(raw: u32) -> Self {
match raw {
TRACE_FRAME_START => Self::FrameStart,
TRACE_FRAME_END => Self::FrameEnd,
TRACE_PRINT_LN => Self::PrintLn,
_ => Self::Unknown(raw),
}
}
}
impl From<TraceEvent> for u32 {
fn from(event: TraceEvent) -> Self {
match event {
TraceEvent::FrameStart => TRACE_FRAME_START,
TraceEvent::FrameEnd => TRACE_FRAME_END,
TraceEvent::PrintLn => TRACE_PRINT_LN,
TraceEvent::AssertionFailed(None) => 0,
TraceEvent::AssertionFailed(Some(code)) => code.get(),
TraceEvent::Unknown(code) => code,
}
}
}
#[cfg(test)]
mod tests {
use super::{TRACE_PRINT_LN, TraceEvent};
#[test]
fn trace_print_ln_roundtrips_through_trace_event() {
assert_eq!(TraceEvent::from(TRACE_PRINT_LN), TraceEvent::PrintLn);
assert_eq!(TraceEvent::PrintLn.as_u32(), TRACE_PRINT_LN);
assert_eq!(u32::from(TraceEvent::PrintLn), TRACE_PRINT_LN);
}
}