diff options
| author | Felix S. Klock II <pnkfelix@pnkfx.org> | 2017-06-15 22:44:56 +0200 |
|---|---|---|
| committer | Felix S. Klock II <pnkfelix@pnkfx.org> | 2017-06-15 23:48:30 +0200 |
| commit | 1d3bc4e90fab35d4debe7d6cb0468d299b38354c (patch) | |
| tree | 980b2e38c735479fd6ebae71d85a007d4fd970e5 /src/liballoc/allocator.rs | |
| parent | 066fafe2062b17fac343219e0067edbc14b774ae (diff) | |
| download | rust-1d3bc4e90fab35d4debe7d6cb0468d299b38354c.tar.gz rust-1d3bc4e90fab35d4debe7d6cb0468d299b38354c.zip | |
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).
Diffstat (limited to 'src/liballoc/allocator.rs')
| -rw-r--r-- | src/liballoc/allocator.rs | 62 |
1 files changed, 43 insertions, 19 deletions
diff --git a/src/liballoc/allocator.rs b/src/liballoc/allocator.rs index 89324cf86f6..c308d99a72c 100644 --- a/src/liballoc/allocator.rs +++ b/src/liballoc/allocator.rs @@ -63,19 +63,21 @@ pub struct Layout { // overflowing_mul as necessary). impl Layout { - /// Constructs a `Layout` from a given `size` and `align`. - /// - /// # Panics - /// - /// Panics if any of the following conditions are not met: + /// Constructs a `Layout` from a given `size` and `align`, + /// or returns `None` if either of the following conditions + /// are not met: /// /// * `align` must be a power of two, /// /// * `size`, when rounded up to the nearest multiple of `align`, /// must not overflow (i.e. the rounded value must be less than /// `usize::MAX`). - pub fn from_size_align(size: usize, align: usize) -> Layout { - assert!(align.is_power_of_two()); // (this implies align != 0.) + pub fn from_size_align(size: usize, align: usize) -> Option<Layout> { + if !align.is_power_of_two() { + return None; + } + + // (power-of-two implies align != 0.) // Rounded up size is: // size_rounded_up = (size + align - 1) & !(align - 1); @@ -89,9 +91,11 @@ impl Layout { // // Above implies that checking for summation overflow is both // 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. @@ -103,7 +107,7 @@ impl Layout { /// Constructs a `Layout` suitable for holding a value of type `T`. pub fn new<T>() -> Self { 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 @@ -111,7 +115,7 @@ impl Layout { /// or other unsized type like a slice). pub fn for_value<T: ?Sized>(t: &T) -> Self { 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 @@ -128,10 +132,10 @@ impl Layout { /// /// # 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 { - assert!(align.is_power_of_two()); - Layout::from_size_align(self.size, cmp::max(self.align, align)) + Layout::from_size_align(self.size, cmp::max(self.align, align)).unwrap() } /// Returns the amount of padding we must insert after `self` @@ -193,7 +197,12 @@ impl Layout { None => return None, 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 @@ -209,8 +218,13 @@ impl Layout { /// On arithmetic overflow, returns `None`. pub fn extend(&self, next: Self) -> Option<(Self, usize)> { 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 offset = match self.size.checked_add(pad) { None => return None, Some(offset) => offset, @@ -219,7 +233,12 @@ impl Layout { None => return None, 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 @@ -239,7 +258,8 @@ impl Layout { None => return None, 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 @@ -262,7 +282,11 @@ impl Layout { None => return None, 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]`. |
