blackbox_log/parser/decode/
mod.rs1#![allow(clippy::cast_possible_truncation)]
2
3mod negative_14_bit;
4mod tagged_16;
5mod tagged_32;
6mod tagged_variable;
7mod variable;
8
9use alloc::vec::Vec;
10
11pub(crate) use self::negative_14_bit::negative_14_bit;
12pub(crate) use self::tagged_16::tagged_16;
13pub(crate) use self::tagged_32::tagged_32;
14pub(crate) use self::tagged_variable::tagged_variable;
15pub(crate) use self::variable::{variable, variable_signed};
16use super::InternalResult;
17use crate::Reader;
18
19byte_enum! {
20 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
21 #[repr(u8)]
22 pub(crate) enum Encoding {
23 VariableSigned = 0,
25 Variable = 1,
27 Negative14Bit = 3,
30 TaggedVariable = 6,
31 Tagged32 = 7,
32 Tagged16 = 8,
41 Null = 9,
43 }
44}
45
46impl Encoding {
47 pub(crate) const fn is_signed(&self) -> bool {
48 match self {
49 Self::VariableSigned
50 | Self::Negative14Bit
51 | Self::TaggedVariable
52 | Self::Tagged32
53 | Self::Tagged16 => true,
54 Self::Variable | Self::Null => false,
55 }
56 }
57
58 pub(crate) const fn max_chunk_size(&self) -> usize {
59 match self {
60 Self::TaggedVariable => 8,
61 Self::Tagged32 => 3,
62 Self::Tagged16 => 4,
63 Self::VariableSigned | Self::Variable | Self::Negative14Bit | Self::Null => 1,
64 }
65 }
66
67 pub(crate) fn decode_into(
68 &self,
69 data: &mut Reader,
70 extra: usize,
71 into: &mut Vec<u32>,
72 ) -> InternalResult<()> {
73 let range = 0..=extra;
74 match self {
75 Self::VariableSigned => into.push(variable_signed(data)?.cast_unsigned()),
76 Self::Variable => into.push(variable(data)?),
77
78 Self::Negative14Bit => into.push(negative_14_bit(data)?.cast_unsigned()),
79
80 Self::TaggedVariable => {
81 into.extend_from_slice(
82 &tagged_variable(data, extra)?.map(i32::cast_unsigned)[range],
83 );
84 }
85 Self::Tagged32 => {
86 into.extend_from_slice(&tagged_32(data)?.map(i32::cast_unsigned)[range]);
87 }
88 Self::Tagged16 => {
89 into.extend_from_slice(
90 &tagged_16(data)?.map(|x| i32::from(x).cast_unsigned())[range],
91 );
92 }
93
94 Self::Null => into.push(0),
95 }
96
97 Ok(())
98 }
99}
100
101#[inline]
102const fn sign_extend<const BITS: u32>(from: u32) -> i32 {
103 let unused_bits = 32 - BITS;
104 (from << unused_bits).cast_signed() >> unused_bits
105}
106
107#[inline]
108const fn zig_zag_decode(value: u32) -> i32 {
109 (value >> 1).cast_signed() ^ -(value.cast_signed() & 1)
110}
111
112#[cfg(test)]
113mod tests {
114 #[test]
115 fn sign_extend() {
116 use super::sign_extend;
117
118 assert_eq!(0, sign_extend::<2>(0b00));
119 assert_eq!(1, sign_extend::<2>(0b01));
120 assert_eq!(-2, sign_extend::<2>(0b10));
121 assert_eq!(-1, sign_extend::<2>(0b11));
122 }
123
124 #[test]
125 fn zig_zag_decode() {
126 use super::zig_zag_decode;
127
128 assert_eq!(0, zig_zag_decode(0));
129 assert_eq!(-1, zig_zag_decode(1));
130 assert_eq!(1, zig_zag_decode(2));
131 assert_eq!(-2, zig_zag_decode(3));
132
133 assert_eq!(i32::MIN, zig_zag_decode(u32::MAX));
134 assert_eq!(i32::MAX, zig_zag_decode(u32::MAX - 1));
135 }
136}