use std::borrow::Borrow;
use std::io::{Result, Write};
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub struct Printer {
quotes: Quotes,
}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum Quotes {
None,
Single,
Double,
}
impl Default for Quotes {
fn default() -> Self {
Self::None
}
}
pub fn println<I>(bytes: I)
where
I: IntoIterator,
I::Item: std::borrow::Borrow<u8>,
{
println!("{}", Printer::default().into_string(bytes));
}
impl Default for Printer {
fn default() -> Self {
Self {
quotes: Quotes::None,
}
}
}
impl Printer {
pub fn new() -> Self {
Self::default()
}
pub fn with_single_quotes() -> Self {
Self {
quotes: Quotes::Single,
}
}
pub fn with_double_quotes() -> Self {
Self {
quotes: Quotes::Double,
}
}
pub fn write_to<I, W>(&self, writer: &mut W, bytes: I) -> Result<()>
where
I: IntoIterator,
I::Item: Borrow<u8>,
W: Write,
{
writer.write_all(self.into_string(bytes).as_bytes())
}
pub fn into_string<I>(&self, bytes: I) -> String
where
I: IntoIterator,
I::Item: Borrow<u8>,
{
let mut output = String::new();
match self.quotes {
Quotes::None => (),
Quotes::Single => output.push('\''),
Quotes::Double => output.push('"'),
}
for byte_borrow in bytes.into_iter() {
let byte = *byte_borrow.borrow();
if byte.is_ascii_graphic() {
match self.quotes {
Quotes::Single if byte == b'\'' => output.push('\\'),
Quotes::Double if byte == b'"' => output.push('\\'),
_ if byte == b'\\' => output.push('\\'),
_ => (),
}
output.push(byte as char);
} else {
output.push_str(&format!("\\x{:02x}", byte));
}
}
match self.quotes {
Quotes::None => (),
Quotes::Single => output.push('\''),
Quotes::Double => output.push('"'),
}
output
}
}