opd_parser/
parser.rs

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}