use alloc::vec::Vec;
#[cfg(feature = "std")]
use std::io::{self, Write};
pub(crate) const HEX_DIGITS: [u8; 16] = *b"0123456789ABCDEF";
#[inline]
pub(crate) fn find_byte(text_bytes: &[u8], mut p: usize, byte: u8) -> usize {
const LO: u64 = 0x0101_0101_0101_0101;
const HI: u64 = 0x8080_8080_8080_8080;
if p < text_bytes.len() && text_bytes[p] == byte {
return p;
}
let pattern = LO * byte as u64;
while p + 8 <= text_bytes.len() {
let x = u64::from_ne_bytes(text_bytes[p..(p + 8)].try_into().unwrap()) ^ pattern;
if x.wrapping_sub(LO) & !x & HI != 0 {
break;
}
p += 8;
}
while p < text_bytes.len() && text_bytes[p] != byte {
p += 1;
}
p
}
#[inline]
pub(crate) fn find_less_than(text_bytes: &[u8], p: usize) -> usize {
find_byte(text_bytes, p, b'<')
}
#[inline]
pub(crate) fn write_hex_to_vec(e: u8, output: &mut Vec<u8>) {
output.reserve(6);
let length = output.len();
unsafe {
let p = output.as_mut_ptr().add(length);
p.write(b'&');
p.add(1).write(b'#');
p.add(2).write(b'x');
p.add(3).write(HEX_DIGITS[(e >> 4) as usize]);
p.add(4).write(HEX_DIGITS[(e & 0xF) as usize]);
p.add(5).write(b';');
output.set_len(length + 6);
}
}
#[cfg(feature = "std")]
#[inline]
pub(crate) fn write_hex_to_writer<W: Write + ?Sized>(
e: u8,
output: &mut W,
) -> Result<(), io::Error> {
let entity =
[b'&', b'#', b'x', HEX_DIGITS[(e >> 4) as usize], HEX_DIGITS[(e & 0xF) as usize], b';'];
output.write_all(&entity)
}
#[inline]
pub(crate) fn write_html_entity_to_vec(e: u8, output: &mut Vec<u8>) {
match e {
b'&' => output.extend_from_slice(b"&"),
b'<' => output.extend_from_slice(b"<"),
b'>' => output.extend_from_slice(b">"),
b'"' => output.extend_from_slice(b"""),
_ => write_hex_to_vec(e, output),
}
}
#[cfg(feature = "std")]
#[inline]
pub(crate) fn write_html_entity_to_writer<W: Write + ?Sized>(
e: u8,
output: &mut W,
) -> Result<(), io::Error> {
match e {
b'&' => output.write_all(b"&"),
b'<' => output.write_all(b"<"),
b'>' => output.write_all(b">"),
b'"' => output.write_all(b"""),
_ => write_hex_to_writer(e, output),
}
}
#[inline]
pub(crate) fn write_char_to_vec(c: char, output: &mut Vec<u8>) {
match c.len_utf8() {
1 => output.push(c as u8),
_ => {
let mut buffer = [0u8; 4];
output.extend_from_slice(c.encode_utf8(&mut buffer).as_bytes());
},
}
}
#[cfg(feature = "std")]
#[inline]
pub(crate) fn write_char_to_writer<W: Write + ?Sized>(
c: char,
output: &mut W,
) -> Result<(), io::Error> {
let mut buffer = [0u8; 4];
let length = c.encode_utf8(&mut buffer).len();
output.write_all(&buffer[..length])
}