1use crate::{DType, PointField, SpatialError, SpatialResult};
2
3#[derive(Clone, Debug, PartialEq)]
5pub enum PointBuffer {
6 F32(Vec<f32>),
8 F64(Vec<f64>),
10 U8(Vec<u8>),
12 U16(Vec<u16>),
14 U32(Vec<u32>),
16 I32(Vec<i32>),
18}
19
20impl PointBuffer {
21 #[must_use]
23 pub fn with_capacity(dtype: DType, capacity: usize) -> Self {
24 match dtype {
25 DType::F32 | DType::F16 => Self::F32(Vec::with_capacity(capacity)),
26 DType::F64 => Self::F64(Vec::with_capacity(capacity)),
27 DType::U8 => Self::U8(Vec::with_capacity(capacity)),
28 DType::U16 => Self::U16(Vec::with_capacity(capacity)),
29 DType::U32 => Self::U32(Vec::with_capacity(capacity)),
30 DType::I32 => Self::I32(Vec::with_capacity(capacity)),
31 }
32 }
33
34 #[must_use]
36 pub fn from_f32(values: Vec<f32>) -> Self {
37 Self::F32(values)
38 }
39
40 #[must_use]
42 pub fn len(&self) -> usize {
43 match self {
44 Self::F32(values) => values.len(),
45 Self::F64(values) => values.len(),
46 Self::U8(values) => values.len(),
47 Self::U16(values) => values.len(),
48 Self::U32(values) => values.len(),
49 Self::I32(values) => values.len(),
50 }
51 }
52
53 #[must_use]
55 pub fn is_empty(&self) -> bool {
56 self.len() == 0
57 }
58
59 #[must_use]
61 pub fn dtype(&self) -> DType {
62 match self {
63 Self::F32(_) => DType::F32,
64 Self::F64(_) => DType::F64,
65 Self::U8(_) => DType::U8,
66 Self::U16(_) => DType::U16,
67 Self::U32(_) => DType::U32,
68 Self::I32(_) => DType::I32,
69 }
70 }
71
72 pub fn resize(&mut self, len: usize, field: &PointField) -> SpatialResult<()> {
74 if field.dtype != self.dtype() && !(field.dtype == DType::F16 && self.dtype() == DType::F32)
75 {
76 return Err(SpatialError::UnsupportedDType(field.dtype));
77 }
78 match self {
79 Self::F32(values) => values.resize(len, 0.0),
80 Self::F64(values) => values.resize(len, 0.0),
81 Self::U8(values) => values.resize(len, 0),
82 Self::U16(values) => values.resize(len, 0),
83 Self::U32(values) => values.resize(len, 0),
84 Self::I32(values) => values.resize(len, 0),
85 }
86 Ok(())
87 }
88
89 pub fn as_f32(&self) -> SpatialResult<&[f32]> {
91 match self {
92 Self::F32(values) => Ok(values),
93 _ => Err(SpatialError::UnsupportedDType(self.dtype())),
94 }
95 }
96
97 pub fn as_f32_mut(&mut self) -> SpatialResult<&mut Vec<f32>> {
99 match self {
100 Self::F32(values) => Ok(values),
101 _ => Err(SpatialError::UnsupportedDType(self.dtype())),
102 }
103 }
104
105 pub fn push_f32(&mut self, value: f32) -> SpatialResult<()> {
107 self.as_f32_mut()?.push(value);
108 Ok(())
109 }
110
111 pub fn push_f64(&mut self, value: f64) -> SpatialResult<()> {
113 match self {
114 Self::F64(values) => {
115 values.push(value);
116 Ok(())
117 }
118 _ => Err(SpatialError::UnsupportedDType(self.dtype())),
119 }
120 }
121
122 pub fn push_u8(&mut self, value: u8) -> SpatialResult<()> {
124 match self {
125 Self::U8(values) => {
126 values.push(value);
127 Ok(())
128 }
129 _ => Err(SpatialError::UnsupportedDType(self.dtype())),
130 }
131 }
132
133 pub fn push_u16(&mut self, value: u16) -> SpatialResult<()> {
135 match self {
136 Self::U16(values) => {
137 values.push(value);
138 Ok(())
139 }
140 _ => Err(SpatialError::UnsupportedDType(self.dtype())),
141 }
142 }
143
144 pub fn push_i32(&mut self, value: i32) -> SpatialResult<()> {
146 match self {
147 Self::I32(values) => {
148 values.push(value);
149 Ok(())
150 }
151 _ => Err(SpatialError::UnsupportedDType(self.dtype())),
152 }
153 }
154}
155
156#[derive(Clone, Debug, Default, PartialEq)]
158pub struct PointBufferSet {
159 buffers: Vec<(String, PointBuffer)>,
160}
161
162impl PointBufferSet {
163 #[must_use]
165 pub fn new() -> Self {
166 Self::default()
167 }
168
169 pub fn insert(&mut self, name: impl Into<String>, buffer: PointBuffer) {
171 let name = name.into();
172 if let Some((_, existing)) = self.buffers.iter_mut().find(|(key, _)| key == &name) {
173 *existing = buffer;
174 } else {
175 self.buffers.push((name, buffer));
176 }
177 }
178
179 #[must_use]
181 pub fn get(&self, name: &str) -> Option<&PointBuffer> {
182 self.buffers.iter().find(|(key, _)| key == name).map(|(_, buffer)| buffer)
183 }
184
185 pub fn get_mut(&mut self, name: &str) -> Option<&mut PointBuffer> {
187 self.buffers.iter_mut().find(|(key, _)| key == name).map(|(_, buffer)| buffer)
188 }
189
190 pub fn iter(&self) -> impl Iterator<Item = (&str, &PointBuffer)> {
192 self.buffers.iter().map(|(name, buffer)| (name.as_str(), buffer))
193 }
194}
195
196#[cfg(test)]
197mod tests {
198 use super::{PointBuffer, PointBufferSet};
199 use crate::{DType, PointField};
200
201 #[test]
202 fn resize_f32_buffer() {
203 let field = PointField::scalar("x", crate::FieldSemantic::PositionX, DType::F32);
204 let mut buffer = PointBuffer::with_capacity(DType::F32, 4);
205 buffer.resize(3, &field).unwrap();
206 assert_eq!(buffer.len(), 3);
207 }
208
209 #[test]
210 fn buffer_set_lookup() {
211 let mut set = PointBufferSet::new();
212 set.insert("x", PointBuffer::from_f32(vec![1.0, 2.0]));
213 assert_eq!(set.get("x").unwrap().len(), 2);
214 }
215}