Skip to content

Commit

Permalink
Add functions for writing zeroed bytes to &mut impl Zeroable and `&…
Browse files Browse the repository at this point in the history
…mut [impl Zeroable]` (#193)

* Add functions for writing zeroed bytes to `&mut impl Zeroable` and `&mut [impl Zeroable]`

* Support `T: !Copy` in `fill_zero`/`write_zero`

* Zero bytes in the drop guard for write_zero

* Update src/lib.rs

Co-authored-by: Alphyr <47725341+a1phyr@users.noreply.github.com>

---------

Co-authored-by: Lokathor <zefria@gmail.com>
Co-authored-by: Alphyr <47725341+a1phyr@users.noreply.github.com>
  • Loading branch information
3 people committed Sep 5, 2023
1 parent 3c1a0d9 commit d790c04
Showing 1 changed file with 44 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/lib.rs
Expand Up @@ -408,3 +408,47 @@ pub fn try_cast_slice_mut<
) -> Result<&mut [B], PodCastError> {
unsafe { internal::try_cast_slice_mut(a) }
}

/// Fill all bytes of `target` with zeroes (see [`Zeroable`]).
///
/// This is similar to `*target = Zeroable::zeroed()`, but guarantees that any
/// padding bytes in `target` are zeroed as well.
///
/// See also [`fill_zero`], if you have a slice rather than a single value.
#[inline]
pub fn write_zero<T: Zeroable>(target: &mut T) {
struct EnsureZeroWrite<T>(*mut T);
impl<T> Drop for EnsureZeroWrite<T> {
#[inline(always)]
fn drop(&mut self) {
unsafe {
core::ptr::write_bytes(self.0, 0u8, 1);
}
}
}
unsafe {
let guard = EnsureZeroWrite(target);
core::ptr::drop_in_place(guard.0);
drop(guard);
}
}

/// Fill all bytes of `slice` with zeroes (see [`Zeroable`]).
///
/// This is similar to `slice.fill(Zeroable::zeroed())`, but guarantees that any
/// padding bytes in `slice` are zeroed as well.
///
/// See also [`write_zero`], which zeroes all bytes of a single value rather
/// than a slice.
#[inline]
pub fn fill_zero<T: Zeroable>(slice: &mut [T]) {
if core::mem::needs_drop::<T>() {
// If `T` needs to be dropped then we have to do this one item at a time, in
// case one of the intermediate drops does a panic.
slice.iter_mut().for_each(write_zero);
} else {
// Otherwise we can be really fast and just fill everthing with zeros.
let len = core::mem::size_of_val::<[T]>(slice);
unsafe { core::ptr::write_bytes(slice.as_mut_ptr() as *mut u8, 0u8, len) }
}
}

0 comments on commit d790c04

Please sign in to comment.