use std::io::{self, Write};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum OutputStatus {
Written,
BrokenPipe,
}
fn map_result(result: io::Result<()>) -> io::Result<OutputStatus> {
match result {
Ok(()) => Ok(OutputStatus::Written),
Err(error) if error.kind() == io::ErrorKind::BrokenPipe => Ok(OutputStatus::BrokenPipe),
Err(error) => Err(error),
}
}
pub(crate) fn stdout_bytes(bytes: &[u8]) -> io::Result<OutputStatus> {
let stdout = io::stdout();
let mut handle = stdout.lock();
map_result(handle.write_all(bytes).and_then(|_| handle.flush()))
}
pub(crate) fn stdout_line(text: &str) -> io::Result<OutputStatus> {
let stdout = io::stdout();
let mut handle = stdout.lock();
map_result(
handle
.write_all(text.as_bytes())
.and_then(|_| handle.write_all(b"\n"))
.and_then(|_| handle.flush()),
)
}
pub(crate) fn stderr_line(text: &str) -> io::Result<OutputStatus> {
let stderr = io::stderr();
let mut handle = stderr.lock();
map_result(
handle
.write_all(text.as_bytes())
.and_then(|_| handle.write_all(b"\n"))
.and_then(|_| handle.flush()),
)
}
#[cfg(test)]
mod tests {
use super::{map_result, OutputStatus};
use std::io;
#[test]
fn map_result_maps_written_broken_pipe_and_other_errors() {
assert_eq!(map_result(Ok(())).unwrap(), OutputStatus::Written);
assert_eq!(
map_result(Err(io::Error::from(io::ErrorKind::BrokenPipe))).unwrap(),
OutputStatus::BrokenPipe
);
let error = map_result(Err(io::Error::from(io::ErrorKind::PermissionDenied))).unwrap_err();
assert_eq!(error.kind(), io::ErrorKind::PermissionDenied);
}
}