@@ -37,14 +37,17 @@ const _: () = {
37
37
38
38
impl Region < Borrowed > {
39
39
pub fn from_slice ( slice : & [ u8 ] ) -> Self {
40
+ // SAFETY: A slice upholds all the safety variants we need to construct a borrowed Region
40
41
unsafe { Self :: from_parts ( slice. as_ptr ( ) , slice. len ( ) , slice. len ( ) ) }
41
42
}
42
43
}
43
44
44
45
impl Region < Owned > {
45
46
/// Construct a region from an existing vector
46
47
pub fn from_vec ( vec : Vec < u8 > ) -> Self {
48
+ // SAFETY: The `std::vec::Vec` type upholds all the safety invariants required to call `from_parts`
47
49
let region = unsafe { Self :: from_parts ( vec. as_ptr ( ) , vec. capacity ( ) , vec. len ( ) ) } ;
50
+ // Important and load bearing: call `mem::forget` to prevent memory from being freed
48
51
mem:: forget ( vec) ;
49
52
region
50
53
}
@@ -72,6 +75,7 @@ impl Region<Owned> {
72
75
73
76
/// Transform the region into a vector
74
77
pub fn into_vec ( self ) -> Vec < u8 > {
78
+ // SAFETY: Invariants are covered by the safety contract of the constructor
75
79
let vector = unsafe {
76
80
Vec :: from_raw_parts (
77
81
self . offset as * mut u8 ,
@@ -88,6 +92,14 @@ impl<O> Region<O>
88
92
where
89
93
O : Ownership ,
90
94
{
95
+ /// # Safety
96
+ ///
97
+ /// This function requires the following invariants to be upheld:
98
+ /// - `capacity` is smaller or equal to `length`
99
+ /// - The number of bytes allocated by the pointer must be equal to `capacity`
100
+ /// - The byte range covered by `length` must be initialized
101
+ /// - `ptr` is a non-dangling and non-null pointer
102
+ /// - If the generic `Ownership` parameter is set to `Owned`, the `ptr` must point to a memory region allocated by a `Vec`
91
103
unsafe fn from_parts ( ptr : * const u8 , capacity : usize , length : usize ) -> Self {
92
104
// Well, this technically violates pointer provenance rules.
93
105
// But there isn't a stable API for it, so that's the best we can do, I guess.
@@ -102,6 +114,7 @@ where
102
114
103
115
/// Access the memory region this region points to in form of a byte slice
104
116
pub fn as_bytes ( & self ) -> & [ u8 ] {
117
+ // SAFETY: Safety contract of constructor requires `length` bytes to be initialized
105
118
unsafe { slice:: from_raw_parts ( self . offset as * const u8 , self . length as usize ) }
106
119
}
107
120
@@ -146,6 +159,8 @@ where
146
159
// "The pointer will never be null, so this type is null-pointer-optimized."
147
160
assert ! ( !region_start. is_null( ) , "Region starts at null pointer" ) ;
148
161
162
+ // SAFETY: Since `from_parts` was required to uphold the invariance that if the parameter is `Owned`
163
+ // the memory has been allocated through a `Vec`, we can safely reconstruct the `Vec` and deallocate it.
149
164
unsafe {
150
165
let data =
151
166
Vec :: from_raw_parts ( region_start, self . length as usize , self . capacity as usize ) ;
0 commit comments