@@ -260,15 +260,19 @@ impl<A> Array<A, Ix2>
260260 /// This is useful when pushing or appending repeatedly to an array to avoid multiple
261261 /// allocations.
262262 ///
263+ /// ***Errors*** with a shape error if the resultant capacity is larger than the addressable
264+ /// bounds; that is, the product of non-zero axis lengths once `axis` has been extended by
265+ /// `additional` exceeds `isize::MAX`.
266+ ///
263267 /// ```rust
264268 /// use ndarray::Array2;
265269 /// let mut a = Array2::<i32>::zeros((2,4));
266- /// a.reserve_rows(1000);
270+ /// a.reserve_rows(1000).unwrap() ;
267271 /// assert!(a.into_raw_vec().capacity() >= 4*1002);
268272 /// ```
269- pub fn reserve_rows ( & mut self , additional : usize )
273+ pub fn reserve_rows ( & mut self , additional : usize ) -> Result < ( ) , ShapeError >
270274 {
271- self . reserve ( Axis ( 0 ) , additional) ;
275+ self . reserve ( Axis ( 0 ) , additional)
272276 }
273277
274278 /// Reserve capacity to grow array by at least `additional` columns.
@@ -279,15 +283,19 @@ impl<A> Array<A, Ix2>
279283 /// This is useful when pushing or appending repeatedly to an array to avoid multiple
280284 /// allocations.
281285 ///
286+ /// ***Errors*** with a shape error if the resultant capacity is larger than the addressable
287+ /// bounds; that is, the product of non-zero axis lengths once `axis` has been extended by
288+ /// `additional` exceeds `isize::MAX`.
289+ ///
282290 /// ```rust
283291 /// use ndarray::Array2;
284292 /// let mut a = Array2::<i32>::zeros((2,4));
285- /// a.reserve_columns(1000);
293+ /// a.reserve_columns(1000).unwrap() ;
286294 /// assert!(a.into_raw_vec().capacity() >= 2*1002);
287295 /// ```
288- pub fn reserve_columns ( & mut self , additional : usize )
296+ pub fn reserve_columns ( & mut self , additional : usize ) -> Result < ( ) , ShapeError >
289297 {
290- self . reserve ( Axis ( 1 ) , additional) ;
298+ self . reserve ( Axis ( 1 ) , additional)
291299 }
292300}
293301
@@ -699,7 +707,7 @@ where D: Dimension
699707 } ;
700708
701709 // grow backing storage and update head ptr
702- self . reserve ( axis, array_dim[ axis. index ( ) ] ) ;
710+ self . reserve ( axis, array_dim[ axis. index ( ) ] ) ? ;
703711
704712 unsafe {
705713 // clone elements from view to the array now
@@ -788,25 +796,42 @@ where D: Dimension
788796
789797 /// Reserve capacity to grow array along `axis` by at least `additional` elements.
790798 ///
799+ /// The axis should be in the range `Axis(` 0 .. *n* `)` where *n* is the
800+ /// number of dimensions (axes) of the array.
801+ ///
791802 /// Existing elements of `array` are untouched and the backing storage is grown by
792803 /// calling the underlying `reserve` method of the `OwnedRepr`.
793804 ///
794805 /// This is useful when pushing or appending repeatedly to an array to avoid multiple
795806 /// allocations.
796807 ///
808+ /// ***Panics*** if the axis is out of bounds.
809+ ///
810+ /// ***Errors*** with a shape error if the resultant capacity is larger than the addressable
811+ /// bounds; that is, the product of non-zero axis lengths once `axis` has been extended by
812+ /// `additional` exceeds `isize::MAX`.
813+ ///
797814 /// ```rust
798815 /// use ndarray::{Array3, Axis};
799816 /// let mut a = Array3::<i32>::zeros((0,2,4));
800- /// a.reserve(Axis(0), 1000);
817+ /// a.reserve(Axis(0), 1000).unwrap() ;
801818 /// assert!(a.into_raw_vec().capacity() >= 2*4*1000);
802819 /// ```
803- pub fn reserve ( & mut self , axis : Axis , additional : usize )
820+ ///
821+ pub fn reserve ( & mut self , axis : Axis , additional : usize ) -> Result < ( ) , ShapeError >
804822 where D : RemoveAxis
805823 {
824+ debug_assert ! ( axis. index( ) < self . ndim( ) ) ;
806825 let self_dim = self . raw_dim ( ) ;
807826 let remaining_shape = self_dim. remove_axis ( axis) ;
808827 let len_to_append = remaining_shape. size ( ) * additional;
809828
829+ // Make sure new capacity is still in bounds
830+ let mut res_dim = self_dim;
831+ res_dim[ axis. index ( ) ] += additional;
832+ let new_len = dimension:: size_of_shape_checked ( & res_dim) ?;
833+ debug_assert_eq ! ( self . len( ) + len_to_append, new_len) ;
834+
810835 unsafe {
811836 // grow backing storage and update head ptr
812837 let data_to_array_offset = if std:: mem:: size_of :: < A > ( ) != 0 {
@@ -820,6 +845,10 @@ where D: Dimension
820845 . reserve ( len_to_append)
821846 . offset ( data_to_array_offset) ;
822847 }
848+
849+ debug_assert ! ( self . pointer_is_inbounds( ) ) ;
850+
851+ Ok ( ( ) )
823852 }
824853}
825854
0 commit comments