From a433f8a919188af9394dec29cce2c7ba2be9533f Mon Sep 17 00:00:00 2001 From: Matt Kantor Date: Sun, 6 Dec 2020 13:36:07 -0800 Subject: [PATCH] Bugfix: `get` and `eval` subcommands could sometimes omit bytes. Bytes from the end of content streams could be missing from Operator's output. I'd somehow gotten it into my head that in `io::Write`, `write` + `flush` was the same as `write_all` (i.e. that non-written bytes were held in some internal buffer that got emptied upon `flush`). In hindsight this is silly, since `io::Write` is a trait there's not even anywhere to store such a buffer (individual `Write` impls could work this way in theory, but at least the one for `io::StdoutLock` doesn't). I hadn't noticed this problem until now because apparently `write` had been writing the entire buffer at once. Something must have changed in the GitHub Actions runners, though, as the issue was 100% reproducible for a certain sample in and all CI runs since that PR was opened. --- src/cli.rs | 10 ++-------- src/content/content_item.rs | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/cli.rs b/src/cli.rs index 07e3a1c..88a6e0c 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -112,10 +112,7 @@ pub fn eval( let media = content_item.render(render_context, &[mime::STAR_STAR])?; executor::block_on(media.content.try_for_each(|bytes| { - let result = match output.write(&bytes) { - Err(error) => Err(StreamError::from(error)), - Ok(_) => Ok(()), - }; + let result = output.write_all(&bytes).map_err(StreamError::from); async { result } }))?; @@ -152,10 +149,7 @@ pub fn get( let media = content_item.render(render_context, &[accept.unwrap_or(mime::STAR_STAR)])?; executor::block_on(media.content.try_for_each(|bytes| { - let result = match output.write(&bytes) { - Err(error) => Err(StreamError::from(error)), - Ok(_) => Ok(()), - }; + let result = output.write_all(&bytes).map_err(StreamError::from); async { result } }))?; diff --git a/src/content/content_item.rs b/src/content/content_item.rs index 3bfd3e1..90c9b82 100644 --- a/src/content/content_item.rs +++ b/src/content/content_item.rs @@ -251,7 +251,7 @@ mod tests { assert!(str::from_utf8(non_utf8_bytes).is_err()); let mut file = tempfile().expect("Failed to create temporary file"); - file.write(non_utf8_bytes) + file.write_all(non_utf8_bytes) .expect("Failed to write to temporary file"); let static_content = StaticContentItem { media_type: MediaType::from_media_range(mime::APPLICATION_OCTET_STREAM).unwrap(),