From: Ian Jackson Date: Tue, 1 Jun 2021 12:58:38 +0000 (+0100) Subject: utils: Provide CookedStdout, buffered and with die on flush fail X-Git-Tag: otter-0.7.0~153 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=bd1af9d9ddeb88ac0261e9ea07cf525e1bab8843;p=otter.git utils: Provide CookedStdout, buffered and with die on flush fail Signed-off-by: Ian Jackson --- diff --git a/src/utils.rs b/src/utils.rs index 4c239b34..d4533ef3 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -731,6 +731,30 @@ impl Write for SigPipeWriter { pub type RawStdout = SigPipeWriter; impl RawStdout { pub fn new() -> Self { SigPipeWriter(io::stdout()) } } +pub struct CookedStdout(pub BufWriter>); +impl CookedStdout { + pub fn new() -> Self { Self(BufWriter::new(RawStdout::new())) } + fn handle_err(e: io::Error) -> ! { + AE::from(e).context("write stdout").end_process(12); + } + fn must_flush(&mut self) { + self.0.flush().unwrap_or_else(|e| Self::handle_err(e)) + } +} +impl Write for CookedStdout { + #[throws(io::Error)] + fn write(&mut self, buf: &[u8]) -> usize { + let r = self.0.write(buf).unwrap_or_else(|e| Self::handle_err(e)); + if buf.contains(&b'\n') { self.flush()? } + r + } + #[throws(io::Error)] + fn flush(&mut self) { self.must_flush() } +} +impl Drop for CookedStdout { + fn drop(&mut self) { self.must_flush() } +} + #[throws(fmt::Error)] pub fn fmt_hex(f: &mut Formatter, buf: &[u8]) { for v in buf { write!(f, "{:02x}", v)?; }