Skip to content

Commit 03dd51c

Browse files
committed
Document some unsafe blocks
Makes progress on #61
1 parent 1209946 commit 03dd51c

File tree

1 file changed

+51
-18
lines changed

1 file changed

+51
-18
lines changed

src/lib.rs

+51-18
Original file line numberDiff line numberDiff line change
@@ -568,15 +568,33 @@ pub unsafe trait AsBytes {
568568
/// `as_bytes` provides access to the bytes of this value as an immutable
569569
/// byte slice.
570570
fn as_bytes(&self) -> &[u8] {
571-
// TODO(#61): Add a "SAFETY" comment and remove this `allow`.
572-
#[allow(clippy::undocumented_unsafe_blocks)]
573-
unsafe {
574-
// Note that this method does not have a `Self: Sized` bound;
575-
// `size_of_val` works for unsized values too.
576-
let len = mem::size_of_val(self);
577-
let slf: *const Self = self;
578-
slice::from_raw_parts(slf.cast::<u8>(), len)
579-
}
571+
// Note that this method does not have a `Self: Sized` bound;
572+
// `size_of_val` works for unsized values too.
573+
let len = mem::size_of_val(self);
574+
let slf: *const Self = self;
575+
576+
// SAFETY:
577+
// - `slf.cast::<u8>()` is valid for reads for `len *
578+
// mem::size_of::<u8>()` many bytes because...
579+
// - `slf` is the same pointer as `self`, and `self` is a reference
580+
// which points to an object whose size is `len`. Thus...
581+
// - The entire region of `len` bytes starting at `slf` is contained
582+
// within a single allocation.
583+
// - `slf` is non-null.
584+
// - `slf` is trivially aligned to `align_of::<u8>() == 1`.
585+
// - `Self: AsBytes` ensures that all of the bytes of `slf` are
586+
// initialized.
587+
// - Since `slf` is derived from `self`, and `self` is an immutable
588+
// reference, the only other references to this memory region that
589+
// could exist are other immutable references, and those don't allow
590+
// mutation.
591+
//
592+
// TODO(#8): Update `AsRef` docs to require that `Self` doesn't allow
593+
// interior mutability so that this bullet point is actually true.
594+
// - The total size of the resulting slice is no larger than
595+
// `isize::MAX` because no allocation produced by safe code can be
596+
// larger than `isize::MAX`.
597+
unsafe { slice::from_raw_parts(slf.cast::<u8>(), len) }
580598
}
581599

582600
/// Gets the bytes of this value mutably.
@@ -587,15 +605,30 @@ pub unsafe trait AsBytes {
587605
where
588606
Self: FromBytes,
589607
{
590-
// TODO(#61): Add a "SAFETY" comment and remove this `allow`.
591-
#[allow(clippy::undocumented_unsafe_blocks)]
592-
unsafe {
593-
// Note that this method does not have a `Self: Sized` bound;
594-
// `size_of_val` works for unsized values too.
595-
let len = mem::size_of_val(self);
596-
let slf: *mut Self = self;
597-
slice::from_raw_parts_mut(slf.cast::<u8>(), len)
598-
}
608+
// Note that this method does not have a `Self: Sized` bound;
609+
// `size_of_val` works for unsized values too.
610+
let len = mem::size_of_val(self);
611+
let slf: *mut Self = self;
612+
613+
// SAFETY:
614+
// - `slf.cast::<u8>()` is valid for reads and writes for `len *
615+
// mem::size_of::<u8>()` many bytes because...
616+
// - `slf` is the same pointer as `self`, and `self` is a reference
617+
// which points to an object whose size is `len`. Thus...
618+
// - The entire region of `len` bytes starting at `slf` is contained
619+
// within a single allocation.
620+
// - `slf` is non-null.
621+
// - `slf` is trivially aligned to `align_of::<u8>() == 1`.
622+
// - `Self: AsBytes` ensures that all of the bytes of `slf` are
623+
// initialized.
624+
// - `Self: FromBytes` ensures that no write to this memory region
625+
// could result in it containing an invalid `Self`.
626+
// - Since `slf` is derived from `self`, and `self` is a mutable
627+
// reference, no other references to this memory region can exist.
628+
// - The total size of the resulting slice is no larger than
629+
// `isize::MAX` because no allocation produced by safe code can be
630+
// larger than `isize::MAX`.
631+
unsafe { slice::from_raw_parts_mut(slf.cast::<u8>(), len) }
599632
}
600633

601634
/// Writes a copy of `self` to `bytes`.

0 commit comments

Comments
 (0)