qusql_parse/
byte_to_char.rs1use alloc::vec::Vec;
4
5pub struct ByteToChar<'a> {
11 bytes: &'a [u8],
12 cnt: Vec<u32>, }
14
15impl<'a> ByteToChar<'a> {
16 pub fn new(bytes: &'a [u8]) -> Self {
18 let mut cnt = Vec::new();
19 let mut char_count = 0;
20 for chunk in bytes.chunks(128) {
21 cnt.push(char_count);
22 char_count += chunk.iter().filter(|&&b| (b & 0xC0) != 0x80).count() as u32;
23 }
24 Self { bytes, cnt }
25 }
26
27 pub fn map(&self, byte_pos: usize) -> usize {
29 let block_index = byte_pos / 128;
30 let block_start_byte = block_index * 128;
31 let char_count_before_block = self.cnt.get(block_index).cloned().unwrap_or(0) as usize;
32 let char_count_in_block = self.bytes[block_start_byte..byte_pos]
33 .iter()
34 .filter(|&&b| (b & 0xC0) != 0x80)
35 .count();
36 char_count_before_block + char_count_in_block
37 }
38
39 pub fn map_span(&self, span: core::ops::Range<usize>) -> core::ops::Range<usize> {
41 self.map(span.start)..self.map(span.end)
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48
49 #[test]
50 fn test_byte_to_char() {
51 let s = "Hello, 世界!"; let b2c = ByteToChar::new(s.as_bytes());
53
54 assert_eq!(b2c.map(0), 0); assert_eq!(b2c.map(7), 7); assert_eq!(b2c.map(13), 9); assert_eq!(b2c.map(14), 10); assert_eq!(b2c.map_span(0..14), 0..10); let long_str = "a".repeat(200) + "世界"; let b2c_long = ByteToChar::new(long_str.as_bytes());
63 assert_eq!(b2c_long.map(0), 0); assert_eq!(b2c_long.map(199), 199); assert_eq!(b2c_long.map(200), 200); assert_eq!(b2c_long.map(206), 202); }
68}