11//! Buffer management for same-process client<->server communication.
22
3+ use std:: alloc:: { self , Layout } ;
34use std:: io:: { self , Write } ;
4- use std:: mem:: { self , ManuallyDrop } ;
55use std:: ops:: { Deref , DerefMut } ;
6- use std:: slice;
6+ use std:: ptr:: null_mut;
7+ use std:: { mem, slice} ;
78
89#[ repr( C ) ]
910pub struct Buffer {
1011 data : * mut u8 ,
1112 len : usize ,
1213 capacity : usize ,
13- reserve : extern "C" fn ( Buffer , usize ) -> Buffer ,
14- drop : extern "C" fn ( Buffer ) ,
1514}
1615
1716unsafe impl Sync for Buffer { }
@@ -20,7 +19,7 @@ unsafe impl Send for Buffer {}
2019impl Default for Buffer {
2120 #[ inline]
2221 fn default ( ) -> Self {
23- Self :: from ( vec ! [ ] )
22+ Self { data : null_mut ( ) , len : 0 , capacity : 0 }
2423 }
2524}
2625
@@ -62,8 +61,7 @@ impl Buffer {
6261 #[ inline]
6362 pub ( super ) fn extend_from_array < const N : usize > ( & mut self , xs : & [ u8 ; N ] ) {
6463 if xs. len ( ) > ( self . capacity - self . len ) {
65- let b = self . take ( ) ;
66- * self = ( b. reserve ) ( b, xs. len ( ) ) ;
64+ self . reserve ( xs. len ( ) ) ;
6765 }
6866 unsafe {
6967 xs. as_ptr ( ) . copy_to_nonoverlapping ( self . data . add ( self . len ) , xs. len ( ) ) ;
@@ -74,8 +72,7 @@ impl Buffer {
7472 #[ inline]
7573 pub ( super ) fn extend_from_slice ( & mut self , xs : & [ u8 ] ) {
7674 if xs. len ( ) > ( self . capacity - self . len ) {
77- let b = self . take ( ) ;
78- * self = ( b. reserve ) ( b, xs. len ( ) ) ;
75+ self . reserve ( xs. len ( ) ) ;
7976 }
8077 unsafe {
8178 xs. as_ptr ( ) . copy_to_nonoverlapping ( self . data . add ( self . len ) , xs. len ( ) ) ;
@@ -89,14 +86,34 @@ impl Buffer {
8986 // will panic if we're exceeding isize::MAX bytes and so there's no need
9087 // to check for overflow.
9188 if self . len == self . capacity {
92- let b = self . take ( ) ;
93- * self = ( b. reserve ) ( b, 1 ) ;
89+ self . reserve ( 1 ) ;
9490 }
9591 unsafe {
9692 * self . data . add ( self . len ) = v;
9793 self . len += 1 ;
9894 }
9995 }
96+
97+ #[ inline]
98+ fn layout ( & self ) -> Layout {
99+ Layout :: array :: < u8 > ( self . capacity ) . unwrap ( )
100+ }
101+
102+ #[ inline( never) ]
103+ fn reserve ( & mut self , amount : usize ) {
104+ debug_assert ! ( amount > 0 ) ;
105+ self . capacity += amount;
106+ assert ! ( self . capacity < isize :: MAX as usize ) ;
107+ let layout = self . layout ( ) ;
108+ self . data = if self . data . is_null ( ) {
109+ unsafe { alloc:: alloc ( layout) }
110+ } else {
111+ unsafe { alloc:: realloc ( self . data , layout, self . capacity ) }
112+ } ;
113+ if self . data . is_null ( ) {
114+ alloc:: handle_alloc_error ( layout) ;
115+ }
116+ }
100117}
101118
102119impl Write for Buffer {
@@ -121,35 +138,10 @@ impl Write for Buffer {
121138impl Drop for Buffer {
122139 #[ inline]
123140 fn drop ( & mut self ) {
124- let b = self . take ( ) ;
125- ( b. drop ) ( b) ;
126- }
127- }
128-
129- impl From < Vec < u8 > > for Buffer {
130- fn from ( v : Vec < u8 > ) -> Self {
131- let mut v = ManuallyDrop :: new ( v) ;
132- let ( data, len, capacity) = ( v. as_mut_ptr ( ) , v. len ( ) , v. capacity ( ) ) ;
133-
134- // This utility function is nested in here because it can *only*
135- // be safely called on `Buffer`s created by *this* `proc_macro`.
136- fn to_vec ( b : Buffer ) -> Vec < u8 > {
141+ if !self . data . is_null ( ) {
137142 unsafe {
138- let b = ManuallyDrop :: new ( b) ;
139- Vec :: from_raw_parts ( b. data , b. len , b. capacity )
143+ alloc:: dealloc ( self . data , self . layout ( ) ) ;
140144 }
141145 }
142-
143- extern "C" fn reserve ( b : Buffer , additional : usize ) -> Buffer {
144- let mut v = to_vec ( b) ;
145- v. reserve ( additional) ;
146- Buffer :: from ( v)
147- }
148-
149- extern "C" fn drop ( b : Buffer ) {
150- mem:: drop ( to_vec ( b) ) ;
151- }
152-
153- Buffer { data, len, capacity, reserve, drop }
154146 }
155147}
0 commit comments