|
5 | 5 | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
6 | 6 | // See the License for the specific language governing permissions and limitations under the License.
|
7 | 7 |
|
8 |
| -use std::mem::size_of; |
9 |
| - |
10 | 8 | use nom::{
|
11 |
| - bytes::complete::take, |
12 | 9 | number::complete::{le_u32, le_u64},
|
| 10 | + sequence::tuple, |
| 11 | + IResult, |
13 | 12 | };
|
14 | 13 |
|
15 |
| -#[derive(Debug)] |
| 14 | +#[derive(Debug, Clone, Copy)] |
16 | 15 | pub struct LogPreamble {
|
17 | 16 | pub chunk_tag: u32,
|
18 | 17 | pub chunk_sub_tag: u32,
|
19 | 18 | pub chunk_data_size: u64,
|
20 | 19 | }
|
| 20 | + |
21 | 21 | impl LogPreamble {
|
22 | 22 | /// Get the preamble (first 16 bytes of all Unified Log entries (chunks)) to detect the log (chunk) type. Ex: Firehose, Statedump, Simpledump, Catalog, etc
|
23 |
| - pub fn detect_preamble(data: &[u8]) -> nom::IResult<&[u8], LogPreamble> { |
24 |
| - let mut preamble = LogPreamble { |
25 |
| - chunk_tag: 0, |
26 |
| - chunk_sub_tag: 0, |
27 |
| - chunk_data_size: 0, |
28 |
| - }; |
29 |
| - |
30 |
| - let (input, tag) = take(size_of::<u32>())(data)?; |
31 |
| - let (input, sub_tag) = take(size_of::<u32>())(input)?; |
32 |
| - let (input, data_size) = take(size_of::<u64>())(input)?; |
33 |
| - |
34 |
| - let (_, trace_tag) = le_u32(tag)?; |
35 |
| - let (_, trace_sub_tag) = le_u32(sub_tag)?; |
36 |
| - let (_, trace_data_size) = le_u64(data_size)?; |
37 |
| - |
38 |
| - preamble.chunk_tag = trace_tag; |
39 |
| - preamble.chunk_sub_tag = trace_sub_tag; |
40 |
| - preamble.chunk_data_size = trace_data_size; |
| 23 | + /// Do not consume the input |
| 24 | + pub fn detect_preamble(input: &[u8]) -> IResult<&[u8], Self> { |
| 25 | + let (_, preamble) = Self::parse(input)?; |
41 | 26 | Ok((input, preamble))
|
42 | 27 | }
|
| 28 | + |
| 29 | + /// Get the preamble (first 16 bytes of all Unified Log entries (chunks)) to detect the log (chunk) type. Ex: Firehose, Statedump, Simpledump, Catalog, etc |
| 30 | + /// And consume the input |
| 31 | + pub fn parse(input: &[u8]) -> IResult<&[u8], Self> { |
| 32 | + let (input, (chunk_tag, chunk_sub_tag, chunk_data_size)) = |
| 33 | + tuple((le_u32, le_u32, le_u64))(input)?; |
| 34 | + Ok(( |
| 35 | + input, |
| 36 | + LogPreamble { |
| 37 | + chunk_tag, |
| 38 | + chunk_sub_tag, |
| 39 | + chunk_data_size, |
| 40 | + }, |
| 41 | + )) |
| 42 | + } |
43 | 43 | }
|
44 | 44 |
|
45 | 45 | #[cfg(test)]
|
46 | 46 | mod tests {
|
47 | 47 | use super::LogPreamble;
|
48 | 48 |
|
49 | 49 | #[test]
|
50 |
| - fn test_detect_preamble() { |
51 |
| - let test_preamble_header = [ |
| 50 | + fn test_detect_preamble() -> anyhow::Result<()> { |
| 51 | + let test_preamble_header = &[ |
52 | 52 | 0, 16, 0, 0, 17, 0, 0, 0, 208, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
|
53 | 53 | ];
|
54 | 54 |
|
55 |
| - let (_, preamble_data) = LogPreamble::detect_preamble(&test_preamble_header).unwrap(); |
| 55 | + let (output, preamble_data) = LogPreamble::detect_preamble(test_preamble_header)?; |
56 | 56 |
|
| 57 | + assert_eq!(output, test_preamble_header); |
57 | 58 | assert_eq!(preamble_data.chunk_tag, 0x1000);
|
58 | 59 | assert_eq!(preamble_data.chunk_sub_tag, 0x11);
|
59 | 60 | assert_eq!(preamble_data.chunk_data_size, 0xd0);
|
60 | 61 |
|
61 |
| - let test_catalog_chunk = [11, 96, 0, 0, 17, 0, 0, 0, 176, 31, 0, 0, 0, 0, 0, 0]; |
62 |
| - let (_, preamble_data) = LogPreamble::detect_preamble(&test_catalog_chunk).unwrap(); |
| 62 | + let test_catalog_chunk = &[11, 96, 0, 0, 17, 0, 0, 0, 176, 31, 0, 0, 0, 0, 0, 0]; |
| 63 | + let (output, preamble_data) = LogPreamble::parse(test_catalog_chunk)?; |
63 | 64 |
|
| 65 | + assert_eq!(output.len(), 0); |
64 | 66 | assert_eq!(preamble_data.chunk_tag, 0x600b);
|
65 | 67 | assert_eq!(preamble_data.chunk_sub_tag, 0x11);
|
66 | 68 | assert_eq!(preamble_data.chunk_data_size, 0x1fb0);
|
| 69 | + |
| 70 | + Ok(()) |
67 | 71 | }
|
68 | 72 | }
|
0 commit comments