@@ -20,6 +20,7 @@ use fmt;
20
20
use mem;
21
21
use usize;
22
22
use ptr:: { self , NonNull } ;
23
+ use num:: NonZeroUsize ;
23
24
24
25
extern {
25
26
/// An opaque, unsized type. Used for pointers to allocated memory.
@@ -66,7 +67,7 @@ fn size_align<T>() -> (usize, usize) {
66
67
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
67
68
pub struct Layout {
68
69
// size of the requested block of memory, measured in bytes.
69
- size : usize ,
70
+ size_ : usize ,
70
71
71
72
// alignment of the requested block of memory, measured in bytes.
72
73
// we ensure that this is always a power-of-two, because API's
@@ -75,17 +76,12 @@ pub struct Layout {
75
76
//
76
77
// (However, we do not analogously require `align >= sizeof(void*)`,
77
78
// even though that is *also* a requirement of `posix_memalign`.)
78
- align : usize ,
79
+ align_ : NonZeroUsize ,
79
80
}
80
81
81
-
82
- // FIXME: audit default implementations for overflow errors,
83
- // (potentially switching to overflowing_add and
84
- // overflowing_mul as necessary).
85
-
86
82
impl Layout {
87
83
/// Constructs a `Layout` from a given `size` and `align`,
88
- /// or returns `None ` if either of the following conditions
84
+ /// or returns `LayoutErr ` if either of the following conditions
89
85
/// are not met:
90
86
///
91
87
/// * `align` must be a power of two,
@@ -126,23 +122,23 @@ impl Layout {
126
122
///
127
123
/// # Safety
128
124
///
129
- /// This function is unsafe as it does not verify that `align` is
130
- /// a power-of-two nor `size` aligned to `align` fits within the
131
- /// address space (i.e. the `Layout::from_size_align` preconditions).
125
+ /// This function is unsafe as it does not verify the preconditions from
126
+ /// [`Layout::from_size_align`](#method.from_size_align).
132
127
#[ inline]
133
128
pub unsafe fn from_size_align_unchecked ( size : usize , align : usize ) -> Self {
134
- Layout { size : size, align : align }
129
+ Layout { size_ : size, align_ : NonZeroUsize :: new_unchecked ( align) }
135
130
}
136
131
137
132
/// The minimum size in bytes for a memory block of this layout.
138
133
#[ inline]
139
- pub fn size ( & self ) -> usize { self . size }
134
+ pub fn size ( & self ) -> usize { self . size_ }
140
135
141
136
/// The minimum byte alignment for a memory block of this layout.
142
137
#[ inline]
143
- pub fn align ( & self ) -> usize { self . align }
138
+ pub fn align ( & self ) -> usize { self . align_ . get ( ) }
144
139
145
140
/// Constructs a `Layout` suitable for holding a value of type `T`.
141
+ #[ inline]
146
142
pub fn new < T > ( ) -> Self {
147
143
let ( size, align) = size_align :: < T > ( ) ;
148
144
// Note that the align is guaranteed by rustc to be a power of two and
@@ -158,6 +154,7 @@ impl Layout {
158
154
/// Produces layout describing a record that could be used to
159
155
/// allocate backing structure for `T` (which could be a trait
160
156
/// or other unsized type like a slice).
157
+ #[ inline]
161
158
pub fn for_value < T : ?Sized > ( t : & T ) -> Self {
162
159
let ( size, align) = ( mem:: size_of_val ( t) , mem:: align_of_val ( t) ) ;
163
160
// See rationale in `new` for why this us using an unsafe variant below
@@ -181,18 +178,19 @@ impl Layout {
181
178
///
182
179
/// # Panics
183
180
///
184
- /// Panics if the combination of `self.size` and the given `align`
185
- /// violates the conditions listed in `from_size_align`.
181
+ /// Panics if the combination of `self.size()` and the given `align`
182
+ /// violates the conditions listed in
183
+ /// [`Layout::from_size_align`](#method.from_size_align).
186
184
#[ inline]
187
185
pub fn align_to ( & self , align : usize ) -> Self {
188
- Layout :: from_size_align ( self . size , cmp:: max ( self . align , align) ) . unwrap ( )
186
+ Layout :: from_size_align ( self . size ( ) , cmp:: max ( self . align ( ) , align) ) . unwrap ( )
189
187
}
190
188
191
189
/// Returns the amount of padding we must insert after `self`
192
190
/// to ensure that the following address will satisfy `align`
193
191
/// (measured in bytes).
194
192
///
195
- /// E.g. if `self.size` is 9, then `self.padding_needed_for(4)`
193
+ /// E.g. if `self.size() ` is 9, then `self.padding_needed_for(4)`
196
194
/// returns 3, because that is the minimum number of bytes of
197
195
/// padding required to get a 4-aligned address (assuming that the
198
196
/// corresponding memory block starts at a 4-aligned address).
@@ -203,7 +201,7 @@ impl Layout {
203
201
/// Note that the utility of the returned value requires `align`
204
202
/// to be less than or equal to the alignment of the starting
205
203
/// address for the whole allocated block of memory. One way to
206
- /// satisfy this constraint is to ensure `align <= self.align`.
204
+ /// satisfy this constraint is to ensure `align <= self.align() `.
207
205
#[ inline]
208
206
pub fn padding_needed_for ( & self , align : usize ) -> usize {
209
207
let len = self . size ( ) ;
@@ -227,7 +225,8 @@ impl Layout {
227
225
// size and padding overflow in the above manner should cause
228
226
// the allocator to yield an error anyway.)
229
227
230
- let len_rounded_up = len. wrapping_add ( align) . wrapping_sub ( 1 ) & !align. wrapping_sub ( 1 ) ;
228
+ let len_rounded_up = len. wrapping_add ( align) . wrapping_sub ( 1 )
229
+ & !align. wrapping_sub ( 1 ) ;
231
230
return len_rounded_up. wrapping_sub ( len) ;
232
231
}
233
232
@@ -238,14 +237,19 @@ impl Layout {
238
237
/// layout of the array and `offs` is the distance between the start
239
238
/// of each element in the array.
240
239
///
241
- /// On arithmetic overflow, returns `None `.
240
+ /// On arithmetic overflow, returns `LayoutErr `.
242
241
#[ inline]
243
242
pub fn repeat ( & self , n : usize ) -> Result < ( Self , usize ) , LayoutErr > {
244
- let padded_size = self . size . checked_add ( self . padding_needed_for ( self . align ) )
243
+ let padded_size = self . size ( ) . checked_add ( self . padding_needed_for ( self . align ( ) ) )
245
244
. ok_or ( LayoutErr { private : ( ) } ) ?;
246
245
let alloc_size = padded_size. checked_mul ( n)
247
246
. ok_or ( LayoutErr { private : ( ) } ) ?;
248
- Ok ( ( Layout :: from_size_align ( alloc_size, self . align ) ?, padded_size) )
247
+
248
+ unsafe {
249
+ // self.align is already known to be valid and alloc_size has been
250
+ // padded already.
251
+ Ok ( ( Layout :: from_size_align_unchecked ( alloc_size, self . align ( ) ) , padded_size) )
252
+ }
249
253
}
250
254
251
255
/// Creates a layout describing the record for `self` followed by
@@ -258,16 +262,15 @@ impl Layout {
258
262
/// start of the `next` embedded within the concatenated record
259
263
/// (assuming that the record itself starts at offset 0).
260
264
///
261
- /// On arithmetic overflow, returns `None`.
265
+ /// On arithmetic overflow, returns `LayoutErr`.
266
+ #[ inline]
262
267
pub fn extend ( & self , next : Self ) -> Result < ( Self , usize ) , LayoutErr > {
263
- let new_align = cmp:: max ( self . align , next. align ) ;
264
- let realigned = Layout :: from_size_align ( self . size , new_align) ?;
265
-
266
- let pad = realigned. padding_needed_for ( next. align ) ;
268
+ let new_align = cmp:: max ( self . align ( ) , next. align ( ) ) ;
269
+ let pad = self . padding_needed_for ( next. align ( ) ) ;
267
270
268
- let offset = self . size . checked_add ( pad)
271
+ let offset = self . size ( ) . checked_add ( pad)
269
272
. ok_or ( LayoutErr { private : ( ) } ) ?;
270
- let new_size = offset. checked_add ( next. size )
273
+ let new_size = offset. checked_add ( next. size ( ) )
271
274
. ok_or ( LayoutErr { private : ( ) } ) ?;
272
275
273
276
let layout = Layout :: from_size_align ( new_size, new_align) ?;
@@ -285,10 +288,11 @@ impl Layout {
285
288
/// guaranteed that all elements in the array will be properly
286
289
/// aligned.
287
290
///
288
- /// On arithmetic overflow, returns `None`.
291
+ /// On arithmetic overflow, returns `LayoutErr`.
292
+ #[ inline]
289
293
pub fn repeat_packed ( & self , n : usize ) -> Result < Self , LayoutErr > {
290
294
let size = self . size ( ) . checked_mul ( n) . ok_or ( LayoutErr { private : ( ) } ) ?;
291
- Layout :: from_size_align ( size, self . align )
295
+ Layout :: from_size_align ( size, self . align ( ) )
292
296
}
293
297
294
298
/// Creates a layout describing the record for `self` followed by
@@ -305,17 +309,19 @@ impl Layout {
305
309
/// signature out of convenience in matching the signature of
306
310
/// `extend`.)
307
311
///
308
- /// On arithmetic overflow, returns `None`.
312
+ /// On arithmetic overflow, returns `LayoutErr`.
313
+ #[ inline]
309
314
pub fn extend_packed ( & self , next : Self ) -> Result < ( Self , usize ) , LayoutErr > {
310
315
let new_size = self . size ( ) . checked_add ( next. size ( ) )
311
316
. ok_or ( LayoutErr { private : ( ) } ) ?;
312
- let layout = Layout :: from_size_align ( new_size, self . align ) ?;
317
+ let layout = Layout :: from_size_align ( new_size, self . align ( ) ) ?;
313
318
Ok ( ( layout, self . size ( ) ) )
314
319
}
315
320
316
321
/// Creates a layout describing the record for a `[T; n]`.
317
322
///
318
- /// On arithmetic overflow, returns `None`.
323
+ /// On arithmetic overflow, returns `LayoutErr`.
324
+ #[ inline]
319
325
pub fn array < T > ( n : usize ) -> Result < Self , LayoutErr > {
320
326
Layout :: new :: < T > ( )
321
327
. repeat ( n)
@@ -842,7 +848,7 @@ pub unsafe trait Alloc {
842
848
layout : Layout ,
843
849
new_size : usize ) -> Result < ( ) , CannotReallocInPlace > {
844
850
let _ = ptr; // this default implementation doesn't care about the actual address.
845
- debug_assert ! ( new_size >= layout. size) ;
851
+ debug_assert ! ( new_size >= layout. size( ) ) ;
846
852
let ( _l, u) = self . usable_size ( & layout) ;
847
853
// _l <= layout.size() [guaranteed by usable_size()]
848
854
// layout.size() <= new_layout.size() [required by this method]
@@ -897,7 +903,7 @@ pub unsafe trait Alloc {
897
903
layout : Layout ,
898
904
new_size : usize ) -> Result < ( ) , CannotReallocInPlace > {
899
905
let _ = ptr; // this default implementation doesn't care about the actual address.
900
- debug_assert ! ( new_size <= layout. size) ;
906
+ debug_assert ! ( new_size <= layout. size( ) ) ;
901
907
let ( l, _u) = self . usable_size ( & layout) ;
902
908
// layout.size() <= _u [guaranteed by usable_size()]
903
909
// new_layout.size() <= layout.size() [required by this method]
0 commit comments