use std::io::Write;
pub fn rev_bytes(data: &[u8], out: &mut impl Write) -> std::io::Result<()> {
if data.is_empty() {
return Ok(());
}
const FLUSH_THRESHOLD: usize = 256 * 1024;
let mut output = Vec::with_capacity(data.len().min(FLUSH_THRESHOLD * 2));
let mut start = 0;
for pos in memchr::memchr_iter(b'\n', data) {
let line = &data[start..pos];
reverse_line(line, &mut output);
output.push(b'\n');
start = pos + 1;
if output.len() >= FLUSH_THRESHOLD {
out.write_all(&output)?;
output.clear();
}
}
if start < data.len() {
let line = &data[start..];
reverse_line(line, &mut output);
}
if !output.is_empty() {
out.write_all(&output)?;
}
Ok(())
}
#[inline]
fn reverse_line(line: &[u8], output: &mut Vec<u8>) {
if line.is_empty() {
return;
}
if is_ascii(line) {
let start = output.len();
output.extend_from_slice(line);
output[start..].reverse();
} else {
match std::str::from_utf8(line) {
Ok(s) => {
output.reserve(line.len());
for ch in s.chars().rev() {
let mut buf = [0u8; 4];
let encoded = ch.encode_utf8(&mut buf);
output.extend_from_slice(encoded.as_bytes());
}
}
Err(_) => {
let start = output.len();
output.extend_from_slice(line);
output[start..].reverse();
}
}
}
}
#[inline]
fn is_ascii(data: &[u8]) -> bool {
let chunks = data.chunks_exact(8);
let remainder = chunks.remainder();
for chunk in chunks {
let word = u64::from_ne_bytes(chunk.try_into().unwrap());
if word & 0x8080808080808080 != 0 {
return false;
}
}
for &b in remainder {
if b & 0x80 != 0 {
return false;
}
}
true
}