1use std::io::Write;
2
3pub fn rev_bytes(data: &[u8], out: &mut impl Write) -> std::io::Result<()> {
8 if data.is_empty() {
9 return Ok(());
10 }
11
12 let mut output = Vec::with_capacity(data.len());
14 let mut start = 0;
15
16 for pos in memchr::memchr_iter(b'\n', data) {
17 let line = &data[start..pos];
18 reverse_line(line, &mut output);
19 output.push(b'\n');
20 start = pos + 1;
21 }
22
23 if start < data.len() {
25 let line = &data[start..];
26 reverse_line(line, &mut output);
27 }
28
29 out.write_all(&output)
30}
31
32#[inline]
35fn reverse_line(line: &[u8], output: &mut Vec<u8>) {
36 if line.is_empty() {
37 return;
38 }
39
40 if is_ascii(line) {
42 let start = output.len();
44 output.extend_from_slice(line);
45 output[start..].reverse();
46 } else {
47 match std::str::from_utf8(line) {
50 Ok(s) => {
51 let chars: Vec<char> = s.chars().rev().collect();
53 for ch in chars {
54 let mut buf = [0u8; 4];
55 let encoded = ch.encode_utf8(&mut buf);
56 output.extend_from_slice(encoded.as_bytes());
57 }
58 }
59 Err(_) => {
60 let start = output.len();
62 output.extend_from_slice(line);
63 output[start..].reverse();
64 }
65 }
66 }
67}
68
69#[inline]
72fn is_ascii(data: &[u8]) -> bool {
73 let chunks = data.chunks_exact(8);
75 let remainder = chunks.remainder();
76
77 for chunk in chunks {
78 let word = u64::from_ne_bytes(chunk.try_into().unwrap());
79 if word & 0x8080808080808080 != 0 {
80 return false;
81 }
82 }
83
84 for &b in remainder {
85 if b & 0x80 != 0 {
86 return false;
87 }
88 }
89
90 true
91}