base_any/
table.rs

1use crate::{Decode, Encode};
2
3/// 编码方案
4pub struct Table<'a> {
5    /// 每个字符对应的位数
6    pub bits: u32,
7    /// 结尾字符集
8    pub fini: &'a [char],
9    /// 正文字符集
10    pub init: &'a [char],
11    decode: [&'a [(u16, u16)]; 17],
12}
13
14impl<'a> Table<'a> {
15    pub(crate) fn decode(&self, ch: char) -> Option<(u32, bool)> {
16        let plane = self.decode[ch as usize >> 16];
17        let idx = plane.binary_search_by_key(&(ch as u16), |&x| x.0);
18        let code = plane[idx.ok()?].1 as u32;
19        Some((code & ((1 << 15) - 1), code >> 15 != 0))
20    }
21
22    /// 编码为迭代器
23    pub fn encode_iter<I>(&'a self, iter: I) -> Encode<'a, I::IntoIter>
24    where
25        I: IntoIterator<Item = u8>,
26    {
27        Encode::new(self, iter.into_iter())
28    }
29
30    /// 解码为迭代器
31    ///
32    /// 若输入有错误字符,则输出该字符的错误。
33    pub fn decode_iter<I>(&'a self, iter: I) -> Decode<'a, I::IntoIter>
34    where
35        I: IntoIterator<Item = char>,
36    {
37        Decode::new(self, iter.into_iter())
38    }
39}
40
41#[cfg(any(feature = "std", test))]
42impl Table<'_> {
43    /// 编码为字符串
44    pub fn encode_str<I>(&self, iter: I) -> String
45    where
46        I: IntoIterator<Item = u8>,
47    {
48        self.encode_iter(iter).collect()
49    }
50
51    /// 解码为数组
52    ///
53    /// 若输入有错误字符,则返回该字符的错误。
54    pub fn decode_vec<I>(&self, iter: I) -> Result<Vec<u8>, char>
55    where
56        I: IntoIterator<Item = char>,
57    {
58        self.decode_iter(iter).collect()
59    }
60}
61
62#[cfg(test)]
63impl Table<'_> {
64    pub(crate) fn with<T>(bits: u32, f: impl FnOnce(&Table) -> T) -> T {
65        let fin_len = if bits > 8 { 1 << (bits - 8) } else { 0 };
66        let chs: Vec<_> = ('\0'..).take(fin_len + (1 << bits)).collect();
67        let mut decode = std::iter::zip(
68            chs.iter().map(|&c| c as u16),
69            (0..fin_len as u16).map(|x| x | (1 << 15)).chain(0..),
70        );
71        let decode = std::array::from_fn(|_| decode.by_ref().take(65536).collect());
72        f(&Table {
73            bits,
74            fini: &chs[..fin_len],
75            init: &chs[fin_len..],
76            decode: decode.each_ref().map(|a: &Vec<_>| &**a),
77        })
78    }
79}
80
81/// 自动生成的编码方案
82#[allow(warnings)]
83pub mod tables {
84    use super::*;
85    include!(concat!(env!("OUT_DIR"), "/table.rs"));
86}