use std::io::{self, Write};
pub(crate) mod text;
pub(crate) struct BrokenPipeWriter<W>(W);
impl<W: Write> BrokenPipeWriter<W> {
pub(crate) fn new(inner: W) -> Self {
Self(inner)
}
}
fn exit_on_broken_pipe<T>(result: io::Result<T>) -> io::Result<T> {
if let Err(ref e) = result
&& e.kind() == io::ErrorKind::BrokenPipe
{
std::process::exit(0);
}
result
}
impl<W: Write> Write for BrokenPipeWriter<W> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
exit_on_broken_pipe(self.0.write(buf))
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
exit_on_broken_pipe(self.0.write_all(buf))
}
fn flush(&mut self) -> io::Result<()> {
exit_on_broken_pipe(self.0.flush())
}
}
pub(crate) const USER_AGENT: &str = concat!("dsp-cli/", env!("CARGO_PKG_VERSION"));
pub(crate) const DSP_CLIENT_HEADER: &str = concat!("dsp-cli/", env!("CARGO_PKG_VERSION"));
pub(crate) fn warn_auth_cache_load_failed(e: &impl std::fmt::Display, fallback: &str) {
tracing::debug!(error = %e, "auth cache load failed");
tracing::warn!("auth cache load failed; {fallback}");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn user_agent_has_expected_prefix() {
assert!(USER_AGENT.starts_with("dsp-cli/"));
}
#[test]
fn user_agent_is_plain_form_no_suffix() {
assert_eq!(USER_AGENT, concat!("dsp-cli/", env!("CARGO_PKG_VERSION")));
}
#[test]
fn dsp_client_header_has_expected_prefix() {
assert!(DSP_CLIENT_HEADER.starts_with("dsp-cli/"));
}
#[test]
fn broken_pipe_writer_passes_through_normal_writes() {
let mut w = BrokenPipeWriter::new(Vec::<u8>::new());
w.write_all(b"hello").unwrap();
w.flush().unwrap();
assert_eq!(w.0, b"hello");
}
#[test]
fn broken_pipe_writer_passes_through_non_broken_pipe_errors_unchanged() {
struct FailingWriter;
impl Write for FailingWriter {
fn write(&mut self, _buf: &[u8]) -> io::Result<usize> {
Err(io::Error::new(io::ErrorKind::NotFound, "boom"))
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
let mut w = BrokenPipeWriter::new(FailingWriter);
let err = w.write(b"x").unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::NotFound);
}
}