1use anyhow::Result;
2use std::{collections::HashMap, iter::FromIterator, ops::Range};
3
4use crate::layout::{
5 PointAttributeDefinition, PointAttributeMember, PointLayout, PointType, PrimitiveType,
6};
7
8use super::{
9 buffer_views::{AttributeView, AttributeViewMut, PointView, PointViewMut},
10 AttributeViewConverting, BufferSliceColumnar, BufferSliceColumnarMut, BufferSliceInterleaved,
11 BufferSliceInterleavedMut, RawAttributeView, RawAttributeViewMut, SliceBuffer, SliceBufferMut,
12};
13
14pub trait BorrowedBuffer<'a> {
18 fn len(&self) -> usize;
30 fn is_empty(&self) -> bool {
42 self.len() == 0
43 }
44 fn point_layout(&self) -> &PointLayout;
58 fn get_point(&self, index: usize, data: &mut [u8]);
65 fn get_point_range(&self, range: Range<usize>, data: &mut [u8]);
72 fn get_attribute(&self, attribute: &PointAttributeDefinition, index: usize, data: &mut [u8]) {
82 let attribute_member = self
83 .point_layout()
84 .get_attribute(attribute)
85 .expect("Attribute not found in PointLayout of this buffer");
86 unsafe {
88 self.get_attribute_unchecked(attribute_member, index, data);
89 }
90 }
91 fn get_attribute_range(
103 &self,
104 attribute: &PointAttributeDefinition,
105 point_range: Range<usize>,
106 data: &mut [u8],
107 ) {
108 let attribute_member = self
109 .point_layout()
110 .get_attribute(attribute)
111 .expect("Attribute not found in PointLayout of this buffer");
112 let attribute_size = attribute_member.size() as usize;
113 let first_point = point_range.start;
114 for point_index in point_range {
115 let zero_based_index = point_index - first_point;
116 let data_slice = &mut data
117 [(zero_based_index * attribute_size)..((zero_based_index + 1) * attribute_size)];
118 unsafe {
120 self.get_attribute_unchecked(attribute_member, point_index, data_slice);
121 }
122 }
123 }
124
125 unsafe fn get_attribute_unchecked(
135 &self,
136 attribute_member: &PointAttributeMember,
137 index: usize,
138 data: &mut [u8],
139 );
140
141 fn as_interleaved(&self) -> Option<&dyn InterleavedBuffer<'a>> {
144 None
145 }
146
147 fn as_columnar(&self) -> Option<&dyn ColumnarBuffer<'a>> {
150 None
151 }
152}
153
154pub trait BorrowedMutBuffer<'a>: BorrowedBuffer<'a> {
160 unsafe fn set_point(&mut self, index: usize, point_data: &[u8]);
172 unsafe fn set_point_range(&mut self, point_range: Range<usize>, point_data: &[u8]);
187 unsafe fn set_attribute(
200 &mut self,
201 attribute: &PointAttributeDefinition,
202 index: usize,
203 attribute_data: &[u8],
204 );
205 unsafe fn set_attribute_range(
219 &mut self,
220 attribute: &PointAttributeDefinition,
221 point_range: Range<usize>,
222 attribute_data: &[u8],
223 );
224 fn swap(&mut self, from_index: usize, to_index: usize);
230
231 fn as_interleaved_mut(&mut self) -> Option<&mut dyn InterleavedBufferMut<'a>> {
234 None
235 }
236
237 fn as_columnar_mut(&mut self) -> Option<&mut dyn ColumnarBufferMut<'a>> {
240 None
241 }
242}
243
244pub trait OwningBuffer<'a>: BorrowedMutBuffer<'a> {
250 unsafe fn push_points(&mut self, point_bytes: &[u8]);
261 fn resize(&mut self, count: usize);
264 fn clear(&mut self);
266}
267
268pub trait BorrowedBufferExt<'a>: BorrowedBuffer<'a> {
288 fn view<'b, T: PointType>(&'b self) -> PointView<'a, 'b, Self, T>
294 where
295 'a: 'b,
296 {
297 PointView::new(self)
298 }
299
300 fn view_attribute<'b, T: PrimitiveType>(
307 &'b self,
308 attribute: &PointAttributeDefinition,
309 ) -> AttributeView<'a, 'b, Self, T>
310 where
311 'a: 'b,
312 {
313 AttributeView::new(self, attribute)
314 }
315
316 fn view_attribute_with_conversion<'b, T: PrimitiveType>(
323 &'b self,
324 attribute: &PointAttributeDefinition,
325 ) -> Result<AttributeViewConverting<'a, 'b, Self, T>>
326 where
327 'a: 'b,
328 {
329 AttributeViewConverting::new(self, attribute)
330 }
331}
332
333impl<'a, T: BorrowedBuffer<'a>> BorrowedBufferExt<'a> for T {}
334impl<'a> BorrowedBufferExt<'a> for dyn BorrowedBuffer<'a> + 'a {}
335impl<'a> BorrowedBufferExt<'a> for dyn BorrowedMutBuffer<'a> + 'a {}
336impl<'a> BorrowedBufferExt<'a> for dyn InterleavedBuffer<'a> + 'a {}
340impl<'a> BorrowedBufferExt<'a> for dyn InterleavedBufferMut<'a> + 'a {}
341impl<'a> BorrowedBufferExt<'a> for dyn ColumnarBuffer<'a> + 'a {}
342impl<'a> BorrowedBufferExt<'a> for dyn ColumnarBufferMut<'a> + 'a {}
343
344pub trait BorrowedMutBufferExt<'a>: BorrowedMutBuffer<'a> {
347 fn view_mut<'b, T: PointType>(&'b mut self) -> PointViewMut<'a, 'b, Self, T>
353 where
354 'a: 'b,
355 {
356 PointViewMut::new(self)
357 }
358
359 fn view_attribute_mut<'b, T: PrimitiveType>(
367 &'b mut self,
368 attribute: &PointAttributeDefinition,
369 ) -> AttributeViewMut<'a, 'b, Self, T>
370 where
371 'a: 'b,
372 {
373 AttributeViewMut::new(self, attribute)
374 }
375
376 fn transform_attribute<'b, T: PrimitiveType, F: Fn(usize, T) -> T>(
392 &'b mut self,
393 attribute: &PointAttributeDefinition,
394 func: F,
395 ) where
396 'a: 'b,
397 {
398 let num_points = self.len();
399 let mut attribute_view = self.view_attribute_mut(attribute);
400 for point_index in 0..num_points {
401 let attribute_value = attribute_view.at(point_index);
402 attribute_view.set_at(point_index, func(point_index, attribute_value));
403 }
404 }
405}
406
407impl<'a, T: BorrowedMutBuffer<'a>> BorrowedMutBufferExt<'a> for T {}
408impl<'a> BorrowedMutBufferExt<'a> for dyn BorrowedMutBuffer<'a> + 'a {}
409impl<'a> BorrowedMutBufferExt<'a> for dyn InterleavedBufferMut<'a> + 'a {}
411impl<'a> BorrowedMutBufferExt<'a> for dyn ColumnarBufferMut<'a> + 'a {}
412
413pub trait OwningBufferExt<'a>: OwningBuffer<'a> {
414 fn append<'b, B: BorrowedBuffer<'b> + ?Sized>(&mut self, other: &'_ B) {
420 assert_eq!(self.point_layout(), other.point_layout());
421
422 if let (Some(_), Some(other_interleaved)) =
430 (self.as_interleaved_mut(), other.as_interleaved())
431 {
432 unsafe {
435 self.push_points(other_interleaved.get_point_range_ref(0..other.len()));
436 }
437 return;
438 }
439
440 let old_self_len = self.len();
441 let new_self_len = old_self_len + other.len();
442 self.resize(new_self_len);
443
444 if let Some(self_interleaved) = self.as_interleaved_mut() {
445 let point_size = self_interleaved.point_layout().size_of_point_entry() as usize;
446 let new_points = self_interleaved.get_point_range_mut(old_self_len..new_self_len);
447 for (index, new_point) in new_points.chunks_exact_mut(point_size).enumerate() {
448 other.get_point(index, new_point);
449 }
450 } else if let Some(self_columnar) = self.as_columnar_mut() {
451 if let Some(other_columnar) = other.as_columnar() {
452 for attribute in other.point_layout().attributes() {
453 unsafe {
455 self_columnar.set_attribute_range(
456 attribute.attribute_definition(),
457 old_self_len..new_self_len,
458 other_columnar.get_attribute_range_ref(
459 attribute.attribute_definition(),
460 0..other_columnar.len(),
461 ),
462 );
463 }
464 }
465 } else {
466 for attribute in other.point_layout().attributes() {
467 let new_attributes = self_columnar.get_attribute_range_mut(
468 attribute.attribute_definition(),
469 old_self_len..new_self_len,
470 );
471 for (index, new_attribute) in new_attributes
472 .chunks_exact_mut(attribute.size() as usize)
473 .enumerate()
474 {
475 other.get_attribute(attribute.attribute_definition(), index, new_attribute);
476 }
477 }
478 }
479 } else {
480 let mut point_buffer = vec![0; self.point_layout().size_of_point_entry() as usize];
481 for point_index in 0..other.len() {
482 other.get_point(point_index, &mut point_buffer);
483 unsafe {
485 self.set_point(old_self_len + point_index, &point_buffer);
486 }
487 }
488 }
489 }
490}
491
492impl<'a, T: OwningBuffer<'a>> OwningBufferExt<'a> for T {}
493impl<'a> OwningBufferExt<'a> for dyn OwningBuffer<'a> + 'a {}
494
495pub trait MakeBufferFromLayout<'a>: BorrowedBuffer<'a> + Sized {
498 fn new_from_layout(point_layout: PointLayout) -> Self;
500}
501
502pub trait InterleavedBuffer<'a>: BorrowedBuffer<'a> {
505 fn get_point_ref<'b>(&'b self, index: usize) -> &'b [u8]
516 where
517 'a: 'b;
518 fn get_point_range_ref<'b>(&'b self, range: Range<usize>) -> &'b [u8]
525 where
526 'a: 'b;
527
528 fn view_raw_attribute<'b>(&'b self, attribute: &PointAttributeMember) -> RawAttributeView<'b>
532 where
533 'a: 'b,
534 {
535 RawAttributeView::from_interleaved_buffer(self, attribute)
536 }
537}
538
539pub trait InterleavedBufferMut<'a>: InterleavedBuffer<'a> + BorrowedMutBuffer<'a> {
542 fn get_point_mut<'b>(&'b mut self, index: usize) -> &'b mut [u8]
548 where
549 'a: 'b;
550 fn get_point_range_mut<'b>(&'b mut self, range: Range<usize>) -> &'b mut [u8]
556 where
557 'a: 'b;
558
559 fn view_raw_attribute_mut<'b>(
561 &'b mut self,
562 attribute: &PointAttributeMember,
563 ) -> RawAttributeViewMut<'b>
564 where
565 'a: 'b,
566 {
567 RawAttributeViewMut::from_interleaved_buffer(self, attribute)
568 }
569}
570
571pub trait ColumnarBuffer<'a>: BorrowedBuffer<'a> {
574 fn get_attribute_ref<'b>(
581 &'b self,
582 attribute: &PointAttributeDefinition,
583 index: usize,
584 ) -> &'b [u8]
585 where
586 'a: 'b;
587 fn get_attribute_range_ref<'b>(
594 &'b self,
595 attribute: &PointAttributeDefinition,
596 range: Range<usize>,
597 ) -> &'b [u8]
598 where
599 'a: 'b;
600
601 fn view_raw_attribute<'b>(&'b self, attribute: &PointAttributeMember) -> RawAttributeView<'b>
605 where
606 'a: 'b,
607 {
608 RawAttributeView::from_columnar_buffer(self, attribute.attribute_definition())
609 }
610}
611
612pub trait ColumnarBufferMut<'a>: ColumnarBuffer<'a> + BorrowedMutBuffer<'a> {
615 fn get_attribute_mut<'b>(
623 &'b mut self,
624 attribute: &PointAttributeDefinition,
625 index: usize,
626 ) -> &'b mut [u8]
627 where
628 'a: 'b;
629 fn get_attribute_range_mut<'b>(
637 &'b mut self,
638 attribute: &PointAttributeDefinition,
639 range: Range<usize>,
640 ) -> &'b mut [u8]
641 where
642 'a: 'b;
643
644 fn view_raw_attribute_mut<'b>(
646 &'b mut self,
647 attribute: &PointAttributeMember,
648 ) -> RawAttributeViewMut<'b>
649 where
650 'a: 'b,
651 {
652 RawAttributeViewMut::from_columnar_buffer(self, attribute.attribute_definition())
653 }
654}
655
656#[derive(Debug, Clone, PartialEq, Eq, Hash)]
659pub struct VectorBuffer {
660 storage: Vec<u8>,
661 point_layout: PointLayout,
662 length: usize,
663}
664
665impl VectorBuffer {
666 pub fn with_capacity(capacity: usize, point_layout: PointLayout) -> Self {
669 let required_bytes = capacity * point_layout.size_of_point_entry() as usize;
670 Self {
671 point_layout,
672 storage: Vec::with_capacity(required_bytes),
673 length: 0,
674 }
675 }
676
677 fn get_byte_range_of_point(&self, point_index: usize) -> Range<usize> {
678 let size_of_point = self.point_layout.size_of_point_entry() as usize;
679 (point_index * size_of_point)..((point_index + 1) * size_of_point)
680 }
681
682 fn get_byte_range_of_points(&self, points_range: Range<usize>) -> Range<usize> {
683 let size_of_point = self.point_layout.size_of_point_entry() as usize;
684 (points_range.start * size_of_point)..(points_range.end * size_of_point)
685 }
686
687 fn get_byte_range_of_attribute(
688 &self,
689 point_index: usize,
690 attribute: &PointAttributeMember,
691 ) -> Range<usize> {
692 let start_byte = (point_index * self.point_layout.size_of_point_entry() as usize)
693 + attribute.offset() as usize;
694 let end_byte = start_byte + attribute.size() as usize;
695 start_byte..end_byte
696 }
697}
698
699impl<'a> MakeBufferFromLayout<'a> for VectorBuffer {
700 fn new_from_layout(point_layout: PointLayout) -> Self {
701 Self {
702 point_layout,
703 storage: Default::default(),
704 length: 0,
705 }
706 }
707}
708
709impl<'a> BorrowedBuffer<'a> for VectorBuffer
710where
711 VectorBuffer: 'a,
712{
713 fn len(&self) -> usize {
714 self.length
715 }
716
717 fn point_layout(&self) -> &PointLayout {
718 &self.point_layout
719 }
720
721 fn get_point(&self, index: usize, data: &mut [u8]) {
722 let point_ref = self.get_point_ref(index);
723 data.copy_from_slice(point_ref);
724 }
725
726 fn get_point_range(&self, range: Range<usize>, data: &mut [u8]) {
727 let points_ref = self.get_point_range_ref(range);
728 data.copy_from_slice(points_ref);
729 }
730
731 unsafe fn get_attribute_unchecked(
732 &self,
733 attribute_member: &PointAttributeMember,
734 index: usize,
735 data: &mut [u8],
736 ) {
737 let byte_range = self.get_byte_range_of_attribute(index, attribute_member);
738 data.copy_from_slice(&self.storage[byte_range]);
739 }
740
741 fn as_interleaved(&self) -> Option<&dyn InterleavedBuffer<'a>> {
742 Some(self)
743 }
744}
745
746impl<'a> BorrowedMutBuffer<'a> for VectorBuffer
747where
748 VectorBuffer: 'a,
749{
750 unsafe fn set_point(&mut self, index: usize, point_data: &[u8]) {
751 let point_bytes = self.get_point_mut(index);
752 point_bytes.copy_from_slice(point_data);
753 }
754
755 unsafe fn set_attribute(
756 &mut self,
757 attribute: &PointAttributeDefinition,
758 index: usize,
759 attribute_data: &[u8],
760 ) {
761 let attribute_member = self
762 .point_layout
763 .get_attribute(attribute)
764 .expect("Attribute not found in PointLayout of this buffer");
765 let attribute_byte_range = self.get_byte_range_of_attribute(index, attribute_member);
766 let attribute_bytes = &mut self.storage[attribute_byte_range];
767 attribute_bytes.copy_from_slice(attribute_data);
768 }
769
770 fn swap(&mut self, from_index: usize, to_index: usize) {
771 assert!(from_index < self.len());
772 assert!(to_index < self.len());
773 if from_index == to_index {
774 return;
775 }
776 let size_of_point = self.point_layout.size_of_point_entry() as usize;
777 unsafe {
779 let from_ptr = self.storage.as_mut_ptr().add(from_index * size_of_point);
780 let to_ptr = self.storage.as_mut_ptr().add(to_index * size_of_point);
781 std::ptr::swap_nonoverlapping(from_ptr, to_ptr, size_of_point);
782 }
783 }
784
785 unsafe fn set_point_range(&mut self, point_range: Range<usize>, point_data: &[u8]) {
786 let point_bytes = self.get_point_range_mut(point_range);
787 point_bytes.copy_from_slice(point_data);
788 }
789
790 unsafe fn set_attribute_range(
791 &mut self,
792 attribute: &PointAttributeDefinition,
793 point_range: Range<usize>,
794 attribute_data: &[u8],
795 ) {
796 let attribute_member = self
797 .point_layout
798 .get_attribute(attribute)
799 .expect("Attribute not found in PointLayout of this buffer");
800 let attribute_size = attribute_member.size() as usize;
801 let first_point = point_range.start;
802 for point_index in point_range {
803 let zero_based_index = point_index - first_point;
804 let src_slice = &attribute_data
805 [(zero_based_index * attribute_size)..((zero_based_index + 1) * attribute_size)];
806 let attribute_byte_range =
807 self.get_byte_range_of_attribute(point_index, attribute_member);
808 let attribute_bytes = &mut self.storage[attribute_byte_range];
809 attribute_bytes.copy_from_slice(src_slice);
810 }
811 }
812
813 fn as_interleaved_mut(&mut self) -> Option<&mut dyn InterleavedBufferMut<'a>> {
814 Some(self)
815 }
816}
817
818impl<'a> OwningBuffer<'a> for VectorBuffer
819where
820 VectorBuffer: 'a,
821{
822 unsafe fn push_points(&mut self, point_bytes: &[u8]) {
823 let size_of_point = self.point_layout.size_of_point_entry() as usize;
824 if size_of_point == 0 {
825 assert_eq!(0, point_bytes.len());
826 } else {
827 assert_eq!(point_bytes.len() % size_of_point, 0);
828 self.storage.extend_from_slice(point_bytes);
829 self.length += point_bytes.len() / size_of_point;
830 }
831 }
832
833 fn resize(&mut self, count: usize) {
834 let size_of_point = self.point_layout.size_of_point_entry() as usize;
835 self.storage.resize(count * size_of_point, 0);
836 self.length = count;
837 }
838
839 fn clear(&mut self) {
840 self.storage.clear();
841 self.length = 0;
842 }
843}
844
845impl<'a> InterleavedBuffer<'a> for VectorBuffer
846where
847 VectorBuffer: 'a,
848{
849 fn get_point_ref<'b>(&'b self, index: usize) -> &'b [u8]
850 where
851 'a: 'b,
852 {
853 &self.storage[self.get_byte_range_of_point(index)]
854 }
855
856 fn get_point_range_ref<'b>(&'b self, range: Range<usize>) -> &'b [u8]
857 where
858 'a: 'b,
859 {
860 &self.storage[self.get_byte_range_of_points(range)]
861 }
862}
863
864impl<'a> InterleavedBufferMut<'a> for VectorBuffer
865where
866 VectorBuffer: 'a,
867{
868 fn get_point_mut<'b>(&'b mut self, index: usize) -> &'b mut [u8]
869 where
870 'a: 'b,
871 {
872 let byte_range = self.get_byte_range_of_point(index);
873 &mut self.storage[byte_range]
874 }
875
876 fn get_point_range_mut<'b>(&'b mut self, range: Range<usize>) -> &'b mut [u8]
877 where
878 'a: 'b,
879 {
880 let byte_range = self.get_byte_range_of_points(range);
881 &mut self.storage[byte_range]
882 }
883}
884
885impl<'a> SliceBuffer<'a> for VectorBuffer
886where
887 Self: 'a,
888{
889 type SliceType = BufferSliceInterleaved<'a, Self>;
890
891 fn slice(&'a self, range: Range<usize>) -> Self::SliceType {
892 BufferSliceInterleaved::new(self, range)
893 }
894}
895
896impl<'a> SliceBufferMut<'a> for VectorBuffer
897where
898 Self: 'a,
899{
900 type SliceTypeMut = BufferSliceInterleavedMut<'a, Self>;
901
902 fn slice_mut(&'a mut self, range: Range<usize>) -> Self::SliceTypeMut {
903 BufferSliceInterleavedMut::new(self, range)
904 }
905}
906
907impl<T: PointType> FromIterator<T> for VectorBuffer {
908 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
909 let point_layout = T::layout();
910 let iter = iter.into_iter();
911 let (_, maybe_known_length) = iter.size_hint();
912 if let Some(known_length) = maybe_known_length {
913 let num_bytes = known_length * point_layout.size_of_point_entry() as usize;
914 let storage = vec![0; num_bytes];
915 let mut buffer = Self {
916 point_layout,
917 storage,
918 length: known_length,
919 };
920 iter.enumerate().for_each(|(index, point)| {
922 let point_bytes = bytemuck::bytes_of(&point);
923 unsafe {
925 buffer.set_point(index, point_bytes);
926 }
927 });
928 buffer
929 } else {
930 let mut buffer = Self {
931 point_layout,
932 storage: Default::default(),
933 length: 0,
934 };
935 iter.for_each(|point| {
936 let point_bytes = bytemuck::bytes_of(&point);
937 unsafe {
939 buffer.push_points(point_bytes);
940 }
941 });
942 buffer
943 }
944 }
945}
946
947pub struct HashMapBufferAttributePusher<'a> {
951 attributes_storage: HashMap<PointAttributeDefinition, Vec<u8>>,
952 num_new_points: Option<usize>,
953 buffer: &'a mut HashMapBuffer,
954}
955
956impl<'a> HashMapBufferAttributePusher<'a> {
957 pub(crate) fn new(buffer: &'a mut HashMapBuffer) -> Self {
958 let attributes_storage = buffer
959 .point_layout()
960 .attributes()
961 .map(|attribute| (attribute.attribute_definition().clone(), vec![]))
962 .collect();
963 Self {
964 attributes_storage,
965 num_new_points: None,
966 buffer,
967 }
968 }
969
970 pub fn push_attribute_range<T: PrimitiveType>(
981 &mut self,
982 attribute: &PointAttributeDefinition,
983 data: &[T],
984 ) {
985 assert_eq!(T::data_type(), attribute.datatype());
986 let storage = self
987 .attributes_storage
988 .get_mut(attribute)
989 .expect("Attribute not found in PointLayout of this buffer");
990 if let Some(point_count) = self.num_new_points {
991 assert_eq!(point_count, data.len());
992 } else {
993 self.num_new_points = Some(data.len());
994 }
995 storage.extend_from_slice(bytemuck::cast_slice(data));
996 }
997
998 pub fn done(self) {
1006 let num_new_points = self.num_new_points.unwrap_or(0);
1007 if num_new_points == 0 {
1008 return;
1009 }
1010
1011 assert!(self
1014 .attributes_storage
1015 .values()
1016 .all(|vector| !vector.is_empty()));
1017
1018 for (attribute, mut data) in self.attributes_storage {
1019 let buffer_storage = self.buffer.attributes_storage.get_mut(&attribute).unwrap();
1021 buffer_storage.append(&mut data);
1022 }
1023
1024 self.buffer.length += num_new_points;
1025 }
1026}
1027
1028#[derive(Debug, Clone, PartialEq, Eq)]
1031pub struct HashMapBuffer {
1032 attributes_storage: HashMap<PointAttributeDefinition, Vec<u8>>,
1033 point_layout: PointLayout,
1034 length: usize,
1035}
1036
1037impl HashMapBuffer {
1038 pub fn with_capacity(capacity: usize, point_layout: PointLayout) -> Self {
1041 let attributes_storage = point_layout
1042 .attributes()
1043 .map(|attribute| {
1044 let bytes_for_attribute = capacity * attribute.size() as usize;
1045 (
1046 attribute.attribute_definition().clone(),
1047 Vec::with_capacity(bytes_for_attribute),
1048 )
1049 })
1050 .collect();
1051 Self {
1052 attributes_storage,
1053 point_layout,
1054 length: 0,
1055 }
1056 }
1057
1058 pub fn begin_push_attributes(&mut self) -> HashMapBufferAttributePusher<'_> {
1060 HashMapBufferAttributePusher::new(self)
1061 }
1062
1063 pub fn filter<
1065 B: for<'a> OwningBuffer<'a> + for<'a> MakeBufferFromLayout<'a>,
1066 F: Fn(usize) -> bool,
1067 >(
1068 &self,
1069 predicate: F,
1070 ) -> B {
1071 let num_matches = (0..self.len()).filter(|idx| predicate(*idx)).count();
1072 let mut filtered_points = B::new_from_layout(self.point_layout.clone());
1073 filtered_points.resize(num_matches);
1074 self.filter_into(&mut filtered_points, predicate, Some(num_matches));
1075 filtered_points
1076 }
1077
1078 pub fn filter_into<B: for<'a> BorrowedMutBuffer<'a>, F: Fn(usize) -> bool>(
1085 &self,
1086 buffer: &mut B,
1087 predicate: F,
1088 num_matches_hint: Option<usize>,
1089 ) {
1090 if buffer.point_layout() != self.point_layout() {
1091 panic!("PointLayouts must match");
1092 }
1093 let num_matches = num_matches_hint
1094 .unwrap_or_else(|| (0..self.len()).filter(|idx| predicate(*idx)).count());
1095 if buffer.len() < num_matches {
1096 panic!("buffer.len() must be at least as large as the number of predicate matches");
1097 }
1098 if let Some(columnar_buffer) = buffer.as_columnar_mut() {
1099 for attribute in self.point_layout.attributes() {
1100 let src_attribute_data =
1101 self.get_attribute_range_ref(attribute.attribute_definition(), 0..self.len());
1102 let dst_attribute_data = columnar_buffer
1103 .get_attribute_range_mut(attribute.attribute_definition(), 0..num_matches);
1104 let stride = attribute.size() as usize;
1105 for (dst_index, src_index) in
1106 (0..self.len()).filter(|idx| predicate(*idx)).enumerate()
1107 {
1108 dst_attribute_data[(dst_index * stride)..((dst_index + 1) * stride)]
1109 .copy_from_slice(
1110 &src_attribute_data[(src_index * stride)..((src_index + 1) * stride)],
1111 );
1112 }
1113 }
1114 } else if let Some(interleaved_buffer) = buffer.as_interleaved_mut() {
1115 let dst_data = interleaved_buffer.get_point_range_mut(0..num_matches);
1116 for attribute in self.point_layout.attributes() {
1117 let src_attribute_data =
1118 self.get_attribute_range_ref(attribute.attribute_definition(), 0..self.len());
1119 let src_stride = attribute.size() as usize;
1120 let dst_offset = attribute.offset() as usize;
1121 let dst_stride = self.point_layout.size_of_point_entry() as usize;
1122 for (dst_index, src_index) in
1123 (0..self.len()).filter(|idx| predicate(*idx)).enumerate()
1124 {
1125 let dst_attribute_start = dst_offset + (dst_index * dst_stride);
1126 let dst_point_range = dst_attribute_start..(dst_attribute_start + src_stride);
1127 dst_data[dst_point_range].copy_from_slice(
1128 &src_attribute_data
1129 [(src_index * src_stride)..((src_index + 1) * src_stride)],
1130 );
1131 }
1132 }
1133 } else {
1134 unimplemented!()
1135 }
1136 }
1137
1138 fn get_byte_range_for_attribute(
1139 point_index: usize,
1140 attribute: &PointAttributeDefinition,
1141 ) -> Range<usize> {
1142 let attribute_size = attribute.size() as usize;
1143 (point_index * attribute_size)..((point_index + 1) * attribute_size)
1144 }
1145
1146 fn get_byte_range_for_attributes(
1147 points_range: Range<usize>,
1148 attribute: &PointAttributeDefinition,
1149 ) -> Range<usize> {
1150 let attribute_size = attribute.size() as usize;
1151 (points_range.start * attribute_size)..(points_range.end * attribute_size)
1152 }
1153}
1154
1155impl<'a> MakeBufferFromLayout<'a> for HashMapBuffer {
1156 fn new_from_layout(point_layout: PointLayout) -> Self {
1157 let attributes_storage = point_layout
1158 .attributes()
1159 .map(|attribute| (attribute.attribute_definition().clone(), Vec::default()))
1160 .collect();
1161 Self {
1162 attributes_storage,
1163 point_layout,
1164 length: 0,
1165 }
1166 }
1167}
1168
1169impl<'a> BorrowedBuffer<'a> for HashMapBuffer
1170where
1171 HashMapBuffer: 'a,
1172{
1173 fn len(&self) -> usize {
1174 self.length
1175 }
1176
1177 fn point_layout(&self) -> &PointLayout {
1178 &self.point_layout
1179 }
1180
1181 fn get_point(&self, index: usize, data: &mut [u8]) {
1182 for attribute in self.point_layout.attributes() {
1183 let attribute_storage = self
1184 .attributes_storage
1185 .get(attribute.attribute_definition())
1186 .expect("Attribute not found within storage of this PointBuffer");
1187 let src_slice = &attribute_storage
1188 [Self::get_byte_range_for_attribute(index, attribute.attribute_definition())];
1189 let dst_slice = &mut data[attribute.byte_range_within_point()];
1190 dst_slice.copy_from_slice(src_slice);
1191 }
1192 }
1193
1194 fn get_point_range(&self, range: Range<usize>, data: &mut [u8]) {
1195 let size_of_point = self.point_layout.size_of_point_entry() as usize;
1196 for attribute in self.point_layout.attributes() {
1197 let attribute_storage = self
1198 .attributes_storage
1199 .get(attribute.attribute_definition())
1200 .expect("Attribute not found within storage of this PointBuffer");
1201 for point_index in range.clone() {
1202 let src_slice = &attribute_storage[Self::get_byte_range_for_attribute(
1203 point_index,
1204 attribute.attribute_definition(),
1205 )];
1206 let dst_point_slice = &mut data[((point_index - range.start) * size_of_point)..];
1207 let dst_slice = &mut dst_point_slice[attribute.byte_range_within_point()];
1208 dst_slice.copy_from_slice(src_slice);
1209 }
1210 }
1211 }
1212
1213 fn get_attribute(&self, attribute: &PointAttributeDefinition, index: usize, data: &mut [u8]) {
1214 let memory = self
1215 .attributes_storage
1216 .get(attribute)
1217 .expect("Attribute not found in PointLayout of this buffer");
1218 let attribute_byte_range = Self::get_byte_range_for_attribute(index, attribute);
1219 data.copy_from_slice(&memory[attribute_byte_range]);
1220 }
1221
1222 unsafe fn get_attribute_unchecked(
1223 &self,
1224 attribute_member: &PointAttributeMember,
1225 index: usize,
1226 data: &mut [u8],
1227 ) {
1228 let memory = self
1229 .attributes_storage
1230 .get(attribute_member.attribute_definition())
1231 .expect("Attribute not found in PointLayout of this buffer");
1232 let attribute_byte_range =
1233 Self::get_byte_range_for_attribute(index, attribute_member.attribute_definition());
1234 data.copy_from_slice(&memory[attribute_byte_range]);
1235 }
1236
1237 fn as_columnar(&self) -> Option<&dyn ColumnarBuffer<'a>> {
1238 Some(self)
1239 }
1240}
1241
1242impl<'a> BorrowedMutBuffer<'a> for HashMapBuffer
1243where
1244 HashMapBuffer: 'a,
1245{
1246 unsafe fn set_point(&mut self, index: usize, point_data: &[u8]) {
1247 for attribute in self.point_layout.attributes() {
1248 let attribute_definition = attribute.attribute_definition();
1249 let attribute_byte_range =
1250 Self::get_byte_range_for_attribute(index, attribute_definition);
1251 let attribute_storage = self
1252 .attributes_storage
1253 .get_mut(attribute_definition)
1254 .expect("Attribute not found within storage of this PointBuffer");
1255 let dst_slice = &mut attribute_storage[attribute_byte_range];
1256 let src_slice = &point_data[attribute.byte_range_within_point()];
1257 dst_slice.copy_from_slice(src_slice);
1258 }
1259 }
1260
1261 unsafe fn set_attribute(
1262 &mut self,
1263 attribute: &PointAttributeDefinition,
1264 index: usize,
1265 attribute_data: &[u8],
1266 ) {
1267 let attribute_byte_range = Self::get_byte_range_for_attribute(index, attribute);
1268 let attribute_storage = self
1269 .attributes_storage
1270 .get_mut(attribute)
1271 .expect("Attribute not found in PointLayout of this buffer");
1272 let attribute_bytes = &mut attribute_storage[attribute_byte_range];
1273 attribute_bytes.copy_from_slice(attribute_data);
1274 }
1275
1276 fn swap(&mut self, from_index: usize, to_index: usize) {
1277 assert!(from_index < self.len());
1278 assert!(to_index < self.len());
1279 if from_index == to_index {
1280 return;
1281 }
1282 for (attribute, storage) in self.attributes_storage.iter_mut() {
1283 let src_byte_range = Self::get_byte_range_for_attribute(from_index, attribute);
1284 let dst_byte_range = Self::get_byte_range_for_attribute(to_index, attribute);
1285 unsafe {
1287 let src_ptr = storage.as_mut_ptr().add(src_byte_range.start);
1288 let dst_ptr = storage.as_mut_ptr().add(dst_byte_range.start);
1289 std::ptr::swap_nonoverlapping(src_ptr, dst_ptr, attribute.size() as usize);
1290 }
1291 }
1292 }
1293
1294 unsafe fn set_point_range(&mut self, point_range: Range<usize>, point_data: &[u8]) {
1295 let size_of_point = self.point_layout.size_of_point_entry() as usize;
1296 let first_point = point_range.start;
1297 for attribute in self.point_layout.attributes() {
1298 let attribute_definition = attribute.attribute_definition();
1299 let attribute_storage = self
1300 .attributes_storage
1301 .get_mut(attribute_definition)
1302 .expect("Attribute not found within storage of this PointBuffer");
1303 for point_index in point_range.clone() {
1304 let zero_based_index = point_index - first_point;
1305 let attribute_byte_range =
1306 Self::get_byte_range_for_attribute(point_index, attribute_definition);
1307
1308 let dst_slice = &mut attribute_storage[attribute_byte_range];
1309 let src_point_slice = &point_data
1310 [(zero_based_index * size_of_point)..((zero_based_index + 1) * size_of_point)];
1311 let src_slice = &src_point_slice[attribute.byte_range_within_point()];
1312 dst_slice.copy_from_slice(src_slice);
1313 }
1314 }
1315 }
1316
1317 unsafe fn set_attribute_range(
1318 &mut self,
1319 attribute: &PointAttributeDefinition,
1320 point_range: Range<usize>,
1321 attribute_data: &[u8],
1322 ) {
1323 let attribute_range = self.get_attribute_range_mut(attribute, point_range);
1324 attribute_range.copy_from_slice(attribute_data);
1325 }
1326
1327 fn as_columnar_mut(&mut self) -> Option<&mut dyn ColumnarBufferMut<'a>> {
1328 Some(self)
1329 }
1330}
1331
1332impl<'a> OwningBuffer<'a> for HashMapBuffer
1333where
1334 HashMapBuffer: 'a,
1335{
1336 unsafe fn push_points(&mut self, point_bytes: &[u8]) {
1337 let point_size = self.point_layout.size_of_point_entry() as usize;
1338 assert_eq!(point_bytes.len() % point_size, 0);
1339 let num_points_added = point_bytes.len() / point_size;
1340 for attribute in self.point_layout.attributes() {
1341 let storage = self
1342 .attributes_storage
1343 .get_mut(attribute.attribute_definition())
1344 .expect("Attribute not found in storage of this buffer");
1345 for index in 0..num_points_added {
1346 let point_bytes = &point_bytes[(index * point_size)..((index + 1) * point_size)];
1347 let attribute_bytes = &point_bytes[attribute.byte_range_within_point()];
1348 storage.extend_from_slice(attribute_bytes);
1349 }
1350 }
1351 self.length += num_points_added;
1352 }
1353
1354 fn resize(&mut self, count: usize) {
1355 for (attribute, storage) in self.attributes_storage.iter_mut() {
1356 let new_num_bytes = count * attribute.size() as usize;
1357 storage.resize(new_num_bytes, 0);
1358 }
1359 self.length = count;
1360 }
1361
1362 fn clear(&mut self) {
1363 for storage in self.attributes_storage.values_mut() {
1364 storage.clear();
1365 }
1366 self.length = 0;
1367 }
1368}
1369
1370impl<'a> ColumnarBuffer<'a> for HashMapBuffer
1371where
1372 HashMapBuffer: 'a,
1373{
1374 fn get_attribute_ref<'b>(
1375 &'b self,
1376 attribute: &PointAttributeDefinition,
1377 index: usize,
1378 ) -> &'b [u8]
1379 where
1380 'a: 'b,
1381 {
1382 let storage_of_attribute = self
1383 .attributes_storage
1384 .get(attribute)
1385 .expect("Attribute not found in PointLayout of this buffer");
1386 &storage_of_attribute[Self::get_byte_range_for_attribute(index, attribute)]
1387 }
1388
1389 fn get_attribute_range_ref<'b>(
1390 &'b self,
1391 attribute: &PointAttributeDefinition,
1392 range: Range<usize>,
1393 ) -> &'b [u8]
1394 where
1395 'a: 'b,
1396 {
1397 let storage_of_attribute = self
1398 .attributes_storage
1399 .get(attribute)
1400 .expect("Attribute not found in PointLayout of this buffer");
1401 &storage_of_attribute[Self::get_byte_range_for_attributes(range, attribute)]
1402 }
1403}
1404
1405impl<'a> ColumnarBufferMut<'a> for HashMapBuffer
1406where
1407 HashMapBuffer: 'a,
1408{
1409 fn get_attribute_mut<'b>(
1410 &'b mut self,
1411 attribute: &PointAttributeDefinition,
1412 index: usize,
1413 ) -> &'b mut [u8]
1414 where
1415 'a: 'b,
1416 {
1417 let byte_range = Self::get_byte_range_for_attribute(index, attribute);
1418 let storage_of_attribute = self
1419 .attributes_storage
1420 .get_mut(attribute)
1421 .expect("Attribute not found in PointLayout of this buffer");
1422 &mut storage_of_attribute[byte_range]
1423 }
1424
1425 fn get_attribute_range_mut<'b>(
1426 &'b mut self,
1427 attribute: &PointAttributeDefinition,
1428 range: Range<usize>,
1429 ) -> &'b mut [u8]
1430 where
1431 'a: 'b,
1432 {
1433 let byte_range = Self::get_byte_range_for_attributes(range, attribute);
1434 let storage_of_attribute = self
1435 .attributes_storage
1436 .get_mut(attribute)
1437 .expect("Attribute not found in PointLayout of this buffer");
1438 &mut storage_of_attribute[byte_range]
1439 }
1440}
1441
1442impl<'a> SliceBuffer<'a> for HashMapBuffer
1443where
1444 Self: 'a,
1445{
1446 type SliceType = BufferSliceColumnar<'a, Self>;
1447
1448 fn slice(&'a self, range: Range<usize>) -> Self::SliceType {
1449 BufferSliceColumnar::new(self, range)
1450 }
1451}
1452
1453impl<'a> SliceBufferMut<'a> for HashMapBuffer {
1454 type SliceTypeMut = BufferSliceColumnarMut<'a, Self>;
1455
1456 fn slice_mut(&'a mut self, range: Range<usize>) -> Self::SliceTypeMut {
1457 BufferSliceColumnarMut::new(self, range)
1458 }
1459}
1460
1461impl<T: PointType> FromIterator<T> for HashMapBuffer {
1462 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
1463 let point_layout = T::layout();
1464 let mut buffer = Self::new_from_layout(point_layout);
1465 iter.into_iter().for_each(|point| {
1466 let point_bytes = bytemuck::bytes_of(&point);
1467 unsafe {
1469 buffer.push_points(point_bytes);
1470 }
1471 });
1472 buffer
1473 }
1474}
1475
1476pub struct ExternalMemoryBuffer<T: AsRef<[u8]>> {
1480 external_memory: T,
1481 point_layout: PointLayout,
1482 length: usize,
1483}
1484
1485impl<T: AsRef<[u8]>> ExternalMemoryBuffer<T> {
1486 pub fn new(external_memory: T, point_layout: PointLayout) -> Self {
1488 let length = match point_layout.size_of_point_entry() {
1489 0 => {
1490 assert_eq!(0, external_memory.as_ref().len());
1491 0
1492 }
1493 point_size => {
1494 assert!(external_memory.as_ref().len() % point_size as usize == 0);
1495 external_memory.as_ref().len() / point_size as usize
1496 }
1497 };
1498 Self {
1499 external_memory,
1500 point_layout,
1501 length,
1502 }
1503 }
1504
1505 fn get_byte_range_for_point(&self, point_index: usize) -> Range<usize> {
1506 let size_of_point = self.point_layout.size_of_point_entry() as usize;
1507 (point_index * size_of_point)..((point_index + 1) * size_of_point)
1508 }
1509
1510 fn get_byte_range_for_point_range(&self, point_range: Range<usize>) -> Range<usize> {
1511 let size_of_point = self.point_layout.size_of_point_entry() as usize;
1512 (point_range.start * size_of_point)..(point_range.end * size_of_point)
1513 }
1514
1515 fn get_byte_range_of_attribute(
1516 &self,
1517 point_index: usize,
1518 attribute: &PointAttributeMember,
1519 ) -> Range<usize> {
1520 let start_byte = (point_index * self.point_layout.size_of_point_entry() as usize)
1521 + attribute.offset() as usize;
1522 let end_byte = start_byte + attribute.size() as usize;
1523 start_byte..end_byte
1524 }
1525}
1526
1527impl<'a, T: AsRef<[u8]>> BorrowedBuffer<'a> for ExternalMemoryBuffer<T>
1528where
1529 ExternalMemoryBuffer<T>: 'a,
1530{
1531 fn len(&self) -> usize {
1532 self.length
1533 }
1534
1535 fn point_layout(&self) -> &PointLayout {
1536 &self.point_layout
1537 }
1538
1539 fn get_point(&self, index: usize, data: &mut [u8]) {
1540 let point_bytes = &self.external_memory.as_ref()[self.get_byte_range_for_point(index)];
1541 data.copy_from_slice(point_bytes);
1542 }
1543
1544 fn get_point_range(&self, range: Range<usize>, data: &mut [u8]) {
1545 let point_bytes =
1546 &self.external_memory.as_ref()[self.get_byte_range_for_point_range(range)];
1547 data.copy_from_slice(point_bytes);
1548 }
1549
1550 unsafe fn get_attribute_unchecked(
1551 &self,
1552 attribute_member: &PointAttributeMember,
1553 index: usize,
1554 data: &mut [u8],
1555 ) {
1556 let attribute_bytes_range = self.get_byte_range_of_attribute(index, attribute_member);
1557 let attribute_bytes = &self.external_memory.as_ref()[attribute_bytes_range];
1558 data.copy_from_slice(attribute_bytes);
1559 }
1560
1561 fn as_interleaved(&self) -> Option<&dyn InterleavedBuffer<'a>> {
1562 Some(self)
1563 }
1564}
1565
1566impl<'a, T: AsMut<[u8]> + AsRef<[u8]>> BorrowedMutBuffer<'a> for ExternalMemoryBuffer<T>
1567where
1568 ExternalMemoryBuffer<T>: 'a,
1569{
1570 unsafe fn set_point(&mut self, index: usize, point_data: &[u8]) {
1571 let point_byte_range = self.get_byte_range_for_point(index);
1572 let point_memory = &mut self.external_memory.as_mut()[point_byte_range];
1573 point_memory.copy_from_slice(point_data);
1574 }
1575
1576 unsafe fn set_attribute(
1577 &mut self,
1578 attribute: &PointAttributeDefinition,
1579 index: usize,
1580 attribute_data: &[u8],
1581 ) {
1582 let attribute_member = self
1583 .point_layout
1584 .get_attribute(attribute)
1585 .expect("Attribute not found in PointLayout of this buffer");
1586 let attribute_byte_range = self.get_byte_range_of_attribute(index, attribute_member);
1587 let attribute_bytes = &mut self.external_memory.as_mut()[attribute_byte_range];
1588 attribute_bytes.copy_from_slice(attribute_data);
1589 }
1590
1591 fn swap(&mut self, from_index: usize, to_index: usize) {
1592 assert!(from_index < self.len());
1593 assert!(to_index < self.len());
1594 if from_index == to_index {
1595 return;
1596 }
1597 let size_of_point = self.point_layout.size_of_point_entry() as usize;
1598 unsafe {
1600 let from_ptr = self
1601 .external_memory
1602 .as_mut()
1603 .as_mut_ptr()
1604 .add(from_index * size_of_point);
1605 let to_ptr = self
1606 .external_memory
1607 .as_mut()
1608 .as_mut_ptr()
1609 .add(to_index * size_of_point);
1610 std::ptr::swap_nonoverlapping(from_ptr, to_ptr, size_of_point);
1611 }
1612 }
1613
1614 unsafe fn set_point_range(&mut self, point_range: Range<usize>, point_data: &[u8]) {
1615 let point_byte_range = self.get_byte_range_for_point_range(point_range);
1616 let point_memory = &mut self.external_memory.as_mut()[point_byte_range];
1617 point_memory.copy_from_slice(point_data);
1618 }
1619
1620 unsafe fn set_attribute_range(
1621 &mut self,
1622 attribute: &PointAttributeDefinition,
1623 point_range: Range<usize>,
1624 attribute_data: &[u8],
1625 ) {
1626 let attribute_member = self
1627 .point_layout
1628 .get_attribute(attribute)
1629 .expect("Attribute not found in PointLayout of this buffer");
1630 let attribute_size = attribute_member.size() as usize;
1631 let first_point = point_range.start;
1632 for point_index in point_range {
1633 let zero_based_index = point_index - first_point;
1634 let src_slice = &attribute_data
1635 [(zero_based_index * attribute_size)..((zero_based_index + 1) * attribute_size)];
1636 let attribute_byte_range =
1637 self.get_byte_range_of_attribute(point_index, attribute_member);
1638 let attribute_bytes = &mut self.external_memory.as_mut()[attribute_byte_range];
1639 attribute_bytes.copy_from_slice(src_slice);
1640 }
1641 }
1642
1643 fn as_interleaved_mut(&mut self) -> Option<&mut dyn InterleavedBufferMut<'a>> {
1644 Some(self)
1645 }
1646}
1647
1648impl<'a, T: AsRef<[u8]>> InterleavedBuffer<'a> for ExternalMemoryBuffer<T>
1649where
1650 ExternalMemoryBuffer<T>: 'a,
1651{
1652 fn get_point_ref<'b>(&'b self, index: usize) -> &'b [u8]
1653 where
1654 'a: 'b,
1655 {
1656 let memory = self.external_memory.as_ref();
1657 &memory[self.get_byte_range_for_point(index)]
1658 }
1659
1660 fn get_point_range_ref<'b>(&'b self, range: Range<usize>) -> &'b [u8]
1661 where
1662 'a: 'b,
1663 {
1664 let memory = self.external_memory.as_ref();
1665 &memory[self.get_byte_range_for_point_range(range)]
1666 }
1667}
1668
1669impl<'a, T: AsRef<[u8]> + AsMut<[u8]>> InterleavedBufferMut<'a> for ExternalMemoryBuffer<T>
1670where
1671 ExternalMemoryBuffer<T>: 'a,
1672{
1673 fn get_point_mut<'b>(&'b mut self, index: usize) -> &'b mut [u8]
1674 where
1675 'a: 'b,
1676 {
1677 let byte_range = self.get_byte_range_for_point(index);
1678 let memory = self.external_memory.as_mut();
1679 &mut memory[byte_range]
1680 }
1681
1682 fn get_point_range_mut<'b>(&'b mut self, range: Range<usize>) -> &'b mut [u8]
1683 where
1684 'a: 'b,
1685 {
1686 let byte_range = self.get_byte_range_for_point_range(range);
1687 let memory = self.external_memory.as_mut();
1688 &mut memory[byte_range]
1689 }
1690}
1691
1692impl<'a, T: AsRef<[u8]> + 'a> SliceBuffer<'a> for ExternalMemoryBuffer<T>
1693where
1694 Self: 'a,
1695{
1696 type SliceType = BufferSliceInterleaved<'a, Self>;
1697
1698 fn slice(&'a self, range: Range<usize>) -> Self::SliceType {
1699 BufferSliceInterleaved::new(self, range)
1700 }
1701}
1702
1703impl<'a, T: AsRef<[u8]> + AsMut<[u8]> + 'a> SliceBufferMut<'a> for ExternalMemoryBuffer<T> {
1704 type SliceTypeMut = BufferSliceInterleavedMut<'a, Self>;
1705 fn slice_mut(&'a mut self, range: Range<usize>) -> Self::SliceTypeMut {
1706 BufferSliceInterleavedMut::new(self, range)
1707 }
1708}
1709
1710#[cfg(test)]
1711mod tests {
1712 use itertools::Itertools;
1713 use nalgebra::Vector3;
1714 use rand::{prelude::Distribution, thread_rng, Rng};
1715
1716 use crate::layout::{attributes::POSITION_3D, PointAttributeDataType};
1717 use crate::test_utils::*;
1718
1719 use super::*;
1720
1721 fn compare_attributes_typed<'a, U: PrimitiveType + std::fmt::Debug + PartialEq>(
1722 buffer: &'a impl BorrowedBuffer<'a>,
1723 attribute: &PointAttributeDefinition,
1724 expected_points: &'a impl BorrowedBuffer<'a>,
1725 ) {
1726 let collected_values = buffer
1727 .view_attribute::<U>(attribute)
1728 .into_iter()
1729 .collect::<Vec<_>>();
1730 let expected_values = expected_points
1731 .view_attribute::<U>(attribute)
1732 .into_iter()
1733 .collect::<Vec<_>>();
1734 assert_eq!(expected_values, collected_values);
1735 }
1736
1737 fn compare_attributes<'a>(
1739 buffer: &'a impl BorrowedBuffer<'a>,
1740 attribute: &PointAttributeDefinition,
1741 expected_points: &'a impl BorrowedBuffer<'a>,
1742 ) {
1743 match attribute.datatype() {
1744 PointAttributeDataType::F32 => {
1745 compare_attributes_typed::<f32>(buffer, attribute, expected_points)
1746 }
1747 PointAttributeDataType::F64 => {
1748 compare_attributes_typed::<f64>(buffer, attribute, expected_points)
1749 }
1750 PointAttributeDataType::I16 => {
1751 compare_attributes_typed::<i16>(buffer, attribute, expected_points)
1752 }
1753 PointAttributeDataType::I32 => {
1754 compare_attributes_typed::<i32>(buffer, attribute, expected_points)
1755 }
1756 PointAttributeDataType::I64 => {
1757 compare_attributes_typed::<i64>(buffer, attribute, expected_points)
1758 }
1759 PointAttributeDataType::I8 => {
1760 compare_attributes_typed::<i8>(buffer, attribute, expected_points)
1761 }
1762 PointAttributeDataType::U16 => {
1763 compare_attributes_typed::<u16>(buffer, attribute, expected_points)
1764 }
1765 PointAttributeDataType::U32 => {
1766 compare_attributes_typed::<u32>(buffer, attribute, expected_points)
1767 }
1768 PointAttributeDataType::U64 => {
1769 compare_attributes_typed::<u64>(buffer, attribute, expected_points)
1770 }
1771 PointAttributeDataType::U8 => {
1772 compare_attributes_typed::<u8>(buffer, attribute, expected_points)
1773 }
1774 PointAttributeDataType::Vec3f32 => {
1775 compare_attributes_typed::<Vector3<f32>>(buffer, attribute, expected_points)
1776 }
1777 PointAttributeDataType::Vec3f64 => {
1778 compare_attributes_typed::<Vector3<f64>>(buffer, attribute, expected_points);
1779 }
1780 PointAttributeDataType::Vec3i32 => {
1781 compare_attributes_typed::<Vector3<i32>>(buffer, attribute, expected_points)
1782 }
1783 PointAttributeDataType::Vec3u16 => {
1784 compare_attributes_typed::<Vector3<u16>>(buffer, attribute, expected_points)
1785 }
1786 PointAttributeDataType::Vec3u8 => {
1787 compare_attributes_typed::<Vector3<u8>>(buffer, attribute, expected_points)
1788 }
1789 _ => unimplemented!(),
1790 }
1791 }
1792
1793 fn test_vector_buffer_with_type<T: PointType + std::fmt::Debug + PartialEq + Copy + Clone>()
1794 where
1795 DefaultPointDistribution: Distribution<T>,
1796 {
1797 const COUNT: usize = 16;
1798 let test_data: Vec<T> = thread_rng()
1799 .sample_iter(DefaultPointDistribution)
1800 .take(COUNT)
1801 .collect();
1802 let overwrite_data: Vec<T> = thread_rng()
1803 .sample_iter(DefaultPointDistribution)
1804 .take(COUNT)
1805 .collect();
1806
1807 let test_data_as_buffer = test_data.iter().copied().collect::<VectorBuffer>();
1808
1809 {
1810 let mut buffer = VectorBuffer::new_from_layout(T::layout());
1811 assert_eq!(0, buffer.len());
1812 assert_eq!(T::layout(), *buffer.point_layout());
1813 assert_eq!(0, buffer.view::<T>().into_iter().count());
1814
1815 for (idx, point) in test_data.iter().enumerate() {
1816 buffer.view_mut().push_point(*point);
1817 assert_eq!(idx + 1, buffer.len());
1818 assert_eq!(*point, buffer.view().at(idx));
1819 }
1820
1821 let mut collected_points = buffer.view().into_iter().collect::<Vec<_>>();
1822 assert_eq!(test_data, collected_points);
1823
1824 let collected_points_by_ref = buffer.view().iter().copied().collect::<Vec<_>>();
1825 assert_eq!(test_data, collected_points_by_ref);
1826
1827 for attribute in buffer.point_layout().attributes() {
1828 compare_attributes(
1829 &buffer,
1830 attribute.attribute_definition(),
1831 &test_data_as_buffer,
1832 );
1833 }
1834
1835 let slice = buffer.slice(1..2);
1836 assert_eq!(test_data[1], slice.view().at(0));
1837
1838 for (idx, point) in overwrite_data.iter().enumerate() {
1839 *buffer.view_mut().at_mut(idx) = *point;
1840 }
1841 collected_points = buffer.view().iter().copied().collect();
1842 assert_eq!(overwrite_data, collected_points);
1843 }
1844 }
1845
1846 fn test_hashmap_buffer_with_type<T: PointType + std::fmt::Debug + PartialEq + Copy + Clone>()
1847 where
1848 DefaultPointDistribution: Distribution<T>,
1849 {
1850 const COUNT: usize = 16;
1851 let test_data: Vec<T> = thread_rng()
1852 .sample_iter(DefaultPointDistribution)
1853 .take(COUNT)
1854 .collect();
1855 let overwrite_data: Vec<T> = thread_rng()
1856 .sample_iter(DefaultPointDistribution)
1857 .take(COUNT)
1858 .collect();
1859
1860 let test_data_as_buffer = test_data.iter().copied().collect::<HashMapBuffer>();
1861
1862 {
1863 let mut buffer = HashMapBuffer::new_from_layout(T::layout());
1864 assert_eq!(0, buffer.len());
1865 assert_eq!(T::layout(), *buffer.point_layout());
1866 assert_eq!(0, buffer.view::<T>().into_iter().count());
1867
1868 for (idx, point) in test_data.iter().enumerate() {
1869 buffer.view_mut().push_point(*point);
1870 assert_eq!(idx + 1, buffer.len());
1871 assert_eq!(*point, buffer.view().at(idx));
1872 }
1873
1874 let mut collected_points = buffer.view().into_iter().collect::<Vec<_>>();
1875 assert_eq!(test_data, collected_points);
1876
1877 for attribute in buffer.point_layout().attributes() {
1878 compare_attributes(
1879 &buffer,
1880 attribute.attribute_definition(),
1881 &test_data_as_buffer,
1882 );
1883 }
1884
1885 let slice = buffer.slice(1..2);
1886 assert_eq!(test_data[1], slice.view().at(0));
1887
1888 for (idx, point) in overwrite_data.iter().enumerate() {
1889 buffer.view_mut().set_at(idx, *point);
1890 }
1891 collected_points = buffer.view().into_iter().collect();
1892 assert_eq!(overwrite_data, collected_points);
1893 }
1894 }
1895
1896 fn test_external_memory_buffer_with_type<
1897 T: PointType + std::fmt::Debug + PartialEq + Copy + Clone,
1898 >()
1899 where
1900 DefaultPointDistribution: Distribution<T>,
1901 {
1902 const COUNT: usize = 16;
1903 let test_data: Vec<T> = thread_rng()
1904 .sample_iter(DefaultPointDistribution)
1905 .take(COUNT)
1906 .collect();
1907 let overwrite_data: Vec<T> = thread_rng()
1908 .sample_iter(DefaultPointDistribution)
1909 .take(COUNT)
1910 .collect();
1911
1912 let mut memory_of_buffer: Vec<u8> =
1913 vec![0; COUNT * T::layout().size_of_point_entry() as usize];
1914 let mut test_data_as_buffer = ExternalMemoryBuffer::new(&mut memory_of_buffer, T::layout());
1915 for (idx, point) in test_data.iter().copied().enumerate() {
1916 test_data_as_buffer.view_mut().set_at(idx, point);
1917 }
1918
1919 {
1920 let mut buffer = VectorBuffer::new_from_layout(T::layout());
1921 assert_eq!(0, buffer.len());
1922 assert_eq!(T::layout(), *buffer.point_layout());
1923 assert_eq!(0, buffer.view::<T>().into_iter().count());
1924
1925 for (idx, point) in test_data.iter().enumerate() {
1926 buffer.view_mut().push_point(*point);
1927 assert_eq!(idx + 1, buffer.len());
1928 assert_eq!(*point, buffer.view().at(idx));
1929 }
1930
1931 let mut collected_points = buffer.view().into_iter().collect::<Vec<_>>();
1932 assert_eq!(test_data, collected_points);
1933
1934 let collected_points_by_ref = buffer.view().iter().copied().collect::<Vec<_>>();
1935 assert_eq!(test_data, collected_points_by_ref);
1936
1937 for attribute in buffer.point_layout().attributes() {
1938 compare_attributes(
1939 &buffer,
1940 attribute.attribute_definition(),
1941 &test_data_as_buffer,
1942 );
1943 }
1944
1945 let slice = buffer.slice(1..2);
1946 assert_eq!(test_data[1], slice.view().at(0));
1947
1948 for (idx, point) in overwrite_data.iter().enumerate() {
1949 *buffer.view_mut().at_mut(idx) = *point;
1950 }
1951 collected_points = buffer.view().iter().copied().collect();
1952 assert_eq!(overwrite_data, collected_points);
1953 }
1954 }
1955
1956 #[test]
1957 fn test_vector_buffer() {
1958 test_vector_buffer_with_type::<CustomPointTypeSmall>();
1959 test_vector_buffer_with_type::<CustomPointTypeBig>();
1960 }
1961
1962 #[test]
1963 fn test_hash_map_buffer() {
1964 test_hashmap_buffer_with_type::<CustomPointTypeSmall>();
1965 test_hashmap_buffer_with_type::<CustomPointTypeBig>();
1966 }
1967
1968 #[test]
1969 fn test_hash_map_buffer_mutate_attribute() {
1970 const COUNT: usize = 16;
1971 let test_data: Vec<CustomPointTypeBig> = thread_rng()
1972 .sample_iter(DefaultPointDistribution)
1973 .take(COUNT)
1974 .collect();
1975 let overwrite_data: Vec<CustomPointTypeBig> = thread_rng()
1976 .sample_iter(DefaultPointDistribution)
1977 .take(COUNT)
1978 .collect();
1979
1980 let mut buffer = test_data.iter().copied().collect::<HashMapBuffer>();
1981
1982 for (idx, attribute) in buffer
1983 .view_attribute_mut::<Vector3<f64>>(&POSITION_3D)
1984 .iter_mut()
1985 .enumerate()
1986 {
1987 *attribute = overwrite_data[idx].position;
1988 }
1989
1990 let expected_positions = overwrite_data
1991 .iter()
1992 .map(|point| point.position)
1993 .collect::<Vec<_>>();
1994 let actual_positions = buffer
1995 .view_attribute(&POSITION_3D)
1996 .into_iter()
1997 .collect::<Vec<_>>();
1998 assert_eq!(expected_positions, actual_positions);
1999 }
2000
2001 #[test]
2002 fn test_external_memory_buffer() {
2003 test_external_memory_buffer_with_type::<CustomPointTypeSmall>();
2004 test_external_memory_buffer_with_type::<CustomPointTypeBig>();
2005 }
2006
2007 fn test_transform_attribute_generic<
2008 'a,
2009 B: BorrowedMutBuffer<'a> + FromIterator<CustomPointTypeBig> + 'a,
2010 >() {
2011 const COUNT: usize = 16;
2012 let test_data: Vec<CustomPointTypeBig> = thread_rng()
2013 .sample_iter(DefaultPointDistribution)
2014 .take(COUNT)
2015 .collect();
2016 let overwrite_data: Vec<CustomPointTypeBig> = thread_rng()
2017 .sample_iter(DefaultPointDistribution)
2018 .take(COUNT)
2019 .collect();
2020
2021 let mut buffer = test_data.iter().copied().collect::<B>();
2022 buffer.transform_attribute(&POSITION_3D, |index, _| -> Vector3<f64> {
2024 overwrite_data[index].position
2025 });
2026
2027 let expected_positions = overwrite_data
2028 .iter()
2029 .map(|point| point.position)
2030 .collect::<Vec<_>>();
2031 let actual_positions = buffer
2032 .view_attribute(&POSITION_3D)
2033 .into_iter()
2034 .collect::<Vec<_>>();
2035 assert_eq!(expected_positions, actual_positions);
2036 }
2037
2038 #[test]
2039 fn test_transform_attribute() {
2040 test_transform_attribute_generic::<VectorBuffer>();
2041 test_transform_attribute_generic::<HashMapBuffer>();
2042 }
2043
2044 #[test]
2045 fn test_append() {
2046 const COUNT: usize = 16;
2047 let test_data: Vec<CustomPointTypeBig> = thread_rng()
2048 .sample_iter(DefaultPointDistribution)
2049 .take(COUNT)
2050 .collect();
2051
2052 let expected_buffer_interleaved = test_data.iter().copied().collect::<VectorBuffer>();
2053 let expected_buffer_columnar = test_data.iter().copied().collect::<HashMapBuffer>();
2054
2055 {
2056 let mut vector_buffer = VectorBuffer::new_from_layout(CustomPointTypeBig::layout());
2057 vector_buffer.append(&expected_buffer_interleaved);
2058 assert_eq!(expected_buffer_interleaved, vector_buffer);
2059 }
2060 {
2061 let mut vector_buffer = VectorBuffer::new_from_layout(CustomPointTypeBig::layout());
2062 vector_buffer.append(&expected_buffer_columnar);
2063 assert_eq!(expected_buffer_interleaved, vector_buffer);
2064 }
2065 {
2066 let mut hashmap_buffer = HashMapBuffer::new_from_layout(CustomPointTypeBig::layout());
2067 hashmap_buffer.append(&expected_buffer_columnar);
2068 assert_eq!(expected_buffer_columnar, hashmap_buffer);
2069 }
2070 {
2071 let mut hashmap_buffer = HashMapBuffer::new_from_layout(CustomPointTypeBig::layout());
2072 hashmap_buffer.append(&expected_buffer_interleaved);
2073 assert_eq!(expected_buffer_columnar, hashmap_buffer);
2074 }
2075 }
2076
2077 #[test]
2078 fn test_buffers_from_empty_layout() {
2079 let empty_layout = PointLayout::default();
2080
2081 {
2082 let buffer = VectorBuffer::new_from_layout(empty_layout.clone());
2083 assert_eq!(0, buffer.len());
2084 }
2085 {
2086 let buffer = HashMapBuffer::new_from_layout(empty_layout.clone());
2087 assert_eq!(0, buffer.len());
2088 }
2089 {
2090 let empty_memory = Vec::default();
2091 let buffer = ExternalMemoryBuffer::new(&empty_memory, empty_layout.clone());
2092 assert_eq!(0, buffer.len());
2093 }
2094 }
2095
2096 fn test_buffer_set_point_range_generic<
2097 B: for<'a> BorrowedMutBuffer<'a>
2098 + FromIterator<CustomPointTypeBig>
2099 + for<'a> SliceBufferMut<'a>,
2100 >() {
2101 const COUNT: usize = 16;
2102 let test_data: Vec<CustomPointTypeBig> = thread_rng()
2103 .sample_iter(DefaultPointDistribution)
2104 .take(COUNT)
2105 .collect();
2106 let overwrite_data: Vec<CustomPointTypeBig> = thread_rng()
2107 .sample_iter(DefaultPointDistribution)
2108 .take(COUNT)
2109 .collect();
2110 let raw_overwrite_data: &[u8] = bytemuck::cast_slice(&overwrite_data);
2111
2112 let mut buffer = test_data.iter().copied().collect::<B>();
2113 unsafe {
2115 buffer.set_point_range(0..COUNT, raw_overwrite_data);
2116 }
2117
2118 let actual_data = buffer
2119 .view::<CustomPointTypeBig>()
2120 .into_iter()
2121 .collect_vec();
2122 assert_eq!(overwrite_data, actual_data);
2123
2124 buffer = test_data.iter().copied().collect::<B>();
2126 let mut buffer_slice = buffer.slice_mut(0..COUNT);
2127 unsafe {
2128 buffer_slice.set_point_range(0..COUNT, raw_overwrite_data);
2129 }
2130 drop(buffer_slice);
2131
2132 let actual_data = buffer
2133 .view::<CustomPointTypeBig>()
2134 .into_iter()
2135 .collect_vec();
2136 assert_eq!(overwrite_data, actual_data);
2137 }
2138
2139 #[test]
2140 fn test_buffers_set_point_range() {
2141 test_buffer_set_point_range_generic::<VectorBuffer>();
2142 test_buffer_set_point_range_generic::<HashMapBuffer>();
2143 }
2144
2145 fn test_buffer_get_point_range_generic<
2146 B: for<'a> BorrowedMutBuffer<'a>
2147 + FromIterator<CustomPointTypeBig>
2148 + for<'a> SliceBufferMut<'a>,
2149 >() {
2150 const COUNT: usize = 16;
2151 let test_data: Vec<CustomPointTypeBig> = thread_rng()
2152 .sample_iter(DefaultPointDistribution)
2153 .take(COUNT)
2154 .collect();
2155 let raw_test_data: &[u8] = bytemuck::cast_slice(test_data.as_slice());
2156 let size_of_single_point = std::mem::size_of::<CustomPointTypeBig>();
2157
2158 let buffer = test_data.iter().copied().collect::<B>();
2159
2160 let mut actual_point_data = vec![0; raw_test_data.len()];
2161 buffer.get_point_range(0..COUNT, &mut actual_point_data);
2162
2163 assert_eq!(raw_test_data, actual_point_data);
2164
2165 let subset_slice = &mut actual_point_data[..(6 * size_of_single_point)];
2167 buffer.get_point_range(2..8, subset_slice);
2168 assert_eq!(
2169 &raw_test_data[(2 * size_of_single_point)..(8 * size_of_single_point)],
2170 subset_slice
2171 );
2172 }
2173
2174 #[test]
2175 fn test_buffer_get_point_range() {
2176 test_buffer_get_point_range_generic::<VectorBuffer>();
2177 test_buffer_get_point_range_generic::<HashMapBuffer>();
2178 }
2179
2180 fn test_buffer_set_attribute_range_generic<
2181 B: for<'a> BorrowedMutBuffer<'a>
2182 + FromIterator<CustomPointTypeBig>
2183 + for<'a> SliceBufferMut<'a>,
2184 >() {
2185 const COUNT: usize = 16;
2186 let test_data: Vec<CustomPointTypeBig> = thread_rng()
2187 .sample_iter(DefaultPointDistribution)
2188 .take(COUNT)
2189 .collect();
2190 let overwrite_data: Vec<CustomPointTypeBig> = thread_rng()
2191 .sample_iter(DefaultPointDistribution)
2192 .take(COUNT)
2193 .collect();
2194 let overwrite_positions = overwrite_data
2195 .iter()
2196 .map(|point| point.position)
2197 .collect_vec();
2198 let overwrite_positions_raw_data: &[u8] = bytemuck::cast_slice(&overwrite_positions);
2199
2200 let mut buffer = test_data.iter().copied().collect::<B>();
2201 unsafe {
2203 buffer.set_attribute_range(&POSITION_3D, 0..COUNT, overwrite_positions_raw_data);
2204 }
2205
2206 let actual_positions = buffer
2207 .view_attribute(&POSITION_3D)
2208 .into_iter()
2209 .collect::<Vec<_>>();
2210 assert_eq!(overwrite_positions, actual_positions);
2211
2212 buffer = test_data.iter().copied().collect::<B>();
2214 let mut buffer_slice = buffer.slice_mut(0..test_data.len());
2215 unsafe {
2216 buffer_slice.set_attribute_range(&POSITION_3D, 0..COUNT, overwrite_positions_raw_data);
2217 }
2218 drop(buffer_slice);
2219
2220 let actual_positions = buffer
2221 .view_attribute(&POSITION_3D)
2222 .into_iter()
2223 .collect::<Vec<_>>();
2224 assert_eq!(overwrite_positions, actual_positions);
2225 }
2226
2227 #[test]
2228 fn test_buffers_set_attribute_range() {
2229 test_buffer_set_attribute_range_generic::<VectorBuffer>();
2230 test_buffer_set_attribute_range_generic::<HashMapBuffer>();
2231 }
2232
2233 #[test]
2234 fn test_buffers_as_memory_layout_accessors() {
2235 let mut vector_buffer = VectorBuffer::new_from_layout(CustomPointTypeSmall::layout());
2236 let mut hashmap_buffer = HashMapBuffer::new_from_layout(CustomPointTypeSmall::layout());
2237
2238 let mut memory: Vec<u8> = Vec::default();
2239 let mut external_memory_buffer =
2240 ExternalMemoryBuffer::new(memory.as_mut_slice(), CustomPointTypeSmall::layout());
2241
2242 assert!(vector_buffer.as_interleaved().is_some());
2243 assert!(vector_buffer.slice(0..0).as_interleaved().is_some());
2244 assert!(vector_buffer.slice_mut(0..0).as_interleaved().is_some());
2245 assert!(hashmap_buffer.as_interleaved().is_none());
2246 assert!(hashmap_buffer.slice(0..0).as_interleaved().is_none());
2247 assert!(hashmap_buffer.slice_mut(0..0).as_interleaved().is_none());
2248 assert!(external_memory_buffer.as_interleaved().is_some());
2249 assert!(external_memory_buffer
2250 .slice(0..0)
2251 .as_interleaved()
2252 .is_some());
2253 assert!(external_memory_buffer
2254 .slice_mut(0..0)
2255 .as_interleaved()
2256 .is_some());
2257
2258 assert!(vector_buffer.as_interleaved_mut().is_some());
2259 assert!(vector_buffer.slice_mut(0..0).as_interleaved_mut().is_some());
2260 assert!(hashmap_buffer.as_interleaved_mut().is_none());
2261 assert!(hashmap_buffer
2262 .slice_mut(0..0)
2263 .as_interleaved_mut()
2264 .is_none());
2265 assert!(external_memory_buffer.as_interleaved_mut().is_some());
2266 assert!(external_memory_buffer
2267 .slice_mut(0..0)
2268 .as_interleaved_mut()
2269 .is_some());
2270
2271 assert!(vector_buffer.as_columnar().is_none());
2272 assert!(vector_buffer.slice(0..0).as_columnar().is_none());
2273 assert!(vector_buffer.slice_mut(0..0).as_columnar().is_none());
2274 assert!(hashmap_buffer.as_columnar().is_some());
2275 assert!(hashmap_buffer.slice(0..0).as_columnar().is_some());
2276 assert!(hashmap_buffer.slice_mut(0..0).as_columnar().is_some());
2277 assert!(external_memory_buffer.as_columnar().is_none());
2278 assert!(external_memory_buffer.slice(0..0).as_columnar().is_none());
2279 assert!(external_memory_buffer
2280 .slice_mut(0..0)
2281 .as_columnar()
2282 .is_none());
2283
2284 assert!(vector_buffer.as_columnar_mut().is_none());
2285 assert!(vector_buffer.slice_mut(0..0).as_columnar_mut().is_none());
2286 assert!(hashmap_buffer.as_columnar_mut().is_some());
2287 assert!(hashmap_buffer.slice_mut(0..0).as_columnar_mut().is_some());
2288 assert!(external_memory_buffer.as_columnar_mut().is_none());
2289 assert!(external_memory_buffer
2290 .slice_mut(0..0)
2291 .as_columnar_mut()
2292 .is_none());
2293 }
2294
2295 #[test]
2296 fn test_hash_map_buffer_filter() {
2297 const COUNT: usize = 16;
2298 let test_data: Vec<CustomPointTypeBig> = thread_rng()
2299 .sample_iter(DefaultPointDistribution)
2300 .take(COUNT)
2301 .collect();
2302 let even_points = test_data
2303 .iter()
2304 .enumerate()
2305 .filter_map(
2306 |(idx, point)| {
2307 if idx % 2 == 0 {
2308 Some(*point)
2309 } else {
2310 None
2311 }
2312 },
2313 )
2314 .collect_vec();
2315
2316 let src_buffer = test_data.iter().copied().collect::<HashMapBuffer>();
2317
2318 let even_points_columnar = src_buffer.filter::<HashMapBuffer, _>(|idx| idx % 2 == 0);
2319 assert_eq!(
2320 even_points_columnar,
2321 even_points.iter().copied().collect::<HashMapBuffer>()
2322 );
2323
2324 let even_points_interleaved = src_buffer.filter::<VectorBuffer, _>(|idx| idx % 2 == 0);
2325 assert_eq!(
2326 even_points_interleaved,
2327 even_points.iter().copied().collect::<VectorBuffer>()
2328 );
2329 }
2330}