@@ -11,6 +11,16 @@ pub struct ArenaMap<IDX, V> {
1111}
1212
1313impl < T , V > ArenaMap < Idx < T > , V > {
14+ /// Creates a new empty map.
15+ pub const fn new ( ) -> Self {
16+ Self { v : Vec :: new ( ) , _ty : PhantomData }
17+ }
18+
19+ /// Create a new empty map with specific capacity.
20+ pub fn with_capacity ( capacity : usize ) -> Self {
21+ Self { v : Vec :: with_capacity ( capacity) , _ty : PhantomData }
22+ }
23+
1424 /// Inserts a value associated with a given arena index into the map.
1525 pub fn insert ( & mut self , idx : Idx < T > , t : V ) {
1626 let idx = Self :: to_idx ( idx) ;
@@ -46,6 +56,16 @@ impl<T, V> ArenaMap<Idx<T>, V> {
4656 self . v . iter ( ) . enumerate ( ) . filter_map ( |( idx, o) | Some ( ( Self :: from_idx ( idx) , o. as_ref ( ) ?) ) )
4757 }
4858
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+
4969 fn to_idx ( idx : Idx < T > ) -> usize {
5070 u32:: from ( idx. into_raw ( ) ) as usize
5171 }
@@ -70,6 +90,103 @@ impl<T, V> std::ops::IndexMut<Idx<V>> for ArenaMap<Idx<V>, T> {
7090
7191impl < T , V > Default for ArenaMap < Idx < V > , T > {
7292 fn default ( ) -> Self {
73- ArenaMap { v : Vec :: new ( ) , _ty : PhantomData }
93+ Self :: new ( )
94+ }
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" )
74191 }
75192}
0 commit comments