use super::*;
pub(super) fn sexpr_to_rd(atom: &str, md: bool, out: &mut String) {
let bytes = atom.as_bytes();
let mut i = 0;
render_sexpr(bytes, &mut i, md, false, out);
}
fn render_sexpr(bytes: &[u8], i: &mut usize, md: bool, verbatim: bool, out: &mut String) {
if bytes.get(*i) != Some(&b'(') {
return;
}
*i += 1; let head_start = *i;
while let Some(&c) = bytes.get(*i) {
if c == b' ' || c == b')' {
break;
}
*i += 1;
}
let head = &bytes[head_start..*i];
let is_leaf = matches!(head, b"TEXT" | b"RCODE" | b"VERB" | b"UNKNOWN");
let escape_percent = md;
if is_leaf {
skip_spaces(bytes, i);
if bytes.get(*i) == Some(&b'"') {
let text = read_quoted(bytes, i);
append_leaf_text(&text, escape_percent, verbatim, out);
}
while let Some(&c) = bytes.get(*i) {
*i += 1;
if c == b')' {
break;
}
}
return;
}
let is_grp = head == b"GRP";
let child_verbatim = verbatim
|| (!is_grp
&& is_fragile_for_md(
std::str::from_utf8(head)
.unwrap_or("")
.trim_start_matches('\\'),
));
if !is_grp {
out.push_str(std::str::from_utf8(head).unwrap_or(""));
}
loop {
skip_spaces(bytes, i);
match bytes.get(*i) {
None => break,
Some(&b')') => {
*i += 1;
break;
}
Some(_) => {
if is_grp {
render_sexpr(bytes, i, md, child_verbatim, out);
} else {
out.push('{');
render_sexpr(bytes, i, md, child_verbatim, out);
out.push('}');
}
}
}
}
}
fn skip_spaces(bytes: &[u8], i: &mut usize) {
while bytes.get(*i) == Some(&b' ') {
*i += 1;
}
}
pub(super) fn read_quoted(bytes: &[u8], i: &mut usize) -> String {
*i += 1; let mut out = String::new();
while let Some(&c) = bytes.get(*i) {
if c == b'\\' {
*i += 1;
match bytes.get(*i) {
Some(b'n') => out.push('\n'),
Some(&other) => out.push(other as char),
None => out.push('\\'),
}
*i += 1;
} else if c == b'"' {
*i += 1; break;
} else {
let start = *i;
*i += 1;
while bytes.get(*i).is_some_and(|b| b & 0xC0 == 0x80) {
*i += 1;
}
out.push_str(std::str::from_utf8(&bytes[start..*i]).unwrap_or(""));
}
}
out
}
pub(super) fn append_leaf_text(text: &str, escape_percent: bool, verbatim: bool, out: &mut String) {
if verbatim {
for c in text.chars() {
if !matches!(c, '{' | '}' | '\\' | '%') {
out.push(c);
}
}
} else if escape_percent {
for c in text.chars() {
if c == '%' {
out.push('\\');
}
out.push(c);
}
} else {
out.push_str(text);
}
}