@@ -475,6 +475,50 @@ where
475475 pub fn values_mut ( & mut self ) -> impl Iterator < Item = & mut V > {
476476 self . iter_mut ( ) . map ( |( _, v) | v)
477477 }
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+ }
478522}
479523
480524impl < K , V , Q , S : LinearMapStorage < K , V > + ?Sized > ops:: Index < & ' _ Q > for LinearMapInner < K , V , S >
@@ -643,11 +687,111 @@ where
643687{
644688}
645689
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+
646790#[ cfg( test) ]
647791mod test {
648792 use static_assertions:: assert_not_impl_any;
649793
650- use super :: { LinearMap , LinearMapView } ;
794+ use super :: { Entry , LinearMap , LinearMapView } ;
651795
652796 // Ensure a `LinearMap` containing `!Send` keys stays `!Send` itself.
653797 assert_not_impl_any ! ( LinearMap <* const ( ) , ( ) , 4 >: Send ) ;
@@ -780,4 +924,205 @@ mod test {
780924 assert_eq ! ( map. len( ) , 0 ) ;
781925 assert ! ( map. is_empty( ) ) ;
782926 }
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+ }
7831128}
0 commit comments