From 10a11c293eaeda41d694fc7c4a4b0353e9f907af Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 22 May 2022 14:15:56 -0600 Subject: [PATCH] fix stream position and term comparison bugs (#1472) --- src/machine/machine_state_impl.rs | 10 ++++++++-- src/machine/streams.rs | 23 ++++++++++++++++++----- src/parser/char_reader.rs | 10 +++++++++- 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index a2940ece..be7edd33 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -1546,7 +1546,10 @@ impl MachineState { } } else { self.pdl.clear(); - return Some(n1.chars().next().cmp(&Some(c2))); + return Some( + n1.chars().next().cmp(&Some(c2)) + .then(Ordering::Greater) + ); } } _ => { @@ -1564,7 +1567,10 @@ impl MachineState { } } else { self.pdl.clear(); - return Some(Some(c1).cmp(&n2.chars().next())); + return Some( + Some(c1).cmp(&n2.chars().next()) + .then(Ordering::Less) + ); } } (HeapCellValueTag::Char, c2) => { diff --git a/src/machine/streams.rs b/src/machine/streams.rs index 1a5ae76e..298c3441 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -139,6 +139,17 @@ impl Read for InputFileStream { } } +impl StreamLayout> { + #[inline] + fn position(&mut self) -> Option { + // stream is the internal CharReader. subtract + // its pending buffer length from position. + self.get_mut().file.seek(SeekFrom::Current(0)) + .map(|pos| pos - self.stream.rem_buf_len() as u64) + .ok() + } +} + #[derive(Debug)] pub struct OutputFileStream { file_name: Atom, @@ -813,8 +824,8 @@ impl Stream { pub(crate) fn position(&mut self) -> Option<(u64, usize)> { // returns lines_read, position. let result = match self { - Stream::InputFile(ref mut file_stream) => { - file_stream.get_mut().file.seek(SeekFrom::Current(0)).ok() + Stream::InputFile(file_stream) => { + file_stream.position() } Stream::NamedTcp(..) | Stream::NamedTls(..) @@ -838,6 +849,7 @@ impl Stream { } = &mut **stream_layout; stream.get_mut().file.seek(SeekFrom::Start(position)).unwrap(); + stream.reset_buffer(); // flush the internal buffer. if let Ok(metadata) = stream.get_ref().file.metadata() { *past_end_of_stream = position > metadata.len(); @@ -853,7 +865,6 @@ impl Stream { Stream::Byte(stream) => stream.past_end_of_stream, Stream::InputFile(stream) => stream.past_end_of_stream, Stream::OutputFile(stream) => stream.past_end_of_stream, - // Stream::PausedProlog(stream) => stream.paused_stream.past_end_of_stream(), Stream::StaticString(stream) => stream.past_end_of_stream, Stream::NamedTcp(stream) => stream.past_end_of_stream, Stream::NamedTls(stream) => stream.past_end_of_stream, @@ -894,6 +905,8 @@ impl Stream { } if let Stream::InputFile(stream_layout) = self { + let position = stream_layout.position(); + let StreamLayout { past_end_of_stream, stream, @@ -902,7 +915,7 @@ impl Stream { match stream.get_ref().file.metadata() { Ok(metadata) => { - if let Ok(position) = stream.get_mut().file.seek(SeekFrom::Current(0)) { + if let Some(position) = position { return match position.cmp(&metadata.len()) { Ordering::Equal => AtEndOfStream::At, Ordering::Less => AtEndOfStream::Not, @@ -1057,7 +1070,7 @@ impl Stream { http_stream.set_tag(ArenaHeaderTag::Dropped); std::ptr::drop_in_place(&mut http_stream.inner_mut().body_reader as *mut _); } - + Ok(()) } Stream::InputFile(mut file_stream) => { diff --git a/src/parser/char_reader.rs b/src/parser/char_reader.rs index dc4d277d..dddabb19 100644 --- a/src/parser/char_reader.rs +++ b/src/parser/char_reader.rs @@ -61,6 +61,14 @@ impl CharReader { pub fn inner_mut(&mut self) -> &mut R { &mut self.inner } + + // Return the number of bytes remaining to be read. Useful for, + // e.g., determining the position relative to the end of the + // owning stream. + #[inline] + pub fn rem_buf_len(&self) -> usize { + self.buf.len() - self.pos + } } pub trait CharRead { @@ -96,7 +104,7 @@ impl CharReader { self.inner } - fn reset_buffer(&mut self) { + pub fn reset_buffer(&mut self) { self.buf.clear(); self.pos = 0; } -- 2.54.0