packed_struct/
debug_fmt.rs

1//! Helper structures for runtime packing visualization.
2
3use crate::internal_prelude::v1::*;
4
5#[cfg(any(feature="alloc", feature="std"))]
6pub trait PackedStructDebug {
7    fn fmt_fields(&self, fmt: &mut Formatter) -> Result<(), FmtError>;
8    fn packed_struct_display_header() -> &'static str;
9}
10
11pub struct DebugBinaryByteSlice<'a> {
12    pub bits: &'a Range<usize>,
13    pub slice: &'a [u8]
14}
15
16impl<'a> fmt::Binary for DebugBinaryByteSlice<'a> {
17    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
18        for i in self.bits.start..(self.bits.end + 1) {
19            let byte = i / 8;
20            let bit = i % 8;
21            let bit = 7 - bit;
22
23            let src_byte = self.slice[byte];
24            let src_bit = (src_byte & (1 << bit)) == (1 << bit);
25
26            let s = if src_bit { "1" } else { "0" };
27            fmt.write_str(s)?;
28        }
29
30        Ok(())
31    }
32}
33
34pub struct DebugBitField<'a> { 
35	pub name: Cow<'a, str>,
36	pub bits: Range<usize>,
37	pub display_value: Cow<'a, str>
38}
39
40
41pub fn packable_fmt_fields(f: &mut Formatter, packed_bytes: &[u8], fields: &[DebugBitField]) -> fmt::Result {
42    if fields.is_empty() {
43		return Ok(());
44	}
45
46    let max_field_length_name = fields.iter().map(|x| x.name.len()).max().unwrap();
47	let max_bit_width = fields.iter().map(|x| x.bits.len()).max().unwrap();
48
49    if max_bit_width > 32 {
50        for field in fields {
51            write!(f, "{name:>0$} | {base_value:?}\r\n",
52                        max_field_length_name + 1,
53                        base_value = field.display_value,
54                        name = field.name
55                        )?;
56        }
57    } else {    
58        for field in fields {
59
60            let debug_binary = DebugBinaryByteSlice {
61                bits: &field.bits,
62                slice: packed_bytes
63            };
64
65            write!(f, "{name:>0$} | bits {bits_start:>3}:{bits_end:<3} | 0b{binary_value:>0width_bits$b}{dummy:>0spaces$} | {base_value:?}\r\n",
66                        max_field_length_name + 1,
67                        base_value = field.display_value,
68                        binary_value = debug_binary,
69                        dummy = "",
70                        bits_start = field.bits.start,
71                        bits_end = field.bits.end,
72                        width_bits = field.bits.len(),
73                        spaces = (max_bit_width - field.bits.len()) as usize,
74                        name = field.name
75                        )?;
76        }
77    }
78
79    Ok(())
80}
81
82pub struct PackedStructDisplay<'a, P: 'a> {
83    pub packed_struct: &'a P,
84    pub header: bool,
85    pub raw_decimal: bool,
86    pub raw_hex: bool,
87    pub raw_binary: bool,
88    pub fields: bool
89}
90
91impl<'a, P> PackedStructDisplay<'a, P> {
92    pub fn new(packed_struct: &'a P) -> Self {
93        PackedStructDisplay {
94            packed_struct,            
95            header: true,
96            raw_decimal: true,
97            raw_hex: true,
98            raw_binary: true,
99            fields: true
100        }
101    }
102}
103
104use crate::packing::PackedStruct;
105use crate::types_bits::ByteArray;
106
107impl<'a, P> fmt::Display for PackedStructDisplay<'a, P> where P: PackedStruct + PackedStructDebug {
108    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
109        let packed = match self.packed_struct.pack() {
110            Ok(packed) => packed,
111            Err(e) => {
112                return f.write_fmt(format_args!("Error while packing: {:?}", e));                
113            }
114        };
115        let packed = packed.as_bytes_slice();
116        let l = packed.len();
117
118        if self.header {
119            f.write_str(P::packed_struct_display_header())?;
120            f.write_str("\r\n")?;
121            f.write_str("\r\n")?;
122        }
123
124        // decimal
125        if self.raw_decimal {
126            f.write_str("Decimal\r\n")?;
127            f.write_str("[")?;
128            for (i, p) in packed.iter().enumerate().take(l) {
129                write!(f, "{}", p)?;
130                if (i + 1) != l {
131                    f.write_str(", ")?;
132                }
133            }
134            f.write_str("]")?;
135
136            f.write_str("\r\n")?;
137            f.write_str("\r\n")?;
138        }
139                        
140        // hex
141        if self.raw_hex {
142            f.write_str("Hex\r\n")?;
143            f.write_str("[")?;
144            for (i, p) in packed.iter().enumerate().take(l) {
145                write!(f, "0x{:X}", p)?;
146                if (i + 1) != l {
147                    f.write_str(", ")?;
148                }
149            }
150            f.write_str("]")?;
151            f.write_str("\r\n")?;
152            f.write_str("\r\n")?;
153        }
154
155        if self.raw_binary {
156            f.write_str("Binary\r\n")?;
157            f.write_str("[")?;
158
159            for (i, p) in packed.iter().enumerate().take(l) {
160                write!(f, "0b{:08b}", p)?;
161                if (i + 1) != l {
162                    f.write_str(", ")?;
163                }
164            }
165            f.write_str("]")?;
166            f.write_str("\r\n")?;
167            f.write_str("\r\n")?;
168        }
169
170        if self.fields {
171            self.packed_struct.fmt_fields(f)?;
172        }
173    
174        Ok(())
175    }
176}