safe_transmute/
align.rs

1//! Alignment checking primitives.
2
3
4use core::mem::{align_of, size_of};
5use self::super::error::UnalignedError;
6
7
8fn validate_alignment<S, T>(data: &[S]) -> Result<(), usize> {
9    // TODO this could probably become more efficient once `ptr::align_offset`
10    // is stabilized (#44488)
11    let ptr = data.as_ptr();
12    let offset = ptr as usize % align_of::<T>();
13    if offset > 0 {
14        // reverse the offset (from "bytes to insert" to "bytes to remove")
15        Err(size_of::<T>() - offset)
16    } else {
17        Ok(())
18    }
19}
20
21
22/// Check whether the given data slice of `S`s is properly aligned for reading
23/// and writing as a slice of `T`s.
24///
25/// # Errors
26///
27/// An `Error::Unaligned` error is returned with the number of bytes to discard
28/// from the front in order to make the conversion safe from alignment concerns.
29pub fn check_alignment<S, T>(data: &[S]) -> Result<(), UnalignedError<S, T>> {
30    validate_alignment::<_, T>(data).map_err(move |off| UnalignedError::new(off, data))
31}
32
33/// Check whether the given mutable data slice of `S`s is properly aligned for
34/// reading and writing as a slice of `T`s, returning the same slice back if
35/// it is.
36///
37/// # Errors
38///
39/// An `Error::Unaligned` error is returned with the number of bytes to discard
40/// from the front in order to make the conversion safe from alignment concerns.
41pub fn check_alignment_mut<S, T>(data: &mut [S]) -> Result<&mut [S], UnalignedError<S, T>> {
42    match validate_alignment::<_, T>(data) {
43        Ok(()) => Ok(data),
44        Err(off) => Err(UnalignedError::new(off, data)),
45    }
46}