pasture_core/containers/
attribute_iterators.rs1use std::marker::PhantomData;
2
3use crate::layout::{PointAttributeDefinition, PointAttributeMember, PrimitiveType};
4
5use super::point_buffer::{BorrowedBuffer, ColumnarBuffer, ColumnarBufferMut};
6
7pub struct AttributeIteratorByValue<'a, 'b, T: PrimitiveType, B: BorrowedBuffer<'a> + ?Sized>
10where
11 'a: 'b,
12{
13 buffer: &'b B,
14 attribute_member: &'b PointAttributeMember,
15 current_index: usize,
16 _phantom: PhantomData<&'a T>,
17}
18
19impl<'a, 'b, T: PrimitiveType, B: BorrowedBuffer<'a> + ?Sized>
20 AttributeIteratorByValue<'a, 'b, T, B>
21{
22 pub(crate) fn new(buffer: &'b B, attribute: &PointAttributeDefinition) -> Self {
23 Self {
24 attribute_member: buffer
25 .point_layout()
26 .get_attribute(attribute)
27 .expect("Attribute not found in PointLayout of buffer"),
28 buffer,
29 current_index: 0,
30 _phantom: Default::default(),
31 }
32 }
33}
34
35impl<'a, 'b, T: PrimitiveType, B: BorrowedBuffer<'a> + ?Sized> Iterator
36 for AttributeIteratorByValue<'a, 'b, T, B>
37{
38 type Item = T;
39
40 fn next(&mut self) -> Option<Self::Item> {
41 if self.current_index == self.buffer.len() {
42 None
43 } else {
44 let mut attribute = T::zeroed();
45 let attribute_bytes = bytemuck::bytes_of_mut(&mut attribute);
46 unsafe {
48 self.buffer.get_attribute_unchecked(
49 self.attribute_member,
50 self.current_index,
51 attribute_bytes,
52 );
53 }
54 self.current_index += 1;
55 Some(attribute)
56 }
57 }
58
59 fn nth(&mut self, n: usize) -> Option<Self::Item> {
60 self.current_index += n;
61 self.next()
62 }
63}
64
65pub struct AttributeIteratorByRef<'a, T: PrimitiveType> {
68 attribute_data: &'a [T],
69 current_index: usize,
70}
71
72impl<'a, T: PrimitiveType> AttributeIteratorByRef<'a, T> {
73 pub(crate) fn new<'b, B: ColumnarBuffer<'b> + ?Sized>(
74 buffer: &'a B,
75 attribute: &PointAttributeDefinition,
76 ) -> Self
77 where
78 'b: 'a,
79 {
80 let attribute_memory = buffer.get_attribute_range_ref(attribute, 0..buffer.len());
81 Self {
82 attribute_data: bytemuck::cast_slice(attribute_memory),
83 current_index: 0,
84 }
85 }
86}
87
88impl<'a, T: PrimitiveType> Iterator for AttributeIteratorByRef<'a, T> {
89 type Item = &'a T;
90
91 fn next(&mut self) -> Option<Self::Item> {
92 if self.current_index == self.attribute_data.len() {
93 None
94 } else {
95 let ret = &self.attribute_data[self.current_index];
96 self.current_index += 1;
97 Some(ret)
98 }
99 }
100
101 fn nth(&mut self, n: usize) -> Option<Self::Item> {
102 self.current_index += n;
103 self.next()
104 }
105}
106
107pub struct AttributeIteratorByMut<'a, T: PrimitiveType> {
110 attribute_data: &'a mut [T],
111 current_index: usize,
112}
113
114impl<'a, T: PrimitiveType> AttributeIteratorByMut<'a, T> {
115 pub(crate) fn new<'b, B: ColumnarBufferMut<'b> + ?Sized>(
116 buffer: &'a mut B,
117 attribute: &PointAttributeDefinition,
118 ) -> Self
119 where
120 'b: 'a,
121 {
122 let attribute_memory = buffer.get_attribute_range_mut(attribute, 0..buffer.len());
123 Self {
124 attribute_data: bytemuck::cast_slice_mut(attribute_memory),
125 current_index: 0,
126 }
127 }
128}
129
130impl<'a, T: PrimitiveType> Iterator for AttributeIteratorByMut<'a, T> {
131 type Item = &'a mut T;
132
133 fn next(&mut self) -> Option<Self::Item> {
134 if self.current_index == self.attribute_data.len() {
135 None
136 } else {
137 unsafe {
138 let attribute_ptr = self.attribute_data.as_mut_ptr().add(self.current_index);
139 self.current_index += 1;
140 Some(&mut *attribute_ptr)
141 }
142 }
143 }
144
145 fn nth(&mut self, n: usize) -> Option<Self::Item> {
146 self.current_index += n;
147 self.next()
148 }
149}
150
151#[cfg(test)]
152mod tests {
153 use nalgebra::Vector3;
154 use rand::{thread_rng, Rng};
155
156 use crate::{
157 containers::{BorrowedBufferExt, BorrowedMutBufferExt, HashMapBuffer},
158 layout::attributes::POSITION_3D,
159 test_utils::{CustomPointTypeSmall, DefaultPointDistribution},
160 };
161
162 #[test]
163 #[allow(clippy::iter_nth_zero)]
164 fn attribute_iterator_nth() {
165 const COUNT: usize = 16;
166 let mut points = thread_rng()
167 .sample_iter::<CustomPointTypeSmall, _>(DefaultPointDistribution)
168 .take(COUNT)
169 .collect::<HashMapBuffer>();
170 let mut points_clone = points.clone();
171
172 let positions_view = points.view_attribute::<Vector3<f64>>(&POSITION_3D);
173 {
174 let mut positions_iter = positions_view.clone().into_iter();
175 assert_eq!(positions_iter.nth(0), Some(positions_view.at(0)));
176 }
177 {
178 let mut positions_iter = positions_view.clone().into_iter();
179 assert_eq!(positions_iter.nth(6), Some(positions_view.at(6)));
180 }
181 {
182 let mut positions_iter = positions_view.clone().into_iter();
183 assert_eq!(positions_iter.nth(COUNT), None);
184 }
185 {
186 let mut positions_iter = positions_view.clone().into_iter();
187 positions_iter.nth(0);
188 assert_eq!(positions_iter.nth(0), Some(positions_view.at(1)));
189 }
190
191 {
192 let mut positions_iter = positions_view.iter();
193 assert_eq!(positions_iter.nth(0), Some(positions_view.at_ref(0)));
194 }
195 {
196 let mut positions_iter = positions_view.iter();
197 assert_eq!(positions_iter.nth(6), Some(positions_view.at_ref(6)));
198 }
199 {
200 let mut positions_iter = positions_view.iter();
201 assert_eq!(positions_iter.nth(COUNT), None);
202 }
203 {
204 let mut positions_iter = positions_view.iter();
205 positions_iter.nth(0);
206 assert_eq!(positions_iter.nth(0), Some(positions_view.at_ref(1)));
207 }
208
209 {
210 let mut positions_view_mut = points.view_attribute_mut::<Vector3<f64>>(&POSITION_3D);
211 let mut cloned_positions_view_mut =
212 points_clone.view_attribute_mut::<Vector3<f64>>(&POSITION_3D);
213 let mut positions_iter = positions_view_mut.iter_mut();
214 assert_eq!(
215 positions_iter.nth(0),
216 Some(cloned_positions_view_mut.at_mut(0))
217 );
218 }
219 {
220 let mut positions_view_mut = points.view_attribute_mut::<Vector3<f64>>(&POSITION_3D);
221 let mut cloned_positions_view_mut =
222 points_clone.view_attribute_mut::<Vector3<f64>>(&POSITION_3D);
223 let mut positions_iter = positions_view_mut.iter_mut();
224 assert_eq!(
225 positions_iter.nth(6),
226 Some(cloned_positions_view_mut.at_mut(6))
227 );
228 }
229 {
230 let mut positions_view_mut = points.view_attribute_mut::<Vector3<f64>>(&POSITION_3D);
231 let mut positions_iter = positions_view_mut.iter_mut();
232 assert_eq!(positions_iter.nth(COUNT), None);
233 }
234 {
235 let mut positions_view_mut = points.view_attribute_mut::<Vector3<f64>>(&POSITION_3D);
236 let mut cloned_positions_view_mut =
237 points_clone.view_attribute_mut::<Vector3<f64>>(&POSITION_3D);
238 let mut positions_iter = positions_view_mut.iter_mut();
239 positions_iter.nth(0);
240 assert_eq!(
241 positions_iter.nth(0),
242 Some(cloned_positions_view_mut.at_mut(1))
243 );
244 }
245 }
246}