use std::env;
use std::ffi::OsStr;
use std::fmt;
use std::fs::File;
use std::io::{self, BufWriter, Stdout, StdoutLock, Write as IoWrite};
#[cfg(unix)]
use std::os::unix::ffi::OsStrExt;
#[cfg(target_os = "wasi")]
use std::os::wasi::ffi::OsStrExt;
pub use os_display::{Quotable, Quoted};
pub fn println_verbatim<S: AsRef<OsStr>>(text: S) -> io::Result<()> {
let mut stdout = io::stdout().lock();
stdout.write_all_os(text.as_ref())?;
stdout.write_all(b"\n")?;
Ok(())
}
pub fn print_verbatim<S: AsRef<OsStr>>(text: S) -> io::Result<()> {
io::stdout().write_all_os(text.as_ref())
}
pub trait OsWrite: io::Write {
fn write_all_os(&mut self, buf: &OsStr) -> io::Result<()> {
#[cfg(any(unix, target_os = "wasi"))]
{
self.write_all(buf.as_bytes())
}
#[cfg(not(any(unix, target_os = "wasi")))]
{
match buf.to_str() {
Some(text) => self.write_all(text.as_bytes()),
None => Err(io::Error::new(
io::ErrorKind::InvalidData,
"OS string cannot be converted to bytes",
)),
}
}
}
}
impl OsWrite for File {}
impl OsWrite for Stdout {}
impl OsWrite for StdoutLock<'_> {}
impl<W: OsWrite> OsWrite for BufWriter<W> {}
impl OsWrite for Box<dyn OsWrite> {
fn write_all_os(&mut self, buf: &OsStr) -> io::Result<()> {
let this: &mut dyn OsWrite = self;
this.write_all_os(buf)
}
}
pub fn print_all_env_vars<T: fmt::Display>(line_ending: T) -> io::Result<()> {
let mut stdout = io::stdout().lock();
for (name, value) in env::vars_os() {
stdout.write_all_os(&name)?;
stdout.write_all(b"=")?;
stdout.write_all_os(&value)?;
write!(stdout, "{line_ending}")?;
}
Ok(())
}