Skip to content

Commit 81c2646

Browse files
authored
Document some unsafe blocks (#227)
Makes progress on #61
1 parent 9f35f36 commit 81c2646

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

590608
/// Gets the bytes of this value mutably.
@@ -595,15 +613,30 @@ pub unsafe trait AsBytes {
595613
where
596614
Self: FromBytes,
597615
{
598-
// TODO(#61): Add a "SAFETY" comment and remove this `allow`.
599-
#[allow(clippy::undocumented_unsafe_blocks)]
600-
unsafe {
601-
// Note that this method does not have a `Self: Sized` bound;
602-
// `size_of_val` works for unsized values too.
603-
let len = mem::size_of_val(self);
604-
let slf: *mut Self = self;
605-
slice::from_raw_parts_mut(slf.cast::<u8>(), len)
606-
}
616+
// Note that this method does not have a `Self: Sized` bound;
617+
// `size_of_val` works for unsized values too.
618+
let len = mem::size_of_val(self);
619+
let slf: *mut Self = self;
620+
621+
// SAFETY:
622+
// - `slf.cast::<u8>()` is valid for reads and writes for `len *
623+
// mem::size_of::<u8>()` many bytes because...
624+
// - `slf` is the same pointer as `self`, and `self` is a reference
625+
// which points to an object whose size is `len`. Thus...
626+
// - The entire region of `len` bytes starting at `slf` is contained
627+
// within a single allocation.
628+
// - `slf` is non-null.
629+
// - `slf` is trivially aligned to `align_of::<u8>() == 1`.
630+
// - `Self: AsBytes` ensures that all of the bytes of `slf` are
631+
// initialized.
632+
// - `Self: FromBytes` ensures that no write to this memory region
633+
// could result in it containing an invalid `Self`.
634+
// - Since `slf` is derived from `self`, and `self` is a mutable
635+
// reference, no other references to this memory region can exist.
636+
// - The total size of the resulting slice is no larger than
637+
// `isize::MAX` because no allocation produced by safe code can be
638+
// larger than `isize::MAX`.
639+
unsafe { slice::from_raw_parts_mut(slf.cast::<u8>(), len) }
607640
}
608641

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

0 commit comments

Comments
 (0)