use std::fmt::Write;
pub(crate) fn write_quoted<'a>(
f: &mut (impl Write + 'a),
literal: &str,
escape: bool,
) -> std::fmt::Result {
if !literal.contains('"') {
write!(f, "\"{literal}\"")
} else if escape && literal.contains('\'') {
write!(f, "\"")?;
for (i, chunk) in literal.split('"').enumerate() {
if i > 0 {
write!(f, ""{chunk}")?;
} else {
write!(f, "{chunk}")?;
}
}
write!(f, "\"")
} else {
write!(f, "'{literal}'")
}
}
pub(crate) fn write_escaped_char_data<'a>(
f: &mut (impl Write + 'a),
data: &str,
) -> std::fmt::Result {
let mut next = 0;
for (i, b) in data.bytes().enumerate() {
if matches!(b, b'\r' | b'"' | b'&' | b'\'' | b'<' | b'>') {
f.write_str(&data[next..i])?;
f.write_str("&#")?;
f.write_char((b / 10 + b'0') as char)?;
f.write_char((b % 10 + b'0') as char)?;
f.write_char(';')?;
next = i + 1;
}
}
if next < data.len() {
f.write_str(&data[next..])?;
}
Ok(())
}
pub(crate) fn write_escaped_att_value<'a>(
f: &mut (impl Write + 'a),
value: &str,
need_quote: bool,
quote: &mut Option<char>,
) -> std::fmt::Result {
let q = quote.unwrap_or_else(|| {
if !value.contains('"') {
'"'
} else {
'\''
}
});
if need_quote {
f.write_char(q)?;
}
let mut next = 0;
for (i, b) in value.bytes().enumerate() {
if matches!(b, b'\r' | b'&') || b == q as u8 {
f.write_str(&value[next..i])?;
f.write_str("&#")?;
f.write_char((b / 10 + b'0') as char)?;
f.write_char((b % 10 + b'0') as char)?;
f.write_char(';')?;
next = i + 1;
}
}
if next < value.len() {
f.write_str(&value[next..])?;
}
if need_quote {
f.write_char(q)?;
}
*quote = Some(q);
Ok(())
}