Skip to content

Commit 35043ae

Browse files
committed
FromZeros boxed slice method supports slice DSTs
Makes progress on #29
1 parent 02dc876 commit 35043ae

File tree

2 files changed

+23
-18
lines changed

2 files changed

+23
-18
lines changed

src/error.rs

+4
Original file line numberDiff line numberDiff line change
@@ -570,6 +570,10 @@ impl<Src, Dst: ?Sized + TryFromBytes> TryReadError<Src, Dst> {
570570
}
571571
}
572572

573+
/// The error type of a failed allocation.
574+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
575+
pub struct AllocError;
576+
573577
#[cfg(test)]
574578
mod tests {
575579
use super::*;

src/lib.rs

+19-18
Original file line numberDiff line numberDiff line change
@@ -2189,14 +2189,16 @@ pub unsafe trait FromZeros: TryFromBytes {
21892189
#[cfg(feature = "alloc")]
21902190
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
21912191
#[inline]
2192-
fn new_box_slice_zeroed(len: usize) -> Box<[Self]>
2192+
fn new_box_zeroed_with_elems(count: usize) -> Option<Box<Self>>
21932193
where
2194-
Self: Sized,
2194+
Self: KnownLayout<PointerMetadata = usize>,
21952195
{
2196-
let size = mem::size_of::<Self>()
2197-
.checked_mul(len)
2198-
.expect("mem::size_of::<Self>() * len overflows `usize`");
2199-
let align = mem::align_of::<Self>();
2196+
let size = match count.size_for_metadata(Self::LAYOUT) {
2197+
Some(size) => size,
2198+
None => return None,
2199+
};
2200+
2201+
let align = Self::LAYOUT.align.get();
22002202
// On stable Rust versions <= 1.64.0, `Layout::from_size_align` has a
22012203
// bug in which sufficiently-large allocations (those which, when
22022204
// rounded up to the alignment, overflow `isize`) are not rejected,
@@ -2208,29 +2210,28 @@ pub unsafe trait FromZeros: TryFromBytes {
22082210
assert!(size <= max_alloc);
22092211
// TODO(https://github.com/rust-lang/rust/issues/55724): Use
22102212
// `Layout::repeat` once it's stabilized.
2211-
let layout =
2212-
Layout::from_size_align(size, align).expect("total allocation size overflows `isize`");
2213+
let layout = Layout::from_size_align(size, align).ok()?;
22132214

22142215
let ptr = if layout.size() != 0 {
22152216
// TODO(#429): Add a "SAFETY" comment and remove this `allow`.
22162217
#[allow(clippy::undocumented_unsafe_blocks)]
2217-
let ptr = unsafe { alloc::alloc::alloc_zeroed(layout).cast::<Self>() };
2218-
if ptr.is_null() {
2219-
alloc::alloc::handle_alloc_error(layout);
2218+
let ptr = unsafe { alloc::alloc::alloc_zeroed(layout) };
2219+
match NonNull::new(ptr) {
2220+
Some(ptr) => ptr,
2221+
None => alloc::alloc::handle_alloc_error(layout),
22202222
}
2221-
ptr
22222223
} else {
22232224
// `Box<[T]>` does not allocate when `T` is zero-sized or when `len`
22242225
// is zero, but it does require a non-null dangling pointer for its
22252226
// allocation.
2226-
NonNull::<Self>::dangling().as_ptr()
2227+
NonNull::<u8>::dangling()
22272228
};
22282229

2230+
let ptr = Self::raw_from_ptr_len(ptr, count);
2231+
22292232
// TODO(#429): Add a "SAFETY" comment and remove this `allow`.
22302233
#[allow(clippy::undocumented_unsafe_blocks)]
2231-
unsafe {
2232-
Box::from_raw(slice::from_raw_parts_mut(ptr, len))
2233-
}
2234+
Some(unsafe { Box::from_raw(ptr.as_ptr()) })
22342235
}
22352236

22362237
/// Creates a `Vec<Self>` from zeroed bytes.
@@ -2257,11 +2258,11 @@ pub unsafe trait FromZeros: TryFromBytes {
22572258
#[cfg(feature = "alloc")]
22582259
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
22592260
#[inline(always)]
2260-
fn new_vec_zeroed(len: usize) -> Vec<Self>
2261+
fn new_vec_zeroed(len: usize) -> Result<Vec<Self>, AllocError>
22612262
where
22622263
Self: Sized,
22632264
{
2264-
Self::new_box_slice_zeroed(len).into()
2265+
<[Self]>::new_box_zeroed_with_elems(len).map(Into::into).ok_or(AllocError)
22652266
}
22662267
}
22672268

0 commit comments

Comments
 (0)