@@ -3,8 +3,8 @@ use crate::options::{Opt, Trim, EOL};
3
3
use anyhow:: Result ;
4
4
use bstr:: ByteSlice ;
5
5
use std:: convert:: TryFrom ;
6
+ use std:: io:: Write ;
6
7
use std:: io:: { self , BufRead } ;
7
- use std:: { io:: Write , ops:: Range } ;
8
8
9
9
use bstr:: io:: BufReadExt ;
10
10
@@ -18,11 +18,12 @@ fn trim<'a>(buffer: &'a [u8], trim_kind: &Trim, delimiter: u8) -> &'a [u8] {
18
18
}
19
19
}
20
20
21
+ #[ inline( always) ]
21
22
fn cut_str_fast_lane < W : Write > (
22
23
initial_buffer : & [ u8 ] ,
23
24
opt : & FastOpt ,
24
25
stdout : & mut W ,
25
- fields : & mut Vec < Range < usize > > ,
26
+ fields : & mut Vec < usize > ,
26
27
last_interesting_field : Side ,
27
28
) -> Result < ( ) > {
28
29
let mut buffer = initial_buffer;
@@ -40,19 +41,14 @@ fn cut_str_fast_lane<W: Write>(
40
41
41
42
let bounds = & opt. bounds ;
42
43
43
- let mut prev_field_start = 0 ;
44
-
45
44
let mut curr_field = 0 ;
46
45
47
46
fields. clear ( ) ;
48
47
49
48
for i in memchr:: memchr_iter ( opt. delimiter , buffer) {
50
49
curr_field += 1 ;
51
50
52
- let ( start, end) = ( prev_field_start, i) ; // end exclusive
53
- prev_field_start = i + 1 ;
54
-
55
- fields. push ( Range { start, end } ) ;
51
+ fields. push ( i) ;
56
52
57
53
if Side :: Some ( curr_field) == last_interesting_field {
58
54
// We have no use for any other fields in this line
@@ -65,20 +61,16 @@ fn cut_str_fast_lane<W: Write>(
65
61
return Ok ( ( ) ) ;
66
62
}
67
63
68
- // After the last loop ended, everything remaining is the field
69
- // after the last delimiter (we want it), or "useless" fields after the
70
- // last one that the user is interested in (and we can ignore them).
71
64
if Side :: Some ( curr_field) != last_interesting_field {
72
- fields. push ( Range {
73
- start : prev_field_start,
74
- end : buffer. len ( ) ,
75
- } ) ;
65
+ // We reached the end of the line. Who knows, maybe
66
+ // the user is interested in this field too.
67
+ fields. push ( buffer. len ( ) ) ;
76
68
}
77
69
78
70
let num_fields = fields. len ( ) ;
79
71
80
72
match num_fields {
81
- 1 if bounds. len ( ) == 1 && fields[ 0 ] . end == buffer. len ( ) => {
73
+ 1 if bounds. len ( ) == 1 && fields[ 0 ] == buffer. len ( ) => {
82
74
stdout. write_all ( buffer) ?;
83
75
}
84
76
_ => {
@@ -107,14 +99,19 @@ fn output_parts<W: Write>(
107
99
// which parts to print
108
100
b : & UserBounds ,
109
101
// where to find the parts inside `line`
110
- fields : & [ Range < usize > ] ,
102
+ fields : & [ usize ] ,
111
103
stdout : & mut W ,
112
104
opt : & FastOpt ,
113
105
) -> Result < ( ) > {
114
106
let r = b. try_into_range ( fields. len ( ) ) ?;
115
107
116
- let idx_start = fields[ r. start ] . start ;
117
- let idx_end = fields[ r. end - 1 ] . end ;
108
+ let idx_start = if r. start == 0 {
109
+ 0
110
+ } else {
111
+ fields[ r. start - 1 ] + 1
112
+ } ;
113
+ let idx_end = fields[ r. end - 1 ] ;
114
+
118
115
let output = & line[ idx_start..idx_end] ;
119
116
120
117
let field_to_print = output;
@@ -175,7 +172,7 @@ pub fn read_and_cut_text_as_bytes<R: BufRead, W: Write>(
175
172
stdout : & mut W ,
176
173
opt : & FastOpt ,
177
174
) -> Result < ( ) > {
178
- let mut fields: Vec < Range < usize > > = Vec :: with_capacity ( 16 ) ;
175
+ let mut fields: Vec < usize > = Vec :: with_capacity ( 16 ) ;
179
176
180
177
let last_interesting_field = opt. bounds . last_interesting_field ;
181
178
@@ -245,7 +242,7 @@ mod tests {
245
242
) ;
246
243
}
247
244
248
- fn make_cut_str_buffers ( ) -> ( Vec < u8 > , Vec < Range < usize > > ) {
245
+ fn make_cut_str_buffers ( ) -> ( Vec < u8 > , Vec < usize > ) {
249
246
let output = Vec :: new ( ) ;
250
247
let fields = Vec :: new ( ) ;
251
248
( output, fields)
@@ -451,6 +448,21 @@ mod tests {
451
448
452
449
#[ test]
453
450
fn cut_str_it_format_fields ( ) {
451
+ let opt = make_fields_opt ( "{2}" ) ;
452
+ let ( mut output, mut fields) = make_cut_str_buffers ( ) ;
453
+
454
+ let line = b"a-b-c" ;
455
+
456
+ cut_str_fast_lane (
457
+ line,
458
+ & opt,
459
+ & mut output,
460
+ & mut fields,
461
+ opt. bounds . last_interesting_field ,
462
+ )
463
+ . unwrap ( ) ;
464
+ assert_eq ! ( output. to_str_lossy( ) , b"b\n " . as_slice( ) . to_str_lossy( ) ) ;
465
+
454
466
let opt = make_fields_opt ( "{1} < {3} > {2}" ) ;
455
467
let ( mut output, mut fields) = make_cut_str_buffers ( ) ;
456
468
@@ -464,7 +476,10 @@ mod tests {
464
476
opt. bounds . last_interesting_field ,
465
477
)
466
478
. unwrap ( ) ;
467
- assert_eq ! ( output, b"a < c > b\n " . as_slice( ) ) ;
479
+ assert_eq ! (
480
+ output. to_str_lossy( ) ,
481
+ b"a < c > b\n " . as_slice( ) . to_str_lossy( )
482
+ ) ;
468
483
}
469
484
470
485
#[ test]
0 commit comments