Changed Layout::from_size_align to return Option.
Added `unwrap` calls in all the places where I can infer that the conditions are met to avoid panic (or when the calling method itself says it will panic in such a case).
This commit is contained in:
@@ -63,19 +63,21 @@ pub struct Layout {
|
|||||||
// overflowing_mul as necessary).
|
// overflowing_mul as necessary).
|
||||||
|
|
||||||
impl Layout {
|
impl Layout {
|
||||||
/// Constructs a `Layout` from a given `size` and `align`.
|
/// Constructs a `Layout` from a given `size` and `align`,
|
||||||
///
|
/// or returns `None` if either of the following conditions
|
||||||
/// # Panics
|
/// are not met:
|
||||||
///
|
|
||||||
/// Panics if any of the following conditions are not met:
|
|
||||||
///
|
///
|
||||||
/// * `align` must be a power of two,
|
/// * `align` must be a power of two,
|
||||||
///
|
///
|
||||||
/// * `size`, when rounded up to the nearest multiple of `align`,
|
/// * `size`, when rounded up to the nearest multiple of `align`,
|
||||||
/// must not overflow (i.e. the rounded value must be less than
|
/// must not overflow (i.e. the rounded value must be less than
|
||||||
/// `usize::MAX`).
|
/// `usize::MAX`).
|
||||||
pub fn from_size_align(size: usize, align: usize) -> Layout {
|
pub fn from_size_align(size: usize, align: usize) -> Option<Layout> {
|
||||||
assert!(align.is_power_of_two()); // (this implies align != 0.)
|
if !align.is_power_of_two() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// (power-of-two implies align != 0.)
|
||||||
|
|
||||||
// Rounded up size is:
|
// Rounded up size is:
|
||||||
// size_rounded_up = (size + align - 1) & !(align - 1);
|
// size_rounded_up = (size + align - 1) & !(align - 1);
|
||||||
@@ -89,9 +91,11 @@ impl Layout {
|
|||||||
//
|
//
|
||||||
// Above implies that checking for summation overflow is both
|
// Above implies that checking for summation overflow is both
|
||||||
// necessary and sufficient.
|
// necessary and sufficient.
|
||||||
assert!(size <= usize::MAX - (align - 1));
|
if size > usize::MAX - (align - 1) {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
Layout { size: size, align: align }
|
Some(Layout { size: size, align: align })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The minimum size in bytes for a memory block of this layout.
|
/// The minimum size in bytes for a memory block of this layout.
|
||||||
@@ -103,7 +107,7 @@ impl Layout {
|
|||||||
/// Constructs a `Layout` suitable for holding a value of type `T`.
|
/// Constructs a `Layout` suitable for holding a value of type `T`.
|
||||||
pub fn new<T>() -> Self {
|
pub fn new<T>() -> Self {
|
||||||
let (size, align) = size_align::<T>();
|
let (size, align) = size_align::<T>();
|
||||||
Layout::from_size_align(size, align)
|
Layout::from_size_align(size, align).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Produces layout describing a record that could be used to
|
/// Produces layout describing a record that could be used to
|
||||||
@@ -111,7 +115,7 @@ impl Layout {
|
|||||||
/// or other unsized type like a slice).
|
/// or other unsized type like a slice).
|
||||||
pub fn for_value<T: ?Sized>(t: &T) -> Self {
|
pub fn for_value<T: ?Sized>(t: &T) -> Self {
|
||||||
let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
|
let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
|
||||||
Layout::from_size_align(size, align)
|
Layout::from_size_align(size, align).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a layout describing the record that can hold a value
|
/// Creates a layout describing the record that can hold a value
|
||||||
@@ -128,10 +132,10 @@ impl Layout {
|
|||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
///
|
///
|
||||||
/// Panics if `align` is not a power of two.
|
/// Panics if the combination of `self.size` and the given `align`
|
||||||
|
/// violates the conditions listed in `from_size_align`.
|
||||||
pub fn align_to(&self, align: usize) -> Self {
|
pub fn align_to(&self, align: usize) -> Self {
|
||||||
assert!(align.is_power_of_two());
|
Layout::from_size_align(self.size, cmp::max(self.align, align)).unwrap()
|
||||||
Layout::from_size_align(self.size, cmp::max(self.align, align))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the amount of padding we must insert after `self`
|
/// Returns the amount of padding we must insert after `self`
|
||||||
@@ -193,7 +197,12 @@ impl Layout {
|
|||||||
None => return None,
|
None => return None,
|
||||||
Some(alloc_size) => alloc_size,
|
Some(alloc_size) => alloc_size,
|
||||||
};
|
};
|
||||||
Some((Layout::from_size_align(alloc_size, self.align), padded_size))
|
|
||||||
|
// We can assume that `self.align` is a power-of-two.
|
||||||
|
// Furthermore, `alloc_size` has alreayd been rounded up
|
||||||
|
// to a multiple of `self.align`; therefore, the call
|
||||||
|
// to `Layout::from_size_align` below should never panic.
|
||||||
|
Some((Layout::from_size_align(alloc_size, self.align).unwrap(), padded_size))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a layout describing the record for `self` followed by
|
/// Creates a layout describing the record for `self` followed by
|
||||||
@@ -209,8 +218,13 @@ impl Layout {
|
|||||||
/// On arithmetic overflow, returns `None`.
|
/// On arithmetic overflow, returns `None`.
|
||||||
pub fn extend(&self, next: Self) -> Option<(Self, usize)> {
|
pub fn extend(&self, next: Self) -> Option<(Self, usize)> {
|
||||||
let new_align = cmp::max(self.align, next.align);
|
let new_align = cmp::max(self.align, next.align);
|
||||||
let realigned = Layout::from_size_align(self.size, new_align);
|
let realigned = match Layout::from_size_align(self.size, new_align) {
|
||||||
|
None => return None,
|
||||||
|
Some(l) => l,
|
||||||
|
};
|
||||||
|
|
||||||
let pad = realigned.padding_needed_for(next.align);
|
let pad = realigned.padding_needed_for(next.align);
|
||||||
|
|
||||||
let offset = match self.size.checked_add(pad) {
|
let offset = match self.size.checked_add(pad) {
|
||||||
None => return None,
|
None => return None,
|
||||||
Some(offset) => offset,
|
Some(offset) => offset,
|
||||||
@@ -219,7 +233,12 @@ impl Layout {
|
|||||||
None => return None,
|
None => return None,
|
||||||
Some(new_size) => new_size,
|
Some(new_size) => new_size,
|
||||||
};
|
};
|
||||||
Some((Layout::from_size_align(new_size, new_align), offset))
|
|
||||||
|
let layout = match Layout::from_size_align(new_size, new_align) {
|
||||||
|
None => return None,
|
||||||
|
Some(l) => l,
|
||||||
|
};
|
||||||
|
Some((layout, offset))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a layout describing the record for `n` instances of
|
/// Creates a layout describing the record for `n` instances of
|
||||||
@@ -239,7 +258,8 @@ impl Layout {
|
|||||||
None => return None,
|
None => return None,
|
||||||
Some(scaled) => scaled,
|
Some(scaled) => scaled,
|
||||||
};
|
};
|
||||||
Some(Layout::from_size_align(size, self.align))
|
|
||||||
|
Layout::from_size_align(size, self.align)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a layout describing the record for `self` followed by
|
/// Creates a layout describing the record for `self` followed by
|
||||||
@@ -262,7 +282,11 @@ impl Layout {
|
|||||||
None => return None,
|
None => return None,
|
||||||
Some(new_size) => new_size,
|
Some(new_size) => new_size,
|
||||||
};
|
};
|
||||||
Some((Layout::from_size_align(new_size, self.align), self.size()))
|
let layout = match Layout::from_size_align(new_size, self.align) {
|
||||||
|
None => return None,
|
||||||
|
Some(l) => l,
|
||||||
|
};
|
||||||
|
Some((layout, self.size()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a layout describing the record for a `[T; n]`.
|
/// Creates a layout describing the record for a `[T; n]`.
|
||||||
|
|||||||
Reference in New Issue
Block a user