Skip to content

Commit 945cf5b

Browse files
committed
Ensure that fast lane works with negative indices too
1 parent cc4f646 commit 945cf5b

File tree

2 files changed

+71
-8
lines changed

2 files changed

+71
-8
lines changed

src/bounds.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ impl UserBoundsList {
117117
/// Detect whether the list can be sorted.
118118
/// It can be sorted only if every bound
119119
/// has the same sign (all positive or all negative).
120-
fn is_sortable(&self) -> bool {
120+
pub fn is_sortable(&self) -> bool {
121121
let mut has_positive_idx = false;
122122
let mut has_negative_idx = false;
123123
self.get_userbounds_only().for_each(|b| {

src/fast_lane.rs

+70-7
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ fn cut_str_fast_lane<W: Write>(
8080
let num_fields = fields.len();
8181

8282
match num_fields {
83-
1 if bounds.len() == 1 => {
83+
1 if bounds.len() == 1 && fields[0].end == buffer.len() => {
8484
stdout.write_all(buffer)?;
8585
}
8686
_ => {
@@ -213,13 +213,15 @@ impl TryFrom<&UserBoundsList> for ForwardBounds {
213213
let value: UserBoundsList = UserBoundsList(value.iter().cloned().collect());
214214

215215
let mut rightmost_bound: Option<Side> = None;
216-
value.iter().for_each(|bof| {
217-
if let BoundOrFiller::Bound(b) = bof {
218-
if rightmost_bound.is_none() || b.r > rightmost_bound.unwrap() {
219-
rightmost_bound = Some(b.r);
216+
if value.is_sortable() {
217+
value.iter().for_each(|bof| {
218+
if let BoundOrFiller::Bound(b) = bof {
219+
if rightmost_bound.is_none() || b.r > rightmost_bound.unwrap() {
220+
rightmost_bound = Some(b.r);
221+
}
220222
}
221-
}
222-
});
223+
});
224+
}
223225

224226
Ok(ForwardBounds {
225227
list: value,
@@ -394,6 +396,67 @@ mod tests {
394396
assert_eq!(output, b"a\n".as_slice());
395397
}
396398

399+
#[test]
400+
fn cut_str_it_cut_with_negative_indices() {
401+
let mut opt = make_fields_opt();
402+
403+
let line = b"a-b-c";
404+
405+
// just one negative index
406+
opt.bounds = ForwardBounds::from_str("-1").unwrap();
407+
let (mut output, mut fields) = make_cut_str_buffers();
408+
cut_str_fast_lane(
409+
line,
410+
&opt,
411+
&mut output,
412+
&mut fields,
413+
opt.bounds.get_last_bound(),
414+
)
415+
.unwrap();
416+
assert_eq!(output, b"c\n".as_slice());
417+
418+
// multiple negative indices, in forward order
419+
opt.bounds = ForwardBounds::from_str("-2,-1").unwrap();
420+
let (mut output, mut fields) = make_cut_str_buffers();
421+
cut_str_fast_lane(
422+
line,
423+
&opt,
424+
&mut output,
425+
&mut fields,
426+
opt.bounds.get_last_bound(),
427+
)
428+
.unwrap();
429+
assert_eq!(output, b"bc\n".as_slice());
430+
431+
// multiple negative indices, in non-forward order
432+
opt.bounds = ForwardBounds::from_str("-1,-2").unwrap();
433+
let (mut output, mut fields) = make_cut_str_buffers();
434+
cut_str_fast_lane(
435+
line,
436+
&opt,
437+
&mut output,
438+
&mut fields,
439+
opt.bounds.get_last_bound(),
440+
)
441+
.unwrap();
442+
assert_eq!(output, b"cb\n".as_slice());
443+
444+
// mix positive and negative indices
445+
// (this is particularly useful to verify that we don't screw
446+
// up optimizations on last field to check)
447+
opt.bounds = ForwardBounds::from_str("-1,1").unwrap();
448+
let (mut output, mut fields) = make_cut_str_buffers();
449+
cut_str_fast_lane(
450+
line,
451+
&opt,
452+
&mut output,
453+
&mut fields,
454+
opt.bounds.get_last_bound(),
455+
)
456+
.unwrap();
457+
assert_eq!(output, b"ca\n".as_slice());
458+
}
459+
397460
#[test]
398461
fn cut_str_it_cut_consecutive_delimiters() {
399462
let mut opt = make_fields_opt();

0 commit comments

Comments
 (0)