@@ -67,6 +67,54 @@ unsafe impl Allocator for Pool {
6767 ngx_pfree ( self . 0 . as_ptr ( ) , ptr. as_ptr ( ) . cast ( ) ) ;
6868 }
6969 }
70+
71+ unsafe fn grow (
72+ & self ,
73+ ptr : NonNull < u8 > ,
74+ old_layout : Layout ,
75+ new_layout : Layout ,
76+ ) -> Result < NonNull < [ u8 ] > , AllocError > {
77+ debug_assert ! (
78+ new_layout. size( ) >= old_layout. size( ) ,
79+ "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
80+ ) ;
81+ self . resize ( ptr, old_layout, new_layout)
82+ }
83+
84+ unsafe fn grow_zeroed (
85+ & self ,
86+ ptr : NonNull < u8 > ,
87+ old_layout : Layout ,
88+ new_layout : Layout ,
89+ ) -> Result < NonNull < [ u8 ] > , AllocError > {
90+ debug_assert ! (
91+ new_layout. size( ) >= old_layout. size( ) ,
92+ "`new_layout.size()` must be greater than or equal to `old_layout.size()`"
93+ ) ;
94+ #[ allow( clippy:: manual_inspect) ]
95+ self . resize ( ptr, old_layout, new_layout) . map ( |new_ptr| {
96+ unsafe {
97+ new_ptr
98+ . cast :: < u8 > ( )
99+ . byte_add ( old_layout. size ( ) )
100+ . write_bytes ( 0 , new_layout. size ( ) - old_layout. size ( ) )
101+ } ;
102+ new_ptr
103+ } )
104+ }
105+
106+ unsafe fn shrink (
107+ & self ,
108+ ptr : NonNull < u8 > ,
109+ old_layout : Layout ,
110+ new_layout : Layout ,
111+ ) -> Result < NonNull < [ u8 ] > , AllocError > {
112+ debug_assert ! (
113+ new_layout. size( ) <= old_layout. size( ) ,
114+ "`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
115+ ) ;
116+ self . resize ( ptr, old_layout, new_layout)
117+ }
70118}
71119
72120impl AsRef < ngx_pool_t > for Pool {
@@ -229,6 +277,39 @@ impl Pool {
229277 p
230278 }
231279 }
280+
281+ /// Resizes a memory allocation in place if possible.
282+ ///
283+ /// If resizing is requested for the last allocation in the pool, it may be
284+ /// possible to adjust pool data and avoid any real allocations.
285+ ///
286+ /// # Safety
287+ /// `ptr` must point to allocated address and `old_layout` must match the current layout
288+ /// of the allocation.
289+ #[ inline( always) ]
290+ unsafe fn resize (
291+ & self ,
292+ ptr : NonNull < u8 > ,
293+ old_layout : Layout ,
294+ new_layout : Layout ,
295+ ) -> Result < NonNull < [ u8 ] > , AllocError > {
296+ if ptr. byte_add ( old_layout. size ( ) ) . as_ptr ( ) == self . as_ref ( ) . d . last
297+ && ptr. byte_add ( new_layout. size ( ) ) . as_ptr ( ) <= self . as_ref ( ) . d . end
298+ && ptr. align_offset ( new_layout. align ( ) ) == 0
299+ {
300+ let pool = self . 0 . as_ptr ( ) ;
301+ unsafe { ( * pool) . d . last = ptr. byte_add ( new_layout. size ( ) ) . as_ptr ( ) } ;
302+ Ok ( NonNull :: slice_from_raw_parts ( ptr, new_layout. size ( ) ) )
303+ } else {
304+ let size = core:: cmp:: min ( old_layout. size ( ) , new_layout. size ( ) ) ;
305+ let new_ptr = <Self as Allocator >:: allocate ( self , new_layout) ?;
306+ unsafe {
307+ ptr. copy_to_nonoverlapping ( new_ptr. cast ( ) , size) ;
308+ self . deallocate ( ptr, old_layout) ;
309+ }
310+ Ok ( new_ptr)
311+ }
312+ }
232313}
233314
234315/// Cleanup handler for a specific type `T`.
0 commit comments