@@ -475,6 +475,40 @@ 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
+ }
478
512
}
479
513
480
514
impl < K , V , Q , S : LinearMapStorage < K , V > + ?Sized > ops:: Index < & ' _ Q > for LinearMapInner < K , V , S >
@@ -643,11 +677,111 @@ where
643
677
{
644
678
}
645
679
680
+ /// A view into an entry in the map
681
+ pub enum Entry < ' a , K , V > {
682
+ /// The entry corresponding to the key `K` exists in the map
683
+ Occupied ( OccupiedEntry < ' a , K , V > ) ,
684
+ /// The entry corresponding to the key `K` does not exist in the map
685
+ Vacant ( VacantEntry < ' a , K , V > ) ,
686
+ }
687
+
688
+ /// An occupied entry which can be manipulated
689
+ pub struct OccupiedEntry < ' a , K , V > {
690
+ // SAFETY: `idx` must not be modified after construction, and
691
+ // the size of `map` must not be changed.
692
+ idx : usize ,
693
+ map : & ' a mut LinearMapView < K , V > ,
694
+ }
695
+
696
+ impl < ' a , K , V > OccupiedEntry < ' a , K , V >
697
+ where
698
+ K : Eq ,
699
+ {
700
+ /// Gets a reference to the key that this entity corresponds to
701
+ pub fn key ( & self ) -> & K {
702
+ // SAFETY: Valid idx from OccupiedEntry construction
703
+ let ( k, _v) = unsafe { self . map . buffer . get_unchecked ( self . idx ) } ;
704
+ k
705
+ }
706
+
707
+ /// Removes this entry from the map and yields its corresponding key and value
708
+ pub fn remove_entry ( self ) -> ( K , V ) {
709
+ // SAFETY: Valid idx from OccupiedEntry construction
710
+ unsafe { self . map . buffer . swap_remove_unchecked ( self . idx ) }
711
+ }
712
+
713
+ /// Removes this entry from the map and yields its corresponding key and value
714
+ pub fn remove ( self ) -> V {
715
+ self . remove_entry ( ) . 1
716
+ }
717
+
718
+ /// Gets a reference to the value associated with this entry
719
+ pub fn get ( & self ) -> & V {
720
+ // SAFETY: Valid idx from OccupiedEntry construction
721
+ let ( _k, v) = unsafe { self . map . buffer . get_unchecked ( self . idx ) } ;
722
+ v
723
+ }
724
+
725
+ /// Gets a mutable reference to the value associated with this entry
726
+ pub fn get_mut ( & mut self ) -> & mut V {
727
+ // SAFETY: Valid idx from OccupiedEntry construction
728
+ let ( _k, v) = unsafe { self . map . buffer . get_unchecked_mut ( self . idx ) } ;
729
+ v
730
+ }
731
+
732
+ /// Consumes this entry and yields a reference to the underlying value
733
+ pub fn into_mut ( self ) -> & ' a mut V {
734
+ // SAFETY: Valid idx from OccupiedEntry construction
735
+ let ( _k, v) = unsafe { self . map . buffer . get_unchecked_mut ( self . idx ) } ;
736
+ v
737
+ }
738
+
739
+ /// Overwrites the underlying map's value with this entry's value
740
+ pub fn insert ( self , value : V ) -> V {
741
+ // SAFETY: Valid idx from OccupiedEntry construction
742
+ let ( _k, v) = unsafe { self . map . buffer . get_unchecked_mut ( self . idx ) } ;
743
+ mem:: replace ( v, value)
744
+ }
745
+ }
746
+
747
+ /// A view into an empty slot in the underlying map
748
+ pub struct VacantEntry < ' a , K , V > {
749
+ key : K ,
750
+ map : & ' a mut LinearMapView < K , V > ,
751
+ }
752
+
753
+ impl < ' a , K , V > VacantEntry < ' a , K , V >
754
+ where
755
+ K : Eq ,
756
+ {
757
+ /// Get the key associated with this entry
758
+ pub fn key ( & self ) -> & K {
759
+ & self . key
760
+ }
761
+
762
+ /// Consumes this entry to yield to key associated with it
763
+ pub fn into_key ( self ) -> K {
764
+ self . key
765
+ }
766
+
767
+ /// Inserts this entry into to underlying map, yields a mutable reference to the inserted value.
768
+ /// If the map is at capacity the value is returned instead.
769
+ pub fn insert ( self , value : V ) -> Result < & ' a mut V , V > {
770
+ self . map
771
+ . buffer
772
+ . push ( ( self . key , value) )
773
+ . map_err ( |( _k, v) | v) ?;
774
+ let idx = self . map . buffer . len ( ) - 1 ;
775
+ let r = & mut self . map . buffer [ idx] ;
776
+ Ok ( & mut r. 1 )
777
+ }
778
+ }
779
+
646
780
#[ cfg( test) ]
647
781
mod test {
648
782
use static_assertions:: assert_not_impl_any;
649
783
650
- use super :: { LinearMap , LinearMapView } ;
784
+ use super :: { Entry , LinearMap , LinearMapView } ;
651
785
652
786
// Ensure a `LinearMap` containing `!Send` keys stays `!Send` itself.
653
787
assert_not_impl_any ! ( LinearMap <* const ( ) , ( ) , 4 >: Send ) ;
@@ -780,4 +914,124 @@ mod test {
780
914
assert_eq ! ( map. len( ) , 0 ) ;
781
915
assert ! ( map. is_empty( ) ) ;
782
916
}
917
+
918
+ // tests that use this constant take too long to run under miri, specially on CI, with a map of
919
+ // this size so make the map smaller when using miri
920
+ #[ cfg( not( miri) ) ]
921
+ const MAP_SLOTS : usize = 4096 ;
922
+ #[ cfg( miri) ]
923
+ const MAP_SLOTS : usize = 64 ;
924
+ fn almost_filled_map ( ) -> LinearMap < usize , usize , MAP_SLOTS > {
925
+ let mut almost_filled = LinearMap :: new ( ) ;
926
+ for i in 1 ..MAP_SLOTS {
927
+ almost_filled. insert ( i, i) . unwrap ( ) ;
928
+ }
929
+ almost_filled
930
+ }
931
+
932
+ #[ test]
933
+ fn entry_find ( ) {
934
+ let key = 0 ;
935
+ let value = 0 ;
936
+ let mut src = almost_filled_map ( ) ;
937
+ let entry = src. entry ( key) ;
938
+ match entry {
939
+ Entry :: Occupied ( _) => {
940
+ panic ! ( "Found entry without inserting" ) ;
941
+ }
942
+ Entry :: Vacant ( v) => {
943
+ assert_eq ! ( & key, v. key( ) ) ;
944
+ assert_eq ! ( key, v. into_key( ) ) ;
945
+ }
946
+ }
947
+ src. insert ( key, value) . unwrap ( ) ;
948
+ let entry = src. entry ( key) ;
949
+ match entry {
950
+ Entry :: Occupied ( mut o) => {
951
+ assert_eq ! ( & key, o. key( ) ) ;
952
+ assert_eq ! ( & value, o. get( ) ) ;
953
+ assert_eq ! ( & value, o. get_mut( ) ) ;
954
+ assert_eq ! ( & value, o. into_mut( ) ) ;
955
+ }
956
+ Entry :: Vacant ( _) => {
957
+ panic ! ( "Entry not found" ) ;
958
+ }
959
+ }
960
+ }
961
+
962
+ #[ test]
963
+ fn entry_vacant_insert ( ) {
964
+ let key = 0 ;
965
+ let value = 0 ;
966
+ let mut src = almost_filled_map ( ) ;
967
+ assert_eq ! ( MAP_SLOTS - 1 , src. len( ) ) ;
968
+ let entry = src. entry ( key) ;
969
+ match entry {
970
+ Entry :: Occupied ( _) => {
971
+ panic ! ( "Entry found when empty" ) ;
972
+ }
973
+ Entry :: Vacant ( v) => {
974
+ assert_eq ! ( value, * v. insert( value) . unwrap( ) ) ;
975
+ }
976
+ } ;
977
+ assert_eq ! ( value, * src. get( & key) . unwrap( ) ) ;
978
+ }
979
+
980
+ #[ test]
981
+ fn entry_occupied_insert ( ) {
982
+ let key = 0 ;
983
+ let value = 0 ;
984
+ let value2 = 5 ;
985
+ let mut src = almost_filled_map ( ) ;
986
+ assert_eq ! ( MAP_SLOTS - 1 , src. len( ) ) ;
987
+ src. insert ( key, value) . unwrap ( ) ;
988
+ let entry = src. entry ( key) ;
989
+ match entry {
990
+ Entry :: Occupied ( o) => {
991
+ assert_eq ! ( value, o. insert( value2) ) ;
992
+ }
993
+ Entry :: Vacant ( _) => {
994
+ panic ! ( "Entry not found" ) ;
995
+ }
996
+ } ;
997
+ assert_eq ! ( value2, * src. get( & key) . unwrap( ) ) ;
998
+ }
999
+
1000
+ #[ test]
1001
+ fn entry_remove_entry ( ) {
1002
+ let key = 0 ;
1003
+ let value = 0 ;
1004
+ let mut src = almost_filled_map ( ) ;
1005
+ src. insert ( key, value) . unwrap ( ) ;
1006
+ assert_eq ! ( MAP_SLOTS , src. len( ) ) ;
1007
+ let entry = src. entry ( key) ;
1008
+ match entry {
1009
+ Entry :: Occupied ( o) => {
1010
+ assert_eq ! ( ( key, value) , o. remove_entry( ) ) ;
1011
+ }
1012
+ Entry :: Vacant ( _) => {
1013
+ panic ! ( "Entry not found" )
1014
+ }
1015
+ } ;
1016
+ assert_eq ! ( MAP_SLOTS - 1 , src. len( ) ) ;
1017
+ }
1018
+
1019
+ #[ test]
1020
+ fn entry_remove ( ) {
1021
+ let key = 0 ;
1022
+ let value = 0 ;
1023
+ let mut src = almost_filled_map ( ) ;
1024
+ src. insert ( key, value) . unwrap ( ) ;
1025
+ assert_eq ! ( MAP_SLOTS , src. len( ) ) ;
1026
+ let entry = src. entry ( key) ;
1027
+ match entry {
1028
+ Entry :: Occupied ( o) => {
1029
+ assert_eq ! ( value, o. remove( ) ) ;
1030
+ }
1031
+ Entry :: Vacant ( _) => {
1032
+ panic ! ( "Entry not found" ) ;
1033
+ }
1034
+ } ;
1035
+ assert_eq ! ( MAP_SLOTS - 1 , src. len( ) ) ;
1036
+ }
783
1037
}
0 commit comments