@@ -11,53 +11,54 @@ use std::fmt;
1111
1212const PRINT_ELEMENTS_LIMIT : Ix = 3 ;
1313
14- fn format_1d_array < A , S , F > (
15- view : & ArrayBase < S , Ix1 > ,
14+ const ELLIPSIS : & str = "..." ;
15+
16+ /// Formats the contents of a list of items, using an ellipsis to indicate when
17+ /// the length of the list is greater than `2 * limit`.
18+ ///
19+ /// # Parameters
20+ ///
21+ /// * `f`: The formatter.
22+ /// * `length`: The length of the list.
23+ /// * `limit`: Half the maximum number of items before indicating overflow with
24+ /// an ellipsis. Also, the number of items on either side of the ellipsis.
25+ /// * `separator`: Separator to write between items.
26+ /// * `ellipsis`: Ellipsis for indicating overflow.
27+ /// * `fmt_elem`: A function that formats an element in the list, given the
28+ /// formatter and the index of the item in the list.
29+ fn format_with_overflow < F > (
1630 f : & mut fmt:: Formatter < ' _ > ,
17- mut format : F ,
18- limit : Ix ,
31+ length : usize ,
32+ limit : usize ,
33+ separator : & str ,
34+ ellipsis : & str ,
35+ mut fmt_elem : F ,
1936) -> fmt:: Result
2037where
21- F : FnMut ( & A , & mut fmt:: Formatter < ' _ > ) -> fmt:: Result ,
22- S : Data < Elem = A > ,
38+ F : FnMut ( & mut fmt:: Formatter < ' _ > , usize ) -> fmt:: Result ,
2339{
24- let to_be_printed = to_be_printed ( view. len ( ) , limit) ;
25-
26- let n_to_be_printed = to_be_printed. len ( ) ;
27-
28- write ! ( f, "[" ) ?;
29- for ( j, index) in to_be_printed. into_iter ( ) . enumerate ( ) {
30- match index {
31- PrintableCell :: ElementIndex ( i) => {
32- format ( & view[ i] , f) ?;
33- if j != n_to_be_printed - 1 {
34- write ! ( f, ", " ) ?;
35- }
36- }
37- PrintableCell :: Ellipses => write ! ( f, "..., " ) ?,
38- }
39- }
40- write ! ( f, "]" ) ?;
41- Ok ( ( ) )
42- }
43-
44- enum PrintableCell {
45- ElementIndex ( usize ) ,
46- Ellipses ,
47- }
48-
49- // Returns what indexes should be printed for a certain axis.
50- // If the axis is longer than 2 * limit, a `Ellipses` is inserted
51- // where indexes are being omitted.
52- fn to_be_printed ( length : usize , limit : usize ) -> Vec < PrintableCell > {
53- if length <= 2 * limit {
54- ( 0 ..length) . map ( PrintableCell :: ElementIndex ) . collect ( )
40+ if length == 0 {
41+ // no-op
42+ } else if length <= 2 * limit {
43+ fmt_elem ( f, 0 ) ?;
44+ ( 1 ..length) . try_for_each ( |i| {
45+ f. write_str ( separator) ?;
46+ fmt_elem ( f, i)
47+ } ) ?;
5548 } else {
56- let mut v: Vec < PrintableCell > = ( 0 ..limit) . map ( PrintableCell :: ElementIndex ) . collect ( ) ;
57- v. push ( PrintableCell :: Ellipses ) ;
58- v. extend ( ( length - limit..length) . map ( PrintableCell :: ElementIndex ) ) ;
59- v
49+ fmt_elem ( f, 0 ) ?;
50+ ( 1 ..limit) . try_for_each ( |i| {
51+ f. write_str ( separator) ?;
52+ fmt_elem ( f, i)
53+ } ) ?;
54+ f. write_str ( separator) ?;
55+ f. write_str ( ellipsis) ?;
56+ ( length - limit..length) . try_for_each ( |i| {
57+ f. write_str ( separator) ?;
58+ fmt_elem ( f, i)
59+ } ) ?;
6060 }
61+ Ok ( ( ) )
6162}
6263
6364fn format_array < A , S , D , F > (
@@ -80,54 +81,37 @@ where
8081 }
8182 match view. shape ( ) {
8283 // If it's 0 dimensional, we just print out the scalar
83- [ ] => format ( view. iter ( ) . next ( ) . unwrap ( ) , f) ?,
84- // We delegate 1-dimensional arrays to a specialized function
85- [ _] => format_1d_array (
86- & view. view ( ) . into_dimensionality :: < Ix1 > ( ) . unwrap ( ) ,
87- f,
88- format,
89- limit,
90- ) ?,
84+ & [ ] => format ( view. iter ( ) . next ( ) . unwrap ( ) , f) ?,
85+ // We handle 1-D arrays as a special case
86+ & [ len] => {
87+ let view = view. view ( ) . into_dimensionality :: < Ix1 > ( ) . unwrap ( ) ;
88+ f. write_str ( "[" ) ?;
89+ format_with_overflow ( f, len, limit, ", " , ELLIPSIS , |f, index| {
90+ format ( & view[ index] , f)
91+ } ) ?;
92+ f. write_str ( "]" ) ?;
93+ }
9194 // For n-dimensional arrays, we proceed recursively
9295 shape => {
9396 // Cast into a dynamically dimensioned view
9497 // This is required to be able to use `index_axis`
9598 let view = view. view ( ) . into_dyn ( ) ;
96- // We start by checking what indexes from the first axis should be printed
97- // We put a `None` in the middle if we are omitting elements
98- let to_be_printed = to_be_printed ( shape[ 0 ] , limit) ;
99-
100- let n_to_be_printed = to_be_printed. len ( ) ;
10199
102100 let blank_lines = "\n " . repeat ( shape. len ( ) - 2 ) ;
103101 let indent = " " . repeat ( depth + 1 ) ;
104-
105- write ! ( f, "[" ) ?;
106- for ( j, index) in to_be_printed. into_iter ( ) . enumerate ( ) {
107- match index {
108- PrintableCell :: ElementIndex ( i) => {
109- // Indent all but the first line.
110- if j != 0 {
111- write ! ( f, "{}" , indent) ?;
112- }
113- // Proceed recursively with the (n-1)-dimensional slice
114- format_array (
115- & view. index_axis ( Axis ( 0 ) , i) ,
116- f,
117- format. clone ( ) ,
118- limit,
119- depth + 1 ,
120- ) ?;
121- // We need to add a separator after each slice,
122- // apart from the last one
123- if j != n_to_be_printed - 1 {
124- write ! ( f, ",\n {}" , blank_lines) ?
125- }
126- }
127- PrintableCell :: Ellipses => write ! ( f, "{}...,\n {}" , indent, blank_lines) ?,
128- }
129- }
130- write ! ( f, "]" ) ?;
102+ let separator = format ! ( ",\n {}{}" , blank_lines, indent) ;
103+
104+ f. write_str ( "[" ) ?;
105+ format_with_overflow ( f, shape[ 0 ] , limit, & separator, ELLIPSIS , |f, index| {
106+ format_array (
107+ & view. index_axis ( Axis ( 0 ) , index) ,
108+ f,
109+ format. clone ( ) ,
110+ limit,
111+ depth + 1 ,
112+ )
113+ } ) ?;
114+ f. write_str ( "]" ) ?;
131115 }
132116 }
133117 Ok ( ( ) )
0 commit comments