@@ -11,53 +11,54 @@ use std::fmt;
11
11
12
12
const PRINT_ELEMENTS_LIMIT : Ix = 3 ;
13
13
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 > (
16
30
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 ,
19
36
) -> fmt:: Result
20
37
where
21
- F : FnMut ( & A , & mut fmt:: Formatter < ' _ > ) -> fmt:: Result ,
22
- S : Data < Elem = A > ,
38
+ F : FnMut ( & mut fmt:: Formatter < ' _ > , usize ) -> fmt:: Result ,
23
39
{
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
+ } ) ?;
55
48
} 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
+ } ) ?;
60
60
}
61
+ Ok ( ( ) )
61
62
}
62
63
63
64
fn format_array < A , S , D , F > (
@@ -80,54 +81,37 @@ where
80
81
}
81
82
match view. shape ( ) {
82
83
// 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
+ }
91
94
// For n-dimensional arrays, we proceed recursively
92
95
shape => {
93
96
// Cast into a dynamically dimensioned view
94
97
// This is required to be able to use `index_axis`
95
98
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 ( ) ;
101
99
102
100
let blank_lines = "\n " . repeat ( shape. len ( ) - 2 ) ;
103
101
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 ( "]" ) ?;
131
115
}
132
116
}
133
117
Ok ( ( ) )
0 commit comments