Move buffer management into parse match arms.

This commit is contained in:
Todd Mortimer 2021-04-07 21:18:17 -04:00
parent 584c9542d8
commit 692dcdd27e

View file

@ -136,7 +136,7 @@ impl<'a, T: Read + Write + 'a> Handle<'a, T> {
{ {
let mut v = Vec::new(); let mut v = Vec::new();
let result = loop { let result = loop {
let rest = match self.session.readline(&mut v) { match self.session.readline(&mut v) {
Err(Error::Io(ref e)) Err(Error::Io(ref e))
if e.kind() == io::ErrorKind::TimedOut if e.kind() == io::ErrorKind::TimedOut
|| e.kind() == io::ErrorKind::WouldBlock => || e.kind() == io::ErrorKind::WouldBlock =>
@ -150,25 +150,19 @@ impl<'a, T: Read + Write + 'a> Handle<'a, T> {
continue; continue;
} }
match parse_idle(&v) { match parse_idle(&v) {
// Something went wrong parsing.
(_rest, Some(Err(r))) => break Err(r), (_rest, Some(Err(r))) => break Err(r),
// Complete response. We expect rest to be empty.
(rest, Some(Ok(response))) => { (rest, Some(Ok(response))) => {
if !callback(response) { if !callback(response) {
break Ok(WaitOutcome::MailboxChanged); break Ok(WaitOutcome::MailboxChanged);
} }
rest
}
(rest, None) => rest,
}
}
Err(r) => break Err(r),
};
// Update remaining data with unparsed data if needed.
if rest.is_empty() { if rest.is_empty() {
v.clear(); v.clear();
} else { } else {
// Assert on partial parse in debug builds - we expect to always parse all // Assert on partial parse in debug builds - we expect
// or none of the input buffer. On release builds, we still do the right thing. // to always parse all or none of the input buffer.
// On release builds, we still do the right thing.
debug_assert!( debug_assert!(
rest.len() != v.len(), rest.len() != v.len(),
"Unexpected partial parse: input: {:?}, output: {:?}", "Unexpected partial parse: input: {:?}, output: {:?}",
@ -178,6 +172,13 @@ impl<'a, T: Read + Write + 'a> Handle<'a, T> {
let used = v.len() - rest.len(); let used = v.len() - rest.len();
v.drain(0..used); v.drain(0..used);
} }
}
// Incomplete parse - do nothing and read more.
(_rest, None) => (),
}
}
Err(r) => break Err(r),
};
}; };
// Reconnect on timeout if needed // Reconnect on timeout if needed