@@ -34,12 +34,7 @@ pub fn alloc(size: usize) -> *mut Region {
34
34
/// a pointer to the Region (preventing the memory from being freed until explicitly called later).
35
35
///
36
36
/// 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 {
43
38
let region = build_region ( & buffer) ;
44
39
mem:: forget ( buffer) ;
45
40
Box :: into_raw ( region)
@@ -74,16 +69,59 @@ pub unsafe fn consume_region(ptr: *mut Region) -> Vec<u8> {
74
69
)
75
70
}
76
71
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
+
77
111
/// Returns a box of a Region, which can be sent over a call to extern
78
112
/// note that this DOES NOT take ownership of the data, and we MUST NOT consume_region
79
113
/// the resulting data.
80
114
/// 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 ;
83
121
build_region_from_components (
84
122
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" ) ,
87
125
)
88
126
}
89
127
0 commit comments