@@ -3,6 +3,7 @@ use core::{
33 iter:: { Enumerate , FusedIterator , repeat_with} ,
44 marker:: PhantomData ,
55 ops:: { Index , IndexMut , Range } ,
6+ ptr:: NonNull ,
67} ;
78
89/// An append-only [`Arena`] whose entities have stable addresses.
@@ -155,6 +156,21 @@ where
155156 . ok_or ( ArenaError :: KeyOutOfBounds )
156157 }
157158
159+ /// Returns a raw pointer to the entity at the given key.
160+ ///
161+ /// Unlike [`get_mut`](StableArena::get_mut), this never forms an intermediate `&mut T`, so the
162+ /// pointer carries the entity's underlying allocation provenance.
163+ ///
164+ /// # Errors
165+ ///
166+ /// If the `key` is out of bounds.
167+ #[ inline]
168+ pub fn get_mut_ptr ( & mut self , key : Key ) -> Result < NonNull < T > , ArenaError > {
169+ self . items
170+ . get_mut_ptr ( key. into_usize ( ) )
171+ . ok_or ( ArenaError :: KeyOutOfBounds )
172+ }
173+
158174 /// Returns exclusive references to the pair of entities at the given keys if any.
159175 ///
160176 /// # Errors
@@ -406,6 +422,19 @@ mod tests {
406422 ) ) ;
407423 }
408424
425+ #[ test]
426+ fn get_mut_ptr_writes_through ( ) {
427+ let mut arena: Arena = ( 0 ..10 ) . collect ( ) ;
428+ let ptr = arena. get_mut_ptr ( 3 ) . unwrap ( ) ;
429+ // Safety: key `3` is in bounds and uniquely owned here.
430+ unsafe { * ptr. as_ptr ( ) = 30 } ;
431+ assert_eq ! ( arena. get( 3 ) . unwrap( ) , & 30 ) ;
432+ assert ! ( matches!(
433+ arena. get_mut_ptr( 10 ) ,
434+ Err ( ArenaError :: KeyOutOfBounds )
435+ ) ) ;
436+ }
437+
409438 #[ test]
410439 fn iter_yields_keys_and_is_double_ended ( ) {
411440 let arena: Arena = ( 0 ..5 ) . collect ( ) ;
0 commit comments