Skip to content

Commit fc7919a

Browse files
authored
Document some unsafe blocks (#227) (#237)
Makes progress on #61
1 parent 311a2b0 commit fc7919a

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
@@ -467,15 +467,33 @@ pub unsafe trait AsBytes {
467467
/// `as_bytes` provides access to the bytes of this value as an immutable
468468
/// byte slice.
469469
fn as_bytes(&self) -> &[u8] {
470-
// TODO(#61): Add a "SAFETY" comment and remove this `allow`.
471-
#[allow(clippy::undocumented_unsafe_blocks)]
472-
unsafe {
473-
// Note that this method does not have a `Self: Sized` bound;
474-
// `size_of_val` works for unsized values too.
475-
let len = mem::size_of_val(self);
476-
let slf: *const Self = self;
477-
slice::from_raw_parts(slf.cast::<u8>(), len)
478-
}
470+
// Note that this method does not have a `Self: Sized` bound;
471+
// `size_of_val` works for unsized values too.
472+
let len = mem::size_of_val(self);
473+
let slf: *const Self = self;
474+
475+
// SAFETY:
476+
// - `slf.cast::<u8>()` is valid for reads for `len *
477+
// mem::size_of::<u8>()` many bytes because...
478+
// - `slf` is the same pointer as `self`, and `self` is a reference
479+
// which points to an object whose size is `len`. Thus...
480+
// - The entire region of `len` bytes starting at `slf` is contained
481+
// within a single allocation.
482+
// - `slf` is non-null.
483+
// - `slf` is trivially aligned to `align_of::<u8>() == 1`.
484+
// - `Self: AsBytes` ensures that all of the bytes of `slf` are
485+
// initialized.
486+
// - Since `slf` is derived from `self`, and `self` is an immutable
487+
// reference, the only other references to this memory region that
488+
// could exist are other immutable references, and those don't allow
489+
// mutation.
490+
//
491+
// TODO(#8): Update `AsRef` docs to require that `Self` doesn't allow
492+
// interior mutability so that this bullet point is actually true.
493+
// - The total size of the resulting slice is no larger than
494+
// `isize::MAX` because no allocation produced by safe code can be
495+
// larger than `isize::MAX`.
496+
unsafe { slice::from_raw_parts(slf.cast::<u8>(), len) }
479497
}
480498

481499
/// Gets the bytes of this value mutably.
@@ -486,15 +504,30 @@ pub unsafe trait AsBytes {
486504
where
487505
Self: FromBytes,
488506
{
489-
// TODO(#61): Add a "SAFETY" comment and remove this `allow`.
490-
#[allow(clippy::undocumented_unsafe_blocks)]
491-
unsafe {
492-
// Note that this method does not have a `Self: Sized` bound;
493-
// `size_of_val` works for unsized values too.
494-
let len = mem::size_of_val(self);
495-
let slf: *mut Self = self;
496-
slice::from_raw_parts_mut(slf.cast::<u8>(), len)
497-
}
507+
// Note that this method does not have a `Self: Sized` bound;
508+
// `size_of_val` works for unsized values too.
509+
let len = mem::size_of_val(self);
510+
let slf: *mut Self = self;
511+
512+
// SAFETY:
513+
// - `slf.cast::<u8>()` is valid for reads and writes for `len *
514+
// mem::size_of::<u8>()` many bytes because...
515+
// - `slf` is the same pointer as `self`, and `self` is a reference
516+
// which points to an object whose size is `len`. Thus...
517+
// - The entire region of `len` bytes starting at `slf` is contained
518+
// within a single allocation.
519+
// - `slf` is non-null.
520+
// - `slf` is trivially aligned to `align_of::<u8>() == 1`.
521+
// - `Self: AsBytes` ensures that all of the bytes of `slf` are
522+
// initialized.
523+
// - `Self: FromBytes` ensures that no write to this memory region
524+
// could result in it containing an invalid `Self`.
525+
// - Since `slf` is derived from `self`, and `self` is a mutable
526+
// reference, no other references to this memory region can exist.
527+
// - The total size of the resulting slice is no larger than
528+
// `isize::MAX` because no allocation produced by safe code can be
529+
// larger than `isize::MAX`.
530+
unsafe { slice::from_raw_parts_mut(slf.cast::<u8>(), len) }
498531
}
499532

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

0 commit comments

Comments
 (0)