Skip to content

Commit 80267c7

Browse files
committed
Store delimiter positions with usize in fast lane
1 parent c1a3852 commit 80267c7

File tree

1 file changed

+37
-22
lines changed

1 file changed

+37
-22
lines changed

src/fast_lane.rs

+37-22
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ use crate::options::{Opt, Trim, EOL};
33
use anyhow::Result;
44
use bstr::ByteSlice;
55
use std::convert::TryFrom;
6+
use std::io::Write;
67
use std::io::{self, BufRead};
7-
use std::{io::Write, ops::Range};
88

99
use bstr::io::BufReadExt;
1010

@@ -18,11 +18,12 @@ fn trim<'a>(buffer: &'a [u8], trim_kind: &Trim, delimiter: u8) -> &'a [u8] {
1818
}
1919
}
2020

21+
#[inline(always)]
2122
fn cut_str_fast_lane<W: Write>(
2223
initial_buffer: &[u8],
2324
opt: &FastOpt,
2425
stdout: &mut W,
25-
fields: &mut Vec<Range<usize>>,
26+
fields: &mut Vec<usize>,
2627
last_interesting_field: Side,
2728
) -> Result<()> {
2829
let mut buffer = initial_buffer;
@@ -40,19 +41,14 @@ fn cut_str_fast_lane<W: Write>(
4041

4142
let bounds = &opt.bounds;
4243

43-
let mut prev_field_start = 0;
44-
4544
let mut curr_field = 0;
4645

4746
fields.clear();
4847

4948
for i in memchr::memchr_iter(opt.delimiter, buffer) {
5049
curr_field += 1;
5150

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);
5652

5753
if Side::Some(curr_field) == last_interesting_field {
5854
// We have no use for any other fields in this line
@@ -65,20 +61,16 @@ fn cut_str_fast_lane<W: Write>(
6561
return Ok(());
6662
}
6763

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).
7164
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());
7668
}
7769

7870
let num_fields = fields.len();
7971

8072
match num_fields {
81-
1 if bounds.len() == 1 && fields[0].end == buffer.len() => {
73+
1 if bounds.len() == 1 && fields[0] == buffer.len() => {
8274
stdout.write_all(buffer)?;
8375
}
8476
_ => {
@@ -107,14 +99,19 @@ fn output_parts<W: Write>(
10799
// which parts to print
108100
b: &UserBounds,
109101
// where to find the parts inside `line`
110-
fields: &[Range<usize>],
102+
fields: &[usize],
111103
stdout: &mut W,
112104
opt: &FastOpt,
113105
) -> Result<()> {
114106
let r = b.try_into_range(fields.len())?;
115107

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+
118115
let output = &line[idx_start..idx_end];
119116

120117
let field_to_print = output;
@@ -175,7 +172,7 @@ pub fn read_and_cut_text_as_bytes<R: BufRead, W: Write>(
175172
stdout: &mut W,
176173
opt: &FastOpt,
177174
) -> Result<()> {
178-
let mut fields: Vec<Range<usize>> = Vec::with_capacity(16);
175+
let mut fields: Vec<usize> = Vec::with_capacity(16);
179176

180177
let last_interesting_field = opt.bounds.last_interesting_field;
181178

@@ -245,7 +242,7 @@ mod tests {
245242
);
246243
}
247244

248-
fn make_cut_str_buffers() -> (Vec<u8>, Vec<Range<usize>>) {
245+
fn make_cut_str_buffers() -> (Vec<u8>, Vec<usize>) {
249246
let output = Vec::new();
250247
let fields = Vec::new();
251248
(output, fields)
@@ -451,6 +448,21 @@ mod tests {
451448

452449
#[test]
453450
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+
454466
let opt = make_fields_opt("{1} < {3} > {2}");
455467
let (mut output, mut fields) = make_cut_str_buffers();
456468

@@ -464,7 +476,10 @@ mod tests {
464476
opt.bounds.last_interesting_field,
465477
)
466478
.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+
);
468483
}
469484

470485
#[test]

0 commit comments

Comments
 (0)