@@ -34,12 +34,7 @@ pub fn alloc(size: usize) -> *mut Region {
3434/// a pointer to the Region (preventing the memory from being freed until explicitly called later).
3535///
3636/// The resulting Region has capacity = length, the buffer capacity is shrunk down to its length.
37- pub fn release_buffer ( mut buffer : Vec < u8 > ) -> * mut Region {
38- // Shrinking the buffer down to the length is important to uphold a safety invariant by the `dealloc` method.
39- // Passing in a differing size into the `dealloc` layout is considered undefined behaviour.
40- //
41- // See: <https://doc.rust-lang.org/stable/alloc/alloc/trait.GlobalAlloc.html#safety-2>
42- buffer. shrink_to_fit ( ) ;
37+ pub fn release_buffer ( buffer : Vec < u8 > ) -> * mut Region {
4338 let region = build_region ( & buffer) ;
4439 mem:: forget ( buffer) ;
4540 Box :: into_raw ( region)
@@ -74,16 +69,59 @@ pub unsafe fn consume_region(ptr: *mut Region) -> Vec<u8> {
7469 )
7570}
7671
72+ /// Element that can be used to construct a new `Box<Region>`
73+ ///
74+ /// # Safety
75+ ///
76+ /// The following invariant must be upheld:
77+ ///
78+ /// - full allocated capacity == value returned by capacity
79+ ///
80+ /// This is important to uphold the safety invariant of the `dealloc` method, which requires us to pass the same Layout
81+ /// into it as was used to allocate a memory region.
82+ ///
83+ /// And since `size` is one of the parameters, it is important to pass in the exact same capacity.
84+ ///
85+ /// See: <https://doc.rust-lang.org/stable/alloc/alloc/trait.GlobalAlloc.html#safety-2>
86+ pub unsafe trait RegionSource : AsRef < [ u8 ] > {
87+ fn capacity ( & self ) -> usize ;
88+ }
89+
90+ unsafe impl RegionSource for & [ u8 ] {
91+ fn capacity ( & self ) -> usize {
92+ self . len ( )
93+ }
94+ }
95+
96+ unsafe impl RegionSource for Vec < u8 > {
97+ fn capacity ( & self ) -> usize {
98+ self . capacity ( )
99+ }
100+ }
101+
102+ unsafe impl < T : ?Sized > RegionSource for & T
103+ where
104+ T : RegionSource ,
105+ {
106+ fn capacity ( & self ) -> usize {
107+ ( * * self ) . capacity ( )
108+ }
109+ }
110+
77111/// Returns a box of a Region, which can be sent over a call to extern
78112/// note that this DOES NOT take ownership of the data, and we MUST NOT consume_region
79113/// the resulting data.
80114/// The Box must be dropped (with scope), but not the data
81- pub fn build_region ( data : & [ u8 ] ) -> Box < Region > {
82- let data_ptr = data. as_ptr ( ) as usize ;
115+ pub fn build_region < S > ( data : S ) -> Box < Region >
116+ where
117+ S : RegionSource ,
118+ {
119+ let data_slice = data. as_ref ( ) ;
120+ let data_ptr = data_slice. as_ptr ( ) as usize ;
83121 build_region_from_components (
84122 u32:: try_from ( data_ptr) . expect ( "pointer doesn't fit in u32" ) ,
85- u32:: try_from ( data. len ( ) ) . expect ( "length doesn't fit in u32" ) ,
86- u32:: try_from ( data . len ( ) ) . expect ( "length doesn't fit in u32" ) ,
123+ u32:: try_from ( data. capacity ( ) ) . expect ( "capacity doesn't fit in u32" ) ,
124+ u32:: try_from ( data_slice . len ( ) ) . expect ( "length doesn't fit in u32" ) ,
87125 )
88126}
89127
0 commit comments