Skip to content

Commit 642e718

Browse files
committed
Make exp_any return the earliest result
Previously, exp_any would return the match with the lowest index in the list. So this: exp_any(&vec![ReadUntil::String("hello"), ReadUntil::String("hell")] With the input from the process as "hello", will sometimes return "hell", and sometimes "hello". Depending on how much the readbuffer happened to have collected. With this change, the earliest match in the input will be matched. That way, any difference in how much the read buffer has currently consumed does not change the output of the exp_any function. Signed-off-by: Erik Karlsson <[email protected]>
1 parent 2576e1f commit 642e718

File tree

2 files changed

+47
-10
lines changed

2 files changed

+47
-10
lines changed

src/reader.rs

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,18 @@ pub fn find(needle: &ReadUntil, buffer: &str, eof: bool) -> Option<(usize, usize
8383
None
8484
}
8585
}
86-
ReadUntil::Any(ref any) => {
87-
for read_until in any {
88-
if let Some(pos_tuple) = find(read_until, buffer, eof) {
89-
return Some(pos_tuple);
86+
ReadUntil::Any(ref anys) => anys
87+
.iter()
88+
// Filter matching needles
89+
.filter_map(|any| find(any, buffer, eof))
90+
// Return the left-most match
91+
.min_by(|(start1, end1), (start2, end2)| {
92+
if start1 == start2 {
93+
end1.cmp(end2)
94+
} else {
95+
start1.cmp(start2)
9096
}
91-
}
92-
None
93-
}
97+
}),
9498
}
9599
}
96100

@@ -304,8 +308,11 @@ mod tests {
304308
let f = io::Cursor::new("2014-03-15");
305309
let mut r = NBReader::new(f, None);
306310
let re = Regex::new(r"^\d{4}-\d{2}-\d{2}$").unwrap();
307-
r.read_until(&ReadUntil::Regex(re))
308-
.expect("regex doesn't match");
311+
assert_eq!(
312+
("".to_string(), "2014-03-15".to_string()),
313+
r.read_until(&ReadUntil::Regex(re))
314+
.expect("regex doesn't match")
315+
);
309316
}
310317

311318
#[test]
@@ -338,6 +345,36 @@ mod tests {
338345
);
339346
}
340347

348+
#[test]
349+
fn test_any_with_multiple_possible_matches() {
350+
let f = io::Cursor::new("zero one two three four five");
351+
let mut r = NBReader::new(f, None);
352+
353+
let result = r
354+
.read_until(&ReadUntil::Any(vec![
355+
ReadUntil::String("two".to_string()),
356+
ReadUntil::String("one".to_string()),
357+
]))
358+
.expect("finding string");
359+
360+
assert_eq!(("zero ".to_string(), "one".to_string()), result);
361+
}
362+
363+
#[test]
364+
fn test_any_with_same_start_different_length() {
365+
let f = io::Cursor::new("hi hello");
366+
let mut r = NBReader::new(f, None);
367+
368+
let result = r
369+
.read_until(&ReadUntil::Any(vec![
370+
ReadUntil::String("hello".to_string()),
371+
ReadUntil::String("hell".to_string()),
372+
]))
373+
.expect("finding string");
374+
375+
assert_eq!(("hi ".to_string(), "hell".to_string()), result);
376+
}
377+
341378
#[test]
342379
fn test_eof() {
343380
let f = io::Cursor::new("lorem ipsum dolor sit amet");

src/session.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ mod tests {
515515
ReadUntil::NBytes(3),
516516
ReadUntil::String("Hi".to_string()),
517517
]) {
518-
Ok(s) => assert_eq!(("".to_string(), "Hi\r".to_string()), s),
518+
Ok(s) => assert_eq!(("".to_string(), "Hi".to_string()), s),
519519
Err(e) => panic!("got error: {}", e),
520520
}
521521
Ok(())

0 commit comments

Comments
 (0)