@@ -667,6 +667,162 @@ impl<T, const N: usize> Vec<T, N> {
667
667
ret
668
668
}
669
669
}
670
+
671
+ /// Retains only the elements specified by the predicate.
672
+ ///
673
+ /// In other words, remove all elements `e` for which `f(&e)` returns `false`.
674
+ /// This method operates in place, visiting each element exactly once in the
675
+ /// original order, and preserves the order of the retained elements.
676
+ ///
677
+ /// # Examples
678
+ ///
679
+ /// ```
680
+ /// use heapless::Vec;
681
+ ///
682
+ /// let mut vec: Vec<_, 8> = Vec::from_slice(&[1, 2, 3, 4]).unwrap();
683
+ /// vec.retain(|&x| x % 2 == 0);
684
+ /// assert_eq!(vec, [2, 4]);
685
+ /// ```
686
+ ///
687
+ /// Because the elements are visited exactly once in the original order,
688
+ /// external state may be used to decide which elements to keep.
689
+ ///
690
+ /// ```
691
+ /// use heapless::Vec;
692
+ ///
693
+ /// let mut vec: Vec<_, 8> = Vec::from_slice(&[1, 2, 3, 4, 5]).unwrap();
694
+ /// let keep = [false, true, true, false, true];
695
+ /// let mut iter = keep.iter();
696
+ /// vec.retain(|_| *iter.next().unwrap());
697
+ /// assert_eq!(vec, [2, 3, 5]);
698
+ /// ```
699
+ pub fn retain < F > ( & mut self , mut f : F )
700
+ where
701
+ F : FnMut ( & T ) -> bool ,
702
+ {
703
+ self . retain_mut ( |elem| f ( elem) ) ;
704
+ }
705
+
706
+ /// Retains only the elements specified by the predicate, passing a mutable reference to it.
707
+ ///
708
+ /// In other words, remove all elements `e` such that `f(&mut e)` returns `false`.
709
+ /// This method operates in place, visiting each element exactly once in the
710
+ /// original order, and preserves the order of the retained elements.
711
+ ///
712
+ /// # Examples
713
+ ///
714
+ /// ```
715
+ /// use heapless::Vec;
716
+ ///
717
+ /// let mut vec: Vec<_, 8> = Vec::from_slice(&[1, 2, 3, 4]).unwrap();
718
+ /// vec.retain_mut(|x| if *x <= 3 {
719
+ /// *x += 1;
720
+ /// true
721
+ /// } else {
722
+ /// false
723
+ /// });
724
+ /// assert_eq!(vec, [2, 3, 4]);
725
+ /// ```
726
+ pub fn retain_mut < F > ( & mut self , mut f : F )
727
+ where
728
+ F : FnMut ( & mut T ) -> bool ,
729
+ {
730
+ let original_len = self . len ( ) ;
731
+ // Avoid double drop if the drop guard is not executed,
732
+ // since we may make some holes during the process.
733
+ unsafe { self . set_len ( 0 ) } ;
734
+
735
+ // Vec: [Kept, Kept, Hole, Hole, Hole, Hole, Unchecked, Unchecked]
736
+ // |<- processed len ->| ^- next to check
737
+ // |<- deleted cnt ->|
738
+ // |<- original_len ->|
739
+ // Kept: Elements which predicate returns true on.
740
+ // Hole: Moved or dropped element slot.
741
+ // Unchecked: Unchecked valid elements.
742
+ //
743
+ // This drop guard will be invoked when predicate or `drop` of element panicked.
744
+ // It shifts unchecked elements to cover holes and `set_len` to the correct length.
745
+ // In cases when predicate and `drop` never panick, it will be optimized out.
746
+ struct BackshiftOnDrop < ' a , T , const N : usize > {
747
+ v : & ' a mut Vec < T , N > ,
748
+ processed_len : usize ,
749
+ deleted_cnt : usize ,
750
+ original_len : usize ,
751
+ }
752
+
753
+ impl < T , const N : usize > Drop for BackshiftOnDrop < ' _ , T , N > {
754
+ fn drop ( & mut self ) {
755
+ if self . deleted_cnt > 0 {
756
+ // SAFETY: Trailing unchecked items must be valid since we never touch them.
757
+ unsafe {
758
+ ptr:: copy (
759
+ self . v . as_ptr ( ) . add ( self . processed_len ) ,
760
+ self . v
761
+ . as_mut_ptr ( )
762
+ . add ( self . processed_len - self . deleted_cnt ) ,
763
+ self . original_len - self . processed_len ,
764
+ ) ;
765
+ }
766
+ }
767
+ // SAFETY: After filling holes, all items are in contiguous memory.
768
+ unsafe {
769
+ self . v . set_len ( self . original_len - self . deleted_cnt ) ;
770
+ }
771
+ }
772
+ }
773
+
774
+ let mut g = BackshiftOnDrop {
775
+ v : self ,
776
+ processed_len : 0 ,
777
+ deleted_cnt : 0 ,
778
+ original_len,
779
+ } ;
780
+
781
+ fn process_loop < F , T , const N : usize , const DELETED : bool > (
782
+ original_len : usize ,
783
+ f : & mut F ,
784
+ g : & mut BackshiftOnDrop < ' _ , T , N > ,
785
+ ) where
786
+ F : FnMut ( & mut T ) -> bool ,
787
+ {
788
+ while g. processed_len != original_len {
789
+ let p = g. v . as_mut_ptr ( ) ;
790
+ // SAFETY: Unchecked element must be valid.
791
+ let cur = unsafe { & mut * p. add ( g. processed_len ) } ;
792
+ if !f ( cur) {
793
+ // Advance early to avoid double drop if `drop_in_place` panicked.
794
+ g. processed_len += 1 ;
795
+ g. deleted_cnt += 1 ;
796
+ // SAFETY: We never touch this element again after dropped.
797
+ unsafe { ptr:: drop_in_place ( cur) } ;
798
+ // We already advanced the counter.
799
+ if DELETED {
800
+ continue ;
801
+ } else {
802
+ break ;
803
+ }
804
+ }
805
+ if DELETED {
806
+ // SAFETY: `deleted_cnt` > 0, so the hole slot must not overlap with current element.
807
+ // We use copy for move, and never touch this element again.
808
+ unsafe {
809
+ let hole_slot = p. add ( g. processed_len - g. deleted_cnt ) ;
810
+ ptr:: copy_nonoverlapping ( cur, hole_slot, 1 ) ;
811
+ }
812
+ }
813
+ g. processed_len += 1 ;
814
+ }
815
+ }
816
+
817
+ // Stage 1: Nothing was deleted.
818
+ process_loop :: < F , T , N , false > ( original_len, & mut f, & mut g) ;
819
+
820
+ // Stage 2: Some elements were deleted.
821
+ process_loop :: < F , T , N , true > ( original_len, & mut f, & mut g) ;
822
+
823
+ // All item are processed. This can be optimized to `set_len` by LLVM.
824
+ drop ( g) ;
825
+ }
670
826
}
671
827
672
828
// Trait implementations
0 commit comments