use std::io;
use crate::CliError;
pub(crate) fn escape_field(value: &str) -> String {
let mut escaped = String::new();
for character in value.chars() {
match character {
'\\' => escaped.push_str("\\\\"),
'\t' => escaped.push_str("\\t"),
'\n' => escaped.push_str("\\n"),
'\r' => escaped.push_str("\\r"),
character if character.is_control() => {
use std::fmt::Write as _;
let _ = write!(escaped, "\\u{{{:x}}}", character as u32);
}
character => escaped.push(character),
}
}
escaped
}
pub(crate) fn write_stdout(output: &str) -> Result<(), CliError> {
let stdout = io::stdout();
write_output(&mut stdout.lock(), output)
}
pub(crate) fn stream_stdout(
write: impl FnOnce(&mut dyn io::Write) -> io::Result<()>,
) -> Result<(), CliError> {
let stdout = io::stdout();
stream_output(&mut stdout.lock(), write)
}
fn stream_output(
output: &mut dyn io::Write,
write: impl FnOnce(&mut dyn io::Write) -> io::Result<()>,
) -> Result<(), CliError> {
match write(output) {
Ok(()) => Ok(()),
Err(error) if error.kind() == io::ErrorKind::BrokenPipe => Ok(()),
Err(error) => Err(CliError::Io(error)),
}
}
fn write_output(writer: &mut impl io::Write, output: &str) -> Result<(), CliError> {
match writer.write_all(output.as_bytes()) {
Ok(()) => Ok(()),
Err(error) if error.kind() == io::ErrorKind::BrokenPipe => Ok(()),
Err(error) => Err(CliError::Io(error)),
}
}
#[cfg(test)]
mod tests;