@@ -63,19 +63,21 @@ pub struct Layout {
63
63
// overflowing_mul as necessary).
64
64
65
65
impl Layout {
66
- /// Constructs a `Layout` from a given `size` and `align`.
67
- ///
68
- /// # Panics
69
- ///
70
- /// Panics if any of the following conditions are not met:
66
+ /// Constructs a `Layout` from a given `size` and `align`,
67
+ /// or returns `None` if either of the following conditions
68
+ /// are not met:
71
69
///
72
70
/// * `align` must be a power of two,
73
71
///
74
72
/// * `size`, when rounded up to the nearest multiple of `align`,
75
73
/// must not overflow (i.e. the rounded value must be less than
76
74
/// `usize::MAX`).
77
- pub fn from_size_align ( size : usize , align : usize ) -> Layout {
78
- assert ! ( align. is_power_of_two( ) ) ; // (this implies align != 0.)
75
+ pub fn from_size_align ( size : usize , align : usize ) -> Option < Layout > {
76
+ if !align. is_power_of_two ( ) {
77
+ return None ;
78
+ }
79
+
80
+ // (power-of-two implies align != 0.)
79
81
80
82
// Rounded up size is:
81
83
// size_rounded_up = (size + align - 1) & !(align - 1);
@@ -89,9 +91,11 @@ impl Layout {
89
91
//
90
92
// Above implies that checking for summation overflow is both
91
93
// necessary and sufficient.
92
- assert ! ( size <= usize :: MAX - ( align - 1 ) ) ;
94
+ if size > usize:: MAX - ( align - 1 ) {
95
+ return None ;
96
+ }
93
97
94
- Layout { size : size, align : align }
98
+ Some ( Layout { size : size, align : align } )
95
99
}
96
100
97
101
/// The minimum size in bytes for a memory block of this layout.
@@ -103,15 +107,15 @@ impl Layout {
103
107
/// Constructs a `Layout` suitable for holding a value of type `T`.
104
108
pub fn new < T > ( ) -> Self {
105
109
let ( size, align) = size_align :: < T > ( ) ;
106
- Layout :: from_size_align ( size, align)
110
+ Layout :: from_size_align ( size, align) . unwrap ( )
107
111
}
108
112
109
113
/// Produces layout describing a record that could be used to
110
114
/// allocate backing structure for `T` (which could be a trait
111
115
/// or other unsized type like a slice).
112
116
pub fn for_value < T : ?Sized > ( t : & T ) -> Self {
113
117
let ( size, align) = ( mem:: size_of_val ( t) , mem:: align_of_val ( t) ) ;
114
- Layout :: from_size_align ( size, align)
118
+ Layout :: from_size_align ( size, align) . unwrap ( )
115
119
}
116
120
117
121
/// Creates a layout describing the record that can hold a value
@@ -128,10 +132,10 @@ impl Layout {
128
132
///
129
133
/// # Panics
130
134
///
131
- /// Panics if `align` is not a power of two.
135
+ /// Panics if the combination of `self.size` and the given `align`
136
+ /// violates the conditions listed in `from_size_align`.
132
137
pub fn align_to ( & self , align : usize ) -> Self {
133
- assert ! ( align. is_power_of_two( ) ) ;
134
- Layout :: from_size_align ( self . size , cmp:: max ( self . align , align) )
138
+ Layout :: from_size_align ( self . size , cmp:: max ( self . align , align) ) . unwrap ( )
135
139
}
136
140
137
141
/// Returns the amount of padding we must insert after `self`
@@ -193,7 +197,12 @@ impl Layout {
193
197
None => return None ,
194
198
Some ( alloc_size) => alloc_size,
195
199
} ;
196
- Some ( ( Layout :: from_size_align ( alloc_size, self . align ) , padded_size) )
200
+
201
+ // We can assume that `self.align` is a power-of-two.
202
+ // Furthermore, `alloc_size` has alreayd been rounded up
203
+ // to a multiple of `self.align`; therefore, the call
204
+ // to `Layout::from_size_align` below should never panic.
205
+ Some ( ( Layout :: from_size_align ( alloc_size, self . align ) . unwrap ( ) , padded_size) )
197
206
}
198
207
199
208
/// Creates a layout describing the record for `self` followed by
@@ -209,8 +218,13 @@ impl Layout {
209
218
/// On arithmetic overflow, returns `None`.
210
219
pub fn extend ( & self , next : Self ) -> Option < ( Self , usize ) > {
211
220
let new_align = cmp:: max ( self . align , next. align ) ;
212
- let realigned = Layout :: from_size_align ( self . size , new_align) ;
221
+ let realigned = match Layout :: from_size_align ( self . size , new_align) {
222
+ None => return None ,
223
+ Some ( l) => l,
224
+ } ;
225
+
213
226
let pad = realigned. padding_needed_for ( next. align ) ;
227
+
214
228
let offset = match self . size . checked_add ( pad) {
215
229
None => return None ,
216
230
Some ( offset) => offset,
@@ -219,7 +233,12 @@ impl Layout {
219
233
None => return None ,
220
234
Some ( new_size) => new_size,
221
235
} ;
222
- Some ( ( Layout :: from_size_align ( new_size, new_align) , offset) )
236
+
237
+ let layout = match Layout :: from_size_align ( new_size, new_align) {
238
+ None => return None ,
239
+ Some ( l) => l,
240
+ } ;
241
+ Some ( ( layout, offset) )
223
242
}
224
243
225
244
/// Creates a layout describing the record for `n` instances of
@@ -239,7 +258,8 @@ impl Layout {
239
258
None => return None ,
240
259
Some ( scaled) => scaled,
241
260
} ;
242
- Some ( Layout :: from_size_align ( size, self . align ) )
261
+
262
+ Layout :: from_size_align ( size, self . align )
243
263
}
244
264
245
265
/// Creates a layout describing the record for `self` followed by
@@ -262,7 +282,11 @@ impl Layout {
262
282
None => return None ,
263
283
Some ( new_size) => new_size,
264
284
} ;
265
- Some ( ( Layout :: from_size_align ( new_size, self . align ) , self . size ( ) ) )
285
+ let layout = match Layout :: from_size_align ( new_size, self . align ) {
286
+ None => return None ,
287
+ Some ( l) => l,
288
+ } ;
289
+ Some ( ( layout, self . size ( ) ) )
266
290
}
267
291
268
292
/// Creates a layout describing the record for a `[T; n]`.
0 commit comments