diff --git a/decode/src/error.rs b/decode/src/error.rs index 60a0d25..f416a18 100644 --- a/decode/src/error.rs +++ b/decode/src/error.rs @@ -3,6 +3,7 @@ use csv; use framed; use serde_json; use std; +use std::io; #[derive(Debug, Error)] pub enum Error { @@ -16,6 +17,9 @@ pub enum Error { #[error(non_std)] Framed(framed::Error), + /// Error in library `std::io`. + Io(io::Error), + /// Error in library `serde_json`. SerdeJson(serde_json::Error), } diff --git a/decode/src/main.rs b/decode/src/main.rs index bfc7106..b5f3867 100644 --- a/decode/src/main.rs +++ b/decode/src/main.rs @@ -14,7 +14,7 @@ mod error; use error::{Error, Result}; use clap::Arg; -use std::io::{stdin, stdout}; +use std::io::{stdin, stdout, stderr, Write}; arg_enum! { #[derive(Debug, Eq, PartialEq)] @@ -58,18 +58,29 @@ fn try() -> Result<()> { }; loop { + // Note: Output is flushed after each line so output on stdout + // and messages on stderr are in sync. + let res = r.recv(); match res { Ok(v) => match out_fmt { - OutputFormat::Csv => csvw.as_mut() - .expect("Should've been initialized") - .serialize(&v)?, + OutputFormat::Csv => { + let csvw = csvw.as_mut() + .expect("Should've been initialized"); + csvw.serialize(&v)?; + csvw.flush()?; + } OutputFormat::Debug => println!("{:#?}", v), OutputFormat::Json => { serde_json::to_writer(stdout(), &v)?; println!(""); + stdout().flush()?; }, }, + Err(ref e) if e.is_corrupt_frame() => { + eprintln!("WARN: Corrupt frame, error: {:?}", e); + stderr().flush()?; + } Err(framed::Error::EofBeforeFrame) => return Ok(()), Err(e) => return Err(Error::from(e)), }; diff --git a/framed/src/error.rs b/framed/src/error.rs index c0aae13..25d0afd 100644 --- a/framed/src/error.rs +++ b/framed/src/error.rs @@ -40,6 +40,21 @@ pub enum Error { Ssmarshal(ssmarshal::Error), } +impl Error { + /// Returns true if the error represents a corrupted frame. Data + /// may have been lost but the decoder should decode the next + /// frame correctly. + pub fn is_corrupt_frame(&self) -> bool { + match *self { + Error::ChecksumError | + Error::CobsDecodeFailed | + Error::EofDuringFrame + => true, + _ => false, + } + } +} + #[cfg(feature = "use_std")] impl From for Error { fn from(e: io::Error) -> Error {