opd_parser/
lib.rs

1mod parser;
2
3pub use parser::parse;
4
5use serde::{Deserialize, Serialize};
6
7pub struct OpdFile {
8    pub header: OpdHeader,
9    pub centroids: Vec<Centroid>,
10    pub frames: Frames,
11}
12
13#[derive(Deserialize, Debug, Serialize)]
14pub struct OpdHeader {
15    pub version: String,
16    pub compressed: Option<String>,
17    #[serde(rename = "type")]
18    pub ty: String,
19    pub directive: OpdHeaderDirective,
20}
21
22#[derive(Clone)]
23pub struct Frame<T> {
24    pub time: f32,
25    pub data: Vec<T>,
26}
27
28impl<'a, T> IntoIterator for &'a Frame<T>
29where
30    T: Copy + Into<f32>,
31{
32    type IntoIter = FrameIterator<'a, T>;
33    type Item = [f32; 3];
34
35    fn into_iter(self) -> Self::IntoIter {
36        FrameIterator {
37            iter: self.data.iter(),
38        }
39    }
40}
41
42pub struct FrameIterator<'a, T> {
43    iter: std::slice::Iter<'a, T>,
44}
45
46impl<'a, T: Copy> Iterator for FrameIterator<'a, T>
47where
48    T: Into<f32>,
49{
50    type Item = [f32; 3];
51
52    fn next(&mut self) -> Option<Self::Item> {
53        let max_value: usize = (1 << (std::mem::size_of::<T>() * 8 - 1)) - 1;
54        let max_value = max_value as f32;
55        let arr: [f32; 3] = [
56            match self.iter.next() {
57                Some(a) => (*a).into() / max_value,
58                None => return None,
59            },
60            match self.iter.next() {
61                Some(a) => (*a).into() / max_value,
62                None => return None,
63            },
64            match self.iter.next() {
65                Some(a) => (*a).into() / max_value,
66                None => return None,
67            },
68        ];
69        Some(arr)
70    }
71}
72
73#[derive(Clone)]
74pub enum Frames {
75    I8(Vec<Frame<i8>>),
76    I16(Vec<Frame<i16>>),
77    I32(Vec<Frame<i32>>),
78    I64(Vec<Frame<i64>>),
79}
80
81#[derive(Deserialize, Debug, Serialize, Clone)]
82pub struct FrameMeta {
83    pub time: f32,
84    pub offset: usize,
85}
86
87#[derive(Deserialize, Debug, Serialize)]
88pub struct OpdHeaderDirective {
89    pub version: String,
90    pub meta: OpdHeaderDirectiveMeta,
91
92    #[serde(rename = "numCentroids")]
93    pub num_centroids: Option<usize>,
94    #[serde(rename = "hasCentroidVolumes")]
95    pub has_centroid_volumes: Option<bool>,
96
97    #[serde(rename = "numPoints")]
98    pub num_points: Option<usize>,
99
100    pub origin: OpdHeaderDirectiveOrigin,
101
102    pub precision: usize,
103    pub scale: [f32; 3],
104    pub frames: Vec<FrameMeta>,
105
106    pub index: Option<bool>,
107    #[serde(rename = "subCentroids")]
108    pub sub_centroids: Option<bool>,
109
110    #[serde(rename = "lastFrameCorrected")]
111    pub last_frame_corrected: Option<bool>,
112}
113
114#[derive(Deserialize, Debug, Serialize)]
115pub struct OpdHeaderDirectiveOrigin {
116    pub x: f64,
117    pub y: f64,
118    pub z: f64,
119}
120
121impl From<OpdHeaderDirectiveOrigin> for [f64; 3] {
122    fn from(value: OpdHeaderDirectiveOrigin) -> Self {
123        [value.x, value.y, value.z]
124    }
125}
126
127#[derive(Deserialize, Debug, Serialize)]
128pub struct OpdHeaderDirectiveMeta {
129    #[serde(rename = "projectId")]
130    pub project_id: String,
131
132    #[serde(rename = "projectName")]
133    pub project_name: String,
134}
135
136pub struct Centroid {
137    pub parent_id: u32,
138
139    /// Relative to origin defined in header
140    pub offset: [f32; 3],
141}