1use nom::{
2 bytes::complete::tag,
3 multi::{count, length_data, many1},
4 number::complete::{be_f32, be_i16, be_i32, be_i64, be_i8, be_u32},
5 IResult,
6};
7
8use crate::{Centroid, Frame, Frames, OpdFile, OpdHeader};
9
10pub fn parse(input: &[u8]) -> IResult<&[u8], OpdFile> {
11 let (input, _) = tag(b".opd".as_slice())(input)?;
12
13 let (input, json_header) = length_data(be_u32)(input)?;
14 let header: crate::OpdHeader = serde_json::from_slice(json_header).unwrap();
15
16 let (mut input, centroids) =
17 count(parse_centroid, header.directive.num_centroids.unwrap())(input)?;
18
19 let _base_offset = header.directive.num_centroids.unwrap() * 4 * 4;
20 let _frame_data_len = header.directive.precision * 3;
21
22 let frames = match header.directive.precision {
23 1 => {
24 let (next_input, frames) = parse_frame(input, &header, be_i8)?;
25 input = next_input;
26 Frames::I8(frames)
27 }
28 2 => {
29 let (next_input, frames) = parse_frame(input, &header, be_i16)?;
30 input = next_input;
31 Frames::I16(frames)
32 }
33 4 => {
34 let (next_input, frames) = parse_frame(input, &header, be_i32)?;
35 input = next_input;
36 Frames::I32(frames)
37 }
38 8 => {
39 let (next_input, frames) = parse_frame(input, &header, be_i64)?;
40 input = next_input;
41 Frames::I64(frames)
42 }
43 _ => {
44 unimplemented!()
45 }
46 };
47
48 Ok((
49 input,
50 OpdFile {
51 header,
52 centroids,
53 frames,
54 },
55 ))
56}
57
58type NumberParser<'a, NUM> = fn(input: &'a [u8]) -> IResult<&'a [u8], NUM>;
59
60pub fn parse_frame<'a, T>(
61 mut input: &'a [u8],
62 header: &OpdHeader,
63 number_parser: NumberParser<'a, T>,
64) -> IResult<&'a [u8], Vec<Frame<T>>> {
65 assert_eq!(header.directive.precision, std::mem::size_of::<T>());
66 let base_offset = header.directive.num_centroids.unwrap() * 4 * 4;
67
68 let mut frames = Vec::with_capacity(header.directive.frames.len());
69 for frame in header.directive.frames.windows(2) {
70 let start = (frame[0].offset - base_offset) / header.directive.precision;
71 let end = (frame[1].offset - base_offset) / header.directive.precision;
72 let len = end - start;
73
74 let (new_input, data) = count(number_parser, len)(input)?;
75 input = new_input;
76 frames.push(Frame {
77 time: frame[0].time,
78 data,
79 });
80 }
81 if let Some(last_frame) = header.directive.frames.last() {
82 let (rest, data) = many1(number_parser)(input)?;
83 frames.push(Frame {
84 time: last_frame.time,
85 data,
86 });
87 Ok((rest, frames))
88 } else {
89 Ok((input, frames))
90 }
91}
92
93pub fn parse_centroid(input: &[u8]) -> IResult<&[u8], Centroid> {
94 let (input, parent_id) = be_u32(input)?;
95 let (input, x) = be_f32(input)?;
96 let (input, y) = be_f32(input)?;
97 let (input, z) = be_f32(input)?;
98 Ok((
99 input,
100 Centroid {
101 parent_id,
102 offset: [x, y, z],
103 },
104 ))
105}