use super::util::{
lazy_decoded_prefix, resolve_escaped_codepoint, simple_control_escape, take_hex_digits_indexed,
};
pub(super) fn unicode_escape_decode(input: &str) -> Result<String, ()> {
let mut decoded_text: Option<String> = None;
let mut chars = input.char_indices().peekable();
while let Some((idx, ch)) = chars.next() {
if ch != '\\' {
if let Some(decoded_text) = decoded_text.as_mut() {
decoded_text.push(ch);
}
continue;
}
match chars.next().map(|(_, escaped)| escaped) {
Some('u') => {
let code = take_hex_digits_indexed(&mut chars, 4)?;
let resolved =
resolve_escaped_codepoint(code, &mut chars.by_ref().map(|(_, c)| c))?;
lazy_decoded_prefix(&mut decoded_text, input, idx).push(resolved);
}
Some('x') => {
let code = take_hex_digits_indexed(&mut chars, 2)?;
lazy_decoded_prefix(&mut decoded_text, input, idx)
.push(char::from_u32(code).ok_or(())?);
}
Some(escaped) => {
let decoded = match simple_control_escape(escaped) {
Some(control) => control,
None => escaped,
};
lazy_decoded_prefix(&mut decoded_text, input, idx).push(decoded);
}
None => return Err(()),
}
}
decoded_text.ok_or(())
}