@@ -38,25 +38,35 @@ impl<const N: usize, Value> IndexMap<N, Value> {
3838
3939 #[ inline( always) ]
4040 pub ( crate ) unsafe fn delete ( & mut self , index : usize ) {
41- unsafe { * self . index . get_unchecked_mut ( index) = Self :: NULL }
41+ * unsafe { self . index . get_unchecked_mut ( index) } = Self :: NULL ;
4242 }
4343
4444 #[ inline( always) ]
4545 pub ( crate ) unsafe fn set ( & mut self , index : usize , value : Value ) {
46- unsafe { * self . index . get_unchecked_mut ( index) = self . values . len ( ) as u8 }
46+ * unsafe { self . index . get_unchecked_mut ( index) } = self . values . len ( ) as u8 ;
4747 self . values . push ( ( index, value) ) ;
4848 }
4949
5050 #[ inline( always) ]
51- pub ( crate ) fn iter ( & self ) -> impl Iterator < Item = & ( usize , Value ) > {
51+ pub ( crate ) fn iter ( & self ) -> impl Iterator < Item = ( usize , & Value ) > {
5252 self . values . iter ( )
53- . filter ( |( i, _) | * unsafe { self . index . get_unchecked ( * i) } != Self :: NULL )
53+ . enumerate ( )
54+ . filter_map ( |( pos, ( index, value) ) | (
55+ // `!= Self::NULL` can't correctly handle *over-set after delete*,
56+ // we MUST check the held index to be equal to the current position
57+ * unsafe { self . index . get_unchecked ( * index) } == pos as u8
58+ ) . then_some ( ( * index, value) ) )
5459 }
5560
5661 #[ inline( always) ]
5762 pub ( crate ) fn into_iter ( self ) -> impl Iterator < Item = ( usize , Value ) > {
5863 self . values . into_iter ( )
59- . filter ( move |( i, _) | * unsafe { self . index . get_unchecked ( * i) } != Self :: NULL )
64+ . enumerate ( )
65+ . filter_map ( move |( pos, ( index, value) ) | (
66+ // `!= Self::NULL` can't correctly handle *over-set after delete*,
67+ // we MUST check the held index to be equal to the current position
68+ * unsafe { self . index . get_unchecked ( index) } == pos as u8
69+ ) . then_some ( ( index, value) ) )
6070 }
6171}
6272
@@ -80,3 +90,83 @@ const _: () = {
8090 }
8191 }
8292} ;
93+
94+ #[ cfg( test) ]
95+ mod test {
96+ use super :: * ;
97+
98+ #[ test]
99+ fn test_index_map_iter_simple ( ) {
100+ let mut map = IndexMap :: < 8 , & ' static str > :: new ( ) ;
101+
102+ unsafe { map. set ( 0 , "a" ) } ;
103+ unsafe { map. set ( 1 , "b" ) } ;
104+ unsafe { map. set ( 2 , "c" ) } ;
105+ unsafe { map. set ( 3 , "d" ) } ;
106+
107+ assert_eq ! (
108+ map. into_iter( ) . collect:: <Vec <_>>( ) ,
109+ vec![ ( 0 , "a" ) , ( 1 , "b" ) , ( 2 , "c" ) , ( 3 , "d" ) ]
110+ ) ;
111+ }
112+
113+ #[ test]
114+ fn test_index_map_iter_with_delete ( ) {
115+ let mut map = IndexMap :: < 8 , & ' static str > :: new ( ) ;
116+
117+ unsafe { map. set ( 0 , "a" ) } ;
118+ unsafe { map. set ( 1 , "b" ) } ;
119+ unsafe { map. set ( 2 , "c" ) } ;
120+ unsafe { map. set ( 3 , "d" ) } ;
121+
122+ unsafe { map. delete ( 1 ) } ;
123+ unsafe { map. delete ( 3 ) } ;
124+
125+ assert_eq ! (
126+ map. into_iter( ) . collect:: <Vec <_>>( ) ,
127+ vec![ ( 0 , "a" ) , ( 2 , "c" ) ]
128+ ) ;
129+ }
130+
131+ #[ test]
132+ fn test_index_map_iter_with_delete_and_other_set ( ) {
133+ let mut map = IndexMap :: < 8 , & ' static str > :: new ( ) ;
134+
135+ unsafe { map. set ( 0 , "a" ) } ;
136+ unsafe { map. set ( 1 , "b" ) } ;
137+ unsafe { map. set ( 2 , "c" ) } ;
138+ unsafe { map. set ( 3 , "d" ) } ;
139+
140+ unsafe { map. delete ( 1 ) } ;
141+ unsafe { map. delete ( 3 ) } ;
142+
143+ unsafe { map. set ( 4 , "e" ) } ;
144+ unsafe { map. set ( 5 , "f" ) } ;
145+
146+ assert_eq ! (
147+ map. into_iter( ) . collect:: <Vec <_>>( ) ,
148+ vec![ ( 0 , "a" ) , ( 2 , "c" ) , ( 4 , "e" ) , ( 5 , "f" ) ]
149+ ) ;
150+ }
151+
152+ #[ test]
153+ fn test_index_map_iter_with_delete_and_overset ( ) {
154+ let mut map = IndexMap :: < 8 , & ' static str > :: new ( ) ;
155+
156+ unsafe { map. set ( 0 , "a" ) } ;
157+ unsafe { map. set ( 1 , "b" ) } ;
158+ unsafe { map. set ( 2 , "c" ) } ;
159+ unsafe { map. set ( 3 , "d" ) } ;
160+
161+ unsafe { map. delete ( 1 ) } ;
162+ unsafe { map. delete ( 3 ) } ;
163+
164+ unsafe { map. set ( 1 , "e" ) } ;
165+ unsafe { map. set ( 3 , "f" ) } ;
166+
167+ assert_eq ! (
168+ map. into_iter( ) . collect:: <Vec <_>>( ) ,
169+ vec![ ( 0 , "a" ) , ( 2 , "c" ) , ( 1 , "e" ) , ( 3 , "f" ) ]
170+ ) ;
171+ }
172+ }
0 commit comments