@@ -475,6 +475,50 @@ where
475
475
pub fn values_mut ( & mut self ) -> impl Iterator < Item = & mut V > {
476
476
self . iter_mut ( ) . map ( |( _, v) | v)
477
477
}
478
+
479
+ /// Returns an entry for the corresponding key
480
+ /// ```
481
+ /// use heapless::linear_map;
482
+ /// use heapless::LinearMap;
483
+ /// let mut map = LinearMap::<_, _, 16>::new();
484
+ /// if let linear_map::Entry::Vacant(v) = map.entry("a") {
485
+ /// v.insert(1).unwrap();
486
+ /// }
487
+ /// if let linear_map::Entry::Occupied(mut o) = map.entry("a") {
488
+ /// println!("found {}", *o.get()); // Prints 1
489
+ /// o.insert(2);
490
+ /// }
491
+ /// // Prints 2
492
+ /// println!("val: {}", *map.get("a").unwrap());
493
+ /// ```
494
+ pub fn entry ( & mut self , key : K ) -> Entry < ' _ , K , V > {
495
+ let idx = self
496
+ . keys ( )
497
+ . enumerate ( )
498
+ . find ( |& ( _, k) | * k. borrow ( ) == key)
499
+ . map ( |( idx, _) | idx) ;
500
+
501
+ match idx {
502
+ Some ( idx) => Entry :: Occupied ( OccupiedEntry {
503
+ idx,
504
+ map : self . as_mut_view ( ) ,
505
+ } ) ,
506
+ None => Entry :: Vacant ( VacantEntry {
507
+ key,
508
+ map : self . as_mut_view ( ) ,
509
+ } ) ,
510
+ }
511
+ }
512
+
513
+ /// Retains only the elements specified by the predicate.
514
+ ///
515
+ /// In other words, remove all pairs `(k, v)` for which `f(&k, &mut v)` returns `false`.
516
+ pub fn retain < F > ( & mut self , mut f : F )
517
+ where
518
+ F : FnMut ( & K , & mut V ) -> bool ,
519
+ {
520
+ self . buffer . retain_mut ( |( k, v) | f ( k, v) ) ;
521
+ }
478
522
}
479
523
480
524
impl < K , V , Q , S : LinearMapStorage < K , V > + ?Sized > ops:: Index < & ' _ Q > for LinearMapInner < K , V , S >
@@ -643,11 +687,111 @@ where
643
687
{
644
688
}
645
689
690
+ /// A view into an entry in the map
691
+ pub enum Entry < ' a , K , V > {
692
+ /// The entry corresponding to the key `K` exists in the map
693
+ Occupied ( OccupiedEntry < ' a , K , V > ) ,
694
+ /// The entry corresponding to the key `K` does not exist in the map
695
+ Vacant ( VacantEntry < ' a , K , V > ) ,
696
+ }
697
+
698
+ /// An occupied entry which can be manipulated
699
+ pub struct OccupiedEntry < ' a , K , V > {
700
+ // SAFETY: `idx` must not be modified after construction, and
701
+ // the size of `map` must not be changed.
702
+ idx : usize ,
703
+ map : & ' a mut LinearMapView < K , V > ,
704
+ }
705
+
706
+ impl < ' a , K , V > OccupiedEntry < ' a , K , V >
707
+ where
708
+ K : Eq ,
709
+ {
710
+ /// Gets a reference to the key that this entity corresponds to
711
+ pub fn key ( & self ) -> & K {
712
+ // SAFETY: Valid idx from OccupiedEntry construction
713
+ let ( k, _v) = unsafe { self . map . buffer . get_unchecked ( self . idx ) } ;
714
+ k
715
+ }
716
+
717
+ /// Removes this entry from the map and yields its corresponding key and value
718
+ pub fn remove_entry ( self ) -> ( K , V ) {
719
+ // SAFETY: Valid idx from OccupiedEntry construction
720
+ unsafe { self . map . buffer . swap_remove_unchecked ( self . idx ) }
721
+ }
722
+
723
+ /// Removes this entry from the map and yields its corresponding key and value
724
+ pub fn remove ( self ) -> V {
725
+ self . remove_entry ( ) . 1
726
+ }
727
+
728
+ /// Gets a reference to the value associated with this entry
729
+ pub fn get ( & self ) -> & V {
730
+ // SAFETY: Valid idx from OccupiedEntry construction
731
+ let ( _k, v) = unsafe { self . map . buffer . get_unchecked ( self . idx ) } ;
732
+ v
733
+ }
734
+
735
+ /// Gets a mutable reference to the value associated with this entry
736
+ pub fn get_mut ( & mut self ) -> & mut V {
737
+ // SAFETY: Valid idx from OccupiedEntry construction
738
+ let ( _k, v) = unsafe { self . map . buffer . get_unchecked_mut ( self . idx ) } ;
739
+ v
740
+ }
741
+
742
+ /// Consumes this entry and yields a reference to the underlying value
743
+ pub fn into_mut ( self ) -> & ' a mut V {
744
+ // SAFETY: Valid idx from OccupiedEntry construction
745
+ let ( _k, v) = unsafe { self . map . buffer . get_unchecked_mut ( self . idx ) } ;
746
+ v
747
+ }
748
+
749
+ /// Overwrites the underlying map's value with this entry's value
750
+ pub fn insert ( self , value : V ) -> V {
751
+ // SAFETY: Valid idx from OccupiedEntry construction
752
+ let ( _k, v) = unsafe { self . map . buffer . get_unchecked_mut ( self . idx ) } ;
753
+ mem:: replace ( v, value)
754
+ }
755
+ }
756
+
757
+ /// A view into an empty slot in the underlying map
758
+ pub struct VacantEntry < ' a , K , V > {
759
+ key : K ,
760
+ map : & ' a mut LinearMapView < K , V > ,
761
+ }
762
+
763
+ impl < ' a , K , V > VacantEntry < ' a , K , V >
764
+ where
765
+ K : Eq ,
766
+ {
767
+ /// Get the key associated with this entry
768
+ pub fn key ( & self ) -> & K {
769
+ & self . key
770
+ }
771
+
772
+ /// Consumes this entry to yield to key associated with it
773
+ pub fn into_key ( self ) -> K {
774
+ self . key
775
+ }
776
+
777
+ /// Inserts this entry into to underlying map, yields a mutable reference to the inserted value.
778
+ /// If the map is at capacity the value is returned instead.
779
+ pub fn insert ( self , value : V ) -> Result < & ' a mut V , V > {
780
+ self . map
781
+ . buffer
782
+ . push ( ( self . key , value) )
783
+ . map_err ( |( _k, v) | v) ?;
784
+ let idx = self . map . buffer . len ( ) - 1 ;
785
+ let r = & mut self . map . buffer [ idx] ;
786
+ Ok ( & mut r. 1 )
787
+ }
788
+ }
789
+
646
790
#[ cfg( test) ]
647
791
mod test {
648
792
use static_assertions:: assert_not_impl_any;
649
793
650
- use super :: { LinearMap , LinearMapView } ;
794
+ use super :: { Entry , LinearMap , LinearMapView } ;
651
795
652
796
// Ensure a `LinearMap` containing `!Send` keys stays `!Send` itself.
653
797
assert_not_impl_any ! ( LinearMap <* const ( ) , ( ) , 4 >: Send ) ;
@@ -780,4 +924,205 @@ mod test {
780
924
assert_eq ! ( map. len( ) , 0 ) ;
781
925
assert ! ( map. is_empty( ) ) ;
782
926
}
927
+
928
+ // tests that use this constant take too long to run under miri, specially on CI, with a map of
929
+ // this size so make the map smaller when using miri
930
+ #[ cfg( not( miri) ) ]
931
+ const MAP_SLOTS : usize = 4096 ;
932
+ #[ cfg( miri) ]
933
+ const MAP_SLOTS : usize = 64 ;
934
+ fn almost_filled_map ( ) -> LinearMap < usize , usize , MAP_SLOTS > {
935
+ let mut almost_filled = LinearMap :: new ( ) ;
936
+ for i in 1 ..MAP_SLOTS {
937
+ almost_filled. insert ( i, i) . unwrap ( ) ;
938
+ }
939
+ almost_filled
940
+ }
941
+
942
+ #[ test]
943
+ fn remove ( ) {
944
+ let mut src = almost_filled_map ( ) ;
945
+ // key doesn't exist
946
+ let k = 0 ;
947
+ let r = src. remove ( & k) ;
948
+ assert ! ( r. is_none( ) ) ;
949
+
950
+ let k = 5 ;
951
+ let v = 5 ;
952
+ let r = src. remove ( & k) ;
953
+ assert_eq ! ( r, Some ( v) ) ;
954
+ let r = src. remove ( & k) ;
955
+ assert ! ( r. is_none( ) ) ;
956
+ assert_eq ! ( src. len( ) , MAP_SLOTS - 2 ) ;
957
+ }
958
+
959
+ #[ test]
960
+ fn replace ( ) {
961
+ let mut src = almost_filled_map ( ) ;
962
+ src. insert ( 10 , 1000 ) . unwrap ( ) ;
963
+ let v = src. get ( & 10 ) . unwrap ( ) ;
964
+ assert_eq ! ( * v, 1000 ) ;
965
+
966
+ let mut src = almost_filled_map ( ) ;
967
+ let v = src. get_mut ( & 10 ) . unwrap ( ) ;
968
+ * v = 500 ;
969
+ let v = src. get ( & 10 ) . unwrap ( ) ;
970
+ assert_eq ! ( * v, 500 ) ;
971
+ }
972
+
973
+ #[ test]
974
+ fn retain ( ) {
975
+ let mut src = almost_filled_map ( ) ;
976
+ src. retain ( |k, _v| k % 2 == 0 ) ;
977
+ src. retain ( |k, _v| k % 3 == 0 ) ;
978
+
979
+ for ( k, v) in src. iter ( ) {
980
+ assert_eq ! ( k, v) ;
981
+ assert_eq ! ( k % 2 , 0 ) ;
982
+ assert_eq ! ( k % 3 , 0 ) ;
983
+ }
984
+
985
+ let mut src = almost_filled_map ( ) ;
986
+ src. retain ( |_k, _v| false ) ;
987
+ assert ! ( src. is_empty( ) ) ;
988
+
989
+ let mut src = almost_filled_map ( ) ;
990
+ src. retain ( |_k, _v| true ) ;
991
+ assert_eq ! ( src. len( ) , MAP_SLOTS - 1 ) ;
992
+ src. insert ( 0 , 0 ) . unwrap ( ) ;
993
+ src. retain ( |_k, _v| true ) ;
994
+ assert_eq ! ( src. len( ) , MAP_SLOTS ) ;
995
+ }
996
+
997
+ #[ test]
998
+ fn entry_find ( ) {
999
+ let key = 0 ;
1000
+ let value = 0 ;
1001
+ let mut src = almost_filled_map ( ) ;
1002
+ let entry = src. entry ( key) ;
1003
+ match entry {
1004
+ Entry :: Occupied ( _) => {
1005
+ panic ! ( "Found entry without inserting" ) ;
1006
+ }
1007
+ Entry :: Vacant ( v) => {
1008
+ assert_eq ! ( & key, v. key( ) ) ;
1009
+ assert_eq ! ( key, v. into_key( ) ) ;
1010
+ }
1011
+ }
1012
+ src. insert ( key, value) . unwrap ( ) ;
1013
+ let entry = src. entry ( key) ;
1014
+ match entry {
1015
+ Entry :: Occupied ( mut o) => {
1016
+ assert_eq ! ( & key, o. key( ) ) ;
1017
+ assert_eq ! ( & value, o. get( ) ) ;
1018
+ assert_eq ! ( & value, o. get_mut( ) ) ;
1019
+ assert_eq ! ( & value, o. into_mut( ) ) ;
1020
+ }
1021
+ Entry :: Vacant ( _) => {
1022
+ panic ! ( "Entry not found" ) ;
1023
+ }
1024
+ }
1025
+ }
1026
+
1027
+ #[ test]
1028
+ fn entry_vacant_insert ( ) {
1029
+ let key = 0 ;
1030
+ let value = 0 ;
1031
+ let mut src = almost_filled_map ( ) ;
1032
+ assert_eq ! ( MAP_SLOTS - 1 , src. len( ) ) ;
1033
+ let entry = src. entry ( key) ;
1034
+ match entry {
1035
+ Entry :: Occupied ( _) => {
1036
+ panic ! ( "Entry found when empty" ) ;
1037
+ }
1038
+ Entry :: Vacant ( v) => {
1039
+ assert_eq ! ( value, * v. insert( value) . unwrap( ) ) ;
1040
+ }
1041
+ } ;
1042
+ assert_eq ! ( value, * src. get( & key) . unwrap( ) ) ;
1043
+ }
1044
+
1045
+ #[ test]
1046
+ fn entry_vacant_full_insert ( ) {
1047
+ let mut src = almost_filled_map ( ) ;
1048
+
1049
+ // fill the map
1050
+ let key = MAP_SLOTS * 2 ;
1051
+ let value = key;
1052
+ src. insert ( key, value) . unwrap ( ) ;
1053
+ assert_eq ! ( MAP_SLOTS , src. len( ) ) ;
1054
+
1055
+ let key = 0 ;
1056
+ let value = 0 ;
1057
+ let entry = src. entry ( key) ;
1058
+ match entry {
1059
+ Entry :: Occupied ( _) => {
1060
+ panic ! ( "Entry found when missing" ) ;
1061
+ }
1062
+ Entry :: Vacant ( v) => {
1063
+ // Value is returned since the map is full
1064
+ assert_eq ! ( value, v. insert( value) . unwrap_err( ) ) ;
1065
+ }
1066
+ } ;
1067
+ assert ! ( src. get( & key) . is_none( ) ) ;
1068
+ }
1069
+
1070
+ #[ test]
1071
+ fn entry_occupied_insert ( ) {
1072
+ let key = 0 ;
1073
+ let value = 0 ;
1074
+ let value2 = 5 ;
1075
+ let mut src = almost_filled_map ( ) ;
1076
+ assert_eq ! ( MAP_SLOTS - 1 , src. len( ) ) ;
1077
+ src. insert ( key, value) . unwrap ( ) ;
1078
+ let entry = src. entry ( key) ;
1079
+ match entry {
1080
+ Entry :: Occupied ( o) => {
1081
+ assert_eq ! ( value, o. insert( value2) ) ;
1082
+ }
1083
+ Entry :: Vacant ( _) => {
1084
+ panic ! ( "Entry not found" ) ;
1085
+ }
1086
+ } ;
1087
+ assert_eq ! ( value2, * src. get( & key) . unwrap( ) ) ;
1088
+ }
1089
+
1090
+ #[ test]
1091
+ fn entry_remove_entry ( ) {
1092
+ let key = 0 ;
1093
+ let value = 0 ;
1094
+ let mut src = almost_filled_map ( ) ;
1095
+ src. insert ( key, value) . unwrap ( ) ;
1096
+ assert_eq ! ( MAP_SLOTS , src. len( ) ) ;
1097
+ let entry = src. entry ( key) ;
1098
+ match entry {
1099
+ Entry :: Occupied ( o) => {
1100
+ assert_eq ! ( ( key, value) , o. remove_entry( ) ) ;
1101
+ }
1102
+ Entry :: Vacant ( _) => {
1103
+ panic ! ( "Entry not found" )
1104
+ }
1105
+ } ;
1106
+ assert_eq ! ( MAP_SLOTS - 1 , src. len( ) ) ;
1107
+ assert ! ( !src. contains_key( & key) ) ;
1108
+ }
1109
+
1110
+ #[ test]
1111
+ fn entry_remove ( ) {
1112
+ let key = 0 ;
1113
+ let value = 0 ;
1114
+ let mut src = almost_filled_map ( ) ;
1115
+ src. insert ( key, value) . unwrap ( ) ;
1116
+ assert_eq ! ( MAP_SLOTS , src. len( ) ) ;
1117
+ let entry = src. entry ( key) ;
1118
+ match entry {
1119
+ Entry :: Occupied ( o) => {
1120
+ assert_eq ! ( value, o. remove( ) ) ;
1121
+ }
1122
+ Entry :: Vacant ( _) => {
1123
+ panic ! ( "Entry not found" ) ;
1124
+ }
1125
+ } ;
1126
+ assert_eq ! ( MAP_SLOTS - 1 , src. len( ) ) ;
1127
+ }
783
1128
}
0 commit comments