use bytes::{Buf, Bytes}; use tinyvec::ArrayVec; #[derive(PartialEq, Debug, Clone)] pub struct Trace { tag: u32, auth: u32, flags: u8, pub(crate) path_snr: ArrayVec<[f32; 64]>, invalid: bool, pub(crate) temp_path: ArrayVec<[u16; 64]>, } impl From for Trace { fn from(value: Bytes) -> Self { let mut bytes = value; let mut trace = Trace { tag: 0, auth: 0, flags: 0, path_snr: ArrayVec::new(), invalid: true, temp_path: ArrayVec::new(), }; if bytes.len() < 10 { return trace; } trace.tag = bytes.get_u32(); trace.auth = bytes.get_u32(); trace.flags = bytes.get_u8(); for byte in bytes.iter() { trace.temp_path.push(*byte as u16); } trace.invalid = false; trace } } impl core::fmt::Display for Trace { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { for (snr, hash) in self.path_snr.iter().zip(self.temp_path.clone()) { f.write_fmt(format_args!("({:2x?}): {}dB ", hash, snr))?; } Ok(()) } } // Tests for std operations #[cfg(test)] mod tests { use crate::{packet::*, packet_content::PacketContent}; use core::str::FromStr; use hex::decode; use tinyvec::array_vec; use super::*; #[test] fn trace() { let sample = "26032CE0F149EB5B240000000000ACA079"; let lhs_packet = Packet { route_type: RouteType::Direct, version: PayloadVersion::VersionOne, path: array_vec!([u16; 64] => 0xAC, 0xA0, 0x79), transport: [0, 0], raw_content: Bytes::copy_from_slice(&decode("49EB5B240000000000ACA079").unwrap()), content: PacketContent::Trace(Trace { tag: 0x49EB5B24, auth: 0x00000000, flags: 0x00, path_snr: array_vec!([f32; 64] => 11.0, -8.0, -3.75), invalid: false, temp_path: array_vec!([u16; 64] => 0xAC, 0xA0, 0x79), }), incomplete: false, }; let rhs_packet = Packet::from_str(sample).unwrap(); assert_eq!(lhs_packet, rhs_packet); // We can only check the description in std mode #[cfg(feature = "std")] assert_eq!( format!("{}", rhs_packet), " Direct | v1 | | [ac, a0, 79] | | TRACE | (ac): 11dB (a0): -8dB (79): -3.75dB " ) } }