@@ -56,6 +56,16 @@ impl<T, V> ArenaMap<Idx<T>, V> {
56
56
self . v . iter ( ) . enumerate ( ) . filter_map ( |( idx, o) | Some ( ( Self :: from_idx ( idx) , o. as_ref ( ) ?) ) )
57
57
}
58
58
59
+ /// Gets the given key's corresponding entry in the map for in-place manipulation.
60
+ pub fn entry ( & mut self , idx : Idx < T > ) -> Entry < ' _ , Idx < T > , V > {
61
+ let idx = Self :: to_idx ( idx) ;
62
+ self . v . resize_with ( ( idx + 1 ) . max ( self . v . len ( ) ) , || None ) ;
63
+ match & mut self . v [ idx] {
64
+ slot @ Some ( _) => Entry :: Occupied ( OccupiedEntry { slot, _ty : PhantomData } ) ,
65
+ slot @ None => Entry :: Vacant ( VacantEntry { slot, _ty : PhantomData } ) ,
66
+ }
67
+ }
68
+
59
69
fn to_idx ( idx : Idx < T > ) -> usize {
60
70
u32:: from ( idx. into_raw ( ) ) as usize
61
71
}
@@ -83,3 +93,100 @@ impl<T, V> Default for ArenaMap<Idx<V>, T> {
83
93
Self :: new ( )
84
94
}
85
95
}
96
+
97
+ /// A view into a single entry in a map, which may either be vacant or occupied.
98
+ ///
99
+ /// This `enum` is constructed from the [`entry`] method on [`ArenaMap`].
100
+ ///
101
+ /// [`entry`]: ArenaMap::entry
102
+ pub enum Entry < ' a , IDX , V > {
103
+ /// A vacant entry.
104
+ Vacant ( VacantEntry < ' a , IDX , V > ) ,
105
+ /// An occupied entry.
106
+ Occupied ( OccupiedEntry < ' a , IDX , V > ) ,
107
+ }
108
+
109
+ impl < ' a , IDX , V > Entry < ' a , IDX , V > {
110
+ /// Ensures a value is in the entry by inserting the default if empty, and returns a mutable reference to
111
+ /// the value in the entry.
112
+ pub fn or_insert ( self , default : V ) -> & ' a mut V {
113
+ match self {
114
+ Self :: Vacant ( ent) => ent. insert ( default) ,
115
+ Self :: Occupied ( ent) => ent. into_mut ( ) ,
116
+ }
117
+ }
118
+
119
+ /// Ensures a value is in the entry by inserting the result of the default function if empty, and returns
120
+ /// a mutable reference to the value in the entry.
121
+ pub fn or_insert_with < F : FnOnce ( ) -> V > ( self , default : F ) -> & ' a mut V {
122
+ match self {
123
+ Self :: Vacant ( ent) => ent. insert ( default ( ) ) ,
124
+ Self :: Occupied ( ent) => ent. into_mut ( ) ,
125
+ }
126
+ }
127
+
128
+ /// Provides in-place mutable access to an occupied entry before any potential inserts into the map.
129
+ pub fn and_modify < F : FnOnce ( & mut V ) > ( mut self , f : F ) -> Self {
130
+ if let Self :: Occupied ( ent) = & mut self {
131
+ f ( ent. get_mut ( ) ) ;
132
+ }
133
+ self
134
+ }
135
+ }
136
+
137
+ impl < ' a , IDX , V > Entry < ' a , IDX , V >
138
+ where
139
+ V : Default ,
140
+ {
141
+ /// Ensures a value is in the entry by inserting the default value if empty, and returns a mutable reference
142
+ /// to the value in the entry.
143
+ pub fn or_default ( self ) -> & ' a mut V {
144
+ self . or_insert_with ( Default :: default)
145
+ }
146
+ }
147
+
148
+ /// A view into an vacant entry in a [`ArenaMap`]. It is part of the [`Entry`] enum.
149
+ pub struct VacantEntry < ' a , IDX , V > {
150
+ slot : & ' a mut Option < V > ,
151
+ _ty : PhantomData < IDX > ,
152
+ }
153
+
154
+ impl < ' a , IDX , V > VacantEntry < ' a , IDX , V > {
155
+ /// Sets the value of the entry with the `VacantEntry`’s key, and returns a mutable reference to it.
156
+ pub fn insert ( self , value : V ) -> & ' a mut V {
157
+ self . slot . insert ( value)
158
+ }
159
+ }
160
+
161
+ /// A view into an occupied entry in a [`ArenaMap`]. It is part of the [`Entry`] enum.
162
+ pub struct OccupiedEntry < ' a , IDX , V > {
163
+ slot : & ' a mut Option < V > ,
164
+ _ty : PhantomData < IDX > ,
165
+ }
166
+
167
+ impl < ' a , IDX , V > OccupiedEntry < ' a , IDX , V > {
168
+ /// Gets a reference to the value in the entry.
169
+ pub fn get ( & self ) -> & V {
170
+ self . slot . as_ref ( ) . expect ( "Occupied" )
171
+ }
172
+
173
+ /// Gets a mutable reference to the value in the entry.
174
+ pub fn get_mut ( & mut self ) -> & mut V {
175
+ self . slot . as_mut ( ) . expect ( "Occupied" )
176
+ }
177
+
178
+ /// Converts the entry into a mutable reference to its value.
179
+ pub fn into_mut ( self ) -> & ' a mut V {
180
+ self . slot . as_mut ( ) . expect ( "Occupied" )
181
+ }
182
+
183
+ /// Sets the value of the entry with the `OccupiedEntry`’s key, and returns the entry’s old value.
184
+ pub fn insert ( & mut self , value : V ) -> V {
185
+ self . slot . replace ( value) . expect ( "Occupied" )
186
+ }
187
+
188
+ /// Takes the value of the entry out of the map, and returns it.
189
+ pub fn remove ( self ) -> V {
190
+ self . slot . take ( ) . expect ( "Occupied" )
191
+ }
192
+ }
0 commit comments