dd-lib 0.2.1

library functions for a clone of the unix coreutil dd
Documentation
//! Structs, enums, and error types for reporting success and failure.
use opts;
use std::{borrow::Cow, fmt, time::SystemTime};
/// A `Result<T, dd::Error>`
pub type Result<T> = std::result::Result<T, Error>;

#[derive(Debug, PartialEq, Eq, Clone)]
/// A successful output from [`dd`][super::dd]
pub enum Success {
    /// Normal operation reports the number of bytes copied.
    /// Corresponds to [`opts::Mode::Standard`]
    Bytes {
        /// bytes successfuly written
        bytes: usize,
        /// start time of operation
        start: SystemTime,
    },
    /// Unblock reports the number of fixed-sized records copied and the block
    /// size. Corresponds to [`opts::Mode::Unblock`]
    Unblock {
        /// number of blocks successfully written
        blocks: usize,
        /// block size (in bytes) of fixed-sized records
        block_size: usize,
        start: SystemTime,
    },
    /// [`opts::Mode::Block`]
    Block {
        /// number of newline or EOF-terminated lines
        lines: usize,
        /// lines truncated to `block_size`
        truncated: usize,
        /// lines padded with spaces to block_size
        padded: usize,
        /// block_size (in bytes)
        block_size: usize,
        /// system time at start of operation
        start: SystemTime,
    },
}
#[derive(Debug)]
/// An Error in operation of [`dd`][super::dd]
pub enum Error {
    /// An error while reading, writing, or converting. See [io][super::io].
    IO(std::io::Error),
    /// An user input error corresponding to an incorectly specified,
    /// unimplemented, or conflicting option.
    Opt(opts::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::IO(err) => write!(f, "io error: {}", err),
            Error::Opt(err) => write!(f, "command line argument error: {}", err),
        }
    }
}

impl From<std::io::Error> for Error {
    fn from(err: ::std::io::Error) -> Self { Error::IO(err) }
}
impl From<opts::Error> for Error {
    fn from(err: opts::Error) -> Self { Error::Opt(err) }
}
impl std::error::Error for Error {}
impl fmt::Display for Success {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Success::Bytes { bytes, start } => write!(f, "wrote {} bytes in {}", bytes, elapsed(start)),
            Success::Block {
                lines,
                truncated,
                padded,
                block_size,
                start,
            } => write!(
                f,
                concat!(
                    "Wrote {lines} lines of length {len} in {seconds}.\n",
                    "Padded {padded}/{len} lines\n",
                    "Truncated {truncated}/{len} lines\n"
                ),
                lines = lines,
                truncated = truncated,
                len = block_size,
                padded = padded,
                seconds = elapsed(start),
            ),
            Success::Unblock {
                blocks,
                block_size,
                start,
            } => write!(
                f,
                "wrote {} records of fixed size {} in {}",
                blocks,
                block_size,
                elapsed(start)
            ),
        }
    }
}

//// the elapsed time in seconds, with three decimal digits of precision
pub fn elapsed(start: &SystemTime) -> Cow<'static, str> {
    match start.elapsed() {
        Ok(elapsed) => Cow::Owned(format!("{}.{:03} seconds", elapsed.as_secs(), elapsed.subsec_millis())),
        _ => Cow::Borrowed("<error obtaining elapsed time>"),
    }
}