@@ -34,7 +34,7 @@ use std::ptr::copy;
3434use std:: ptr:: { read_volatile, write_volatile} ;
3535use std:: result;
3636use std:: sync:: atomic:: Ordering ;
37- use zerocopy:: { FromBytes , FromZeros , IntoBytes } ;
37+ use zerocopy:: { CastError , FromBytes , FromZeros , Immutable , IntoBytes , KnownLayout } ;
3838
3939use crate :: atomic_integer:: AtomicInteger ;
4040use crate :: bitmap:: { Bitmap , BitmapSlice , BS } ;
@@ -206,27 +206,36 @@ pub trait VolatileMemory {
206206 ///
207207 /// If the resulting pointer is not aligned, this method will return an
208208 /// [`Error`](enum.Error.html).
209- unsafe fn aligned_as_ref < T : Copy + Send + Sync + FromBytes + IntoBytes + FromZeros > (
209+ unsafe fn aligned_as_ref <
210+ T : Copy + Send + Sync + FromBytes + IntoBytes + FromZeros + Immutable + KnownLayout ,
211+ > (
210212 & self ,
211213 offset : usize ,
212214 ) -> Result < & T > {
213215 let slice = self . get_slice ( offset, size_of :: < T > ( ) ) ?;
214- slice. check_alignment ( align_of :: < T > ( ) ) ?;
215-
216- assert_eq ! (
217- slice. len( ) ,
218- size_of:: <T >( ) ,
219- "VolatileMemory::get_slice(offset, count) returned slice of length != count."
220- ) ;
221216
222- // SAFETY: This is safe because the invariants of the constructors of VolatileSlice ensure that
223- // slice.addr is valid memory of size slice.len(). The assert above ensures that
224- // the length of the slice is exactly enough to hold one `T`.
225- // Dereferencing the pointer is safe because we check the alignment above, and the invariants
226- // of this function ensure that no aliasing pointers exist. Lastly, the lifetime of the
227- // returned VolatileArrayRef match that of the VolatileSlice returned by get_slice and thus the
228- // lifetime one `self`.
229- unsafe { Ok ( & * ( slice. addr as * const T ) ) }
217+ let slice_addr = slice. addr ;
218+ let size_of_t = size_of :: < T > ( ) ;
219+
220+ // SAFETY: Creating a byte slice from the pointer is safe because the invariants of the
221+ // constructors of VolatileSlice ensure that slice.addr is valid memory of size slice.len()
222+ // and the invariants of this function ensure that no aliasing reference exists.
223+ // Lastly, the lifetime of the returned reference matches that of the VolatileSlice returned
224+ // by get_slice and thus the lifetime one `self`.
225+ let rust_slice = unsafe { core:: slice:: from_raw_parts ( slice_addr, size_of_t) } ;
226+ T :: ref_from_bytes ( rust_slice) . map_err ( |error| match error {
227+ CastError :: < _ , T > :: Alignment ( _) => Error :: Misaligned {
228+ addr : slice. addr . addr ( ) ,
229+ alignment : align_of :: < T > ( ) ,
230+ } ,
231+ CastError :: < _ , T > :: Size ( size) => {
232+ panic ! ( "VolatileMemory::get_slice({}, count) returned slice of length != count, expected: \" {}\" actual: \" {}\" ." , offset, size_of:: <T >( ) , size. into_src( ) . len( ) ) ;
233+ }
234+ CastError :: < _ , T > :: Validity ( infallible) => {
235+ // Ensures this error is actually infallible.
236+ match infallible { }
237+ }
238+ } )
230239 }
231240
232241 /// Returns a mutable reference to an instance of `T` at `offset`. Mutable accesses performed
@@ -245,28 +254,36 @@ pub trait VolatileMemory {
245254 // the function is unsafe, and the conversion is safe if following the safety
246255 // instrutions above
247256 #[ allow( clippy:: mut_from_ref) ]
248- unsafe fn aligned_as_mut < T : Copy + Send + Sync + FromBytes + IntoBytes + FromZeros > (
257+ unsafe fn aligned_as_mut <
258+ T : Copy + Send + Sync + FromBytes + IntoBytes + FromZeros + KnownLayout ,
259+ > (
249260 & self ,
250261 offset : usize ,
251262 ) -> Result < & mut T > {
252263 let slice = self . get_slice ( offset, size_of :: < T > ( ) ) ?;
253- slice. check_alignment ( align_of :: < T > ( ) ) ?;
254-
255- assert_eq ! (
256- slice. len( ) ,
257- size_of:: <T >( ) ,
258- "VolatileMemory::get_slice(offset, count) returned slice of length != count."
259- ) ;
260-
261- // SAFETY: This is safe because the invariants of the constructors of VolatileSlice ensure that
262- // slice.addr is valid memory of size slice.len(). The assert above ensures that
263- // the length of the slice is exactly enough to hold one `T`.
264- // Dereferencing the pointer is safe because we check the alignment above, and the invariants
265- // of this function ensure that no aliasing pointers exist. Lastly, the lifetime of the
266- // returned VolatileArrayRef match that of the VolatileSlice returned by get_slice and thus the
267- // lifetime one `self`.
268264
269- unsafe { Ok ( & mut * ( slice. addr as * mut T ) ) }
265+ let slice_addr = slice. addr ;
266+ let size_of_t = size_of :: < T > ( ) ;
267+
268+ // SAFETY: Creating a mutable byte slice from the pointer is safe because the invariants of the
269+ // constructors of VolatileSlice ensure that slice.addr is valid memory of size slice.len()
270+ // and the invariants of this function ensure that no aliasing reference exists.
271+ // Lastly, the lifetime of the returned reference matches that of the VolatileSlice returned
272+ // by get_slice and thus the lifetime one `self`.
273+ let rust_slice = unsafe { core:: slice:: from_raw_parts_mut ( slice_addr, size_of_t) } ;
274+ T :: mut_from_bytes ( rust_slice) . map_err ( |error| match error {
275+ CastError :: < _ , T > :: Alignment ( _) => Error :: Misaligned {
276+ addr : slice. addr . addr ( ) ,
277+ alignment : align_of :: < T > ( ) ,
278+ } ,
279+ CastError :: < _ , T > :: Size ( size) => {
280+ panic ! ( "VolatileMemory::get_slice({}, count) returned slice of length != count, expected: \" {}\" actual: \" {}\" ." , offset, size_of:: <T >( ) , size. into_src( ) . len( ) ) ;
281+ }
282+ CastError :: < _ , T > :: Validity ( infallible) => {
283+ // Ensures this error is actually infallible.
284+ match infallible { }
285+ }
286+ } )
270287 }
271288
272289 /// Returns a reference to an instance of `T` at `offset`. Mutable accesses performed
0 commit comments