base_x/
decoder.rs

1#[cfg(not(feature = "std"))]
2use alloc::vec::Vec;
3
4#[cfg(not(feature = "std"))]
5use core as std;
6
7use bigint::BigUint;
8use DecodeError;
9
10pub(crate) trait Decoder<'a, 'b>
11where
12    <Self::Iter as Iterator>::Item: std::cmp::PartialEq + Copy,
13{
14    type Iter: std::iter::Iterator;
15
16    fn iter(_: &'a str) -> Self::Iter;
17    fn carry(&self, _: <Self::Iter as std::iter::Iterator>::Item) -> Option<u32>;
18    fn alphabet<'c>(&self) -> &'c [<Self::Iter as std::iter::Iterator>::Item]
19    where
20        'b: 'c;
21    fn decode(&self, input: &'a str) -> Result<Vec<u8>, DecodeError> {
22        if input.is_empty() {
23            return Ok(Vec::new());
24        }
25        let alpha = self.alphabet();
26        let base = alpha.len() as u32;
27
28        let mut big = BigUint::with_capacity(4);
29
30        for c in Self::iter(input) {
31            if let Some(carry) = self.carry(c) {
32                big.mul_add(base, carry);
33            } else {
34                return Err(DecodeError);
35            }
36        }
37
38        let mut bytes = big.into_bytes_be();
39
40        let leader = alpha[0];
41
42        let leaders = Self::iter(input).take_while(|byte| *byte == leader).count();
43
44        for _ in 0..leaders {
45            bytes.insert(0, 0);
46        }
47
48        Ok(bytes)
49    }
50}
51
52pub(crate) struct U8Decoder<'b> {
53    alphabet: &'b [u8],
54    lookup: [u8; 256],
55}
56
57impl<'a> U8Decoder<'a> {
58    #[inline]
59    pub(crate) fn new(alphabet: &'a [u8]) -> Self {
60        const INVALID_INDEX: u8 = 0xFF;
61        let mut lookup = [INVALID_INDEX; 256];
62
63        for (i, byte) in alphabet.iter().enumerate() {
64            lookup[*byte as usize] = i as u8;
65        }
66        U8Decoder { alphabet, lookup }
67    }
68}
69
70impl<'a, 'b> Decoder<'a, 'b> for U8Decoder<'b> {
71    type Iter = std::str::Bytes<'a>;
72    #[inline]
73    fn iter(s: &'a str) -> Self::Iter {
74        s.bytes()
75    }
76    #[inline]
77    fn carry(&self, c: u8) -> Option<u32> {
78        match self.lookup[c as usize] {
79            0xFF => None,
80            index => Some(index.into()),
81        }
82    }
83    #[inline]
84    fn alphabet<'c>(&self) -> &'c [u8]
85    where
86        'b: 'c,
87    {
88        self.alphabet
89    }
90}
91
92pub(crate) struct CharDecoder<'b>(pub &'b [char]);
93
94impl<'a, 'b> Decoder<'a, 'b> for CharDecoder<'b> {
95    type Iter = std::str::Chars<'a>;
96
97    #[inline]
98    fn iter(s: &'a str) -> Self::Iter {
99        s.chars()
100    }
101    #[inline]
102    fn carry(&self, c: char) -> Option<u32> {
103        self.0
104            .iter()
105            .enumerate()
106            .find(|&(_, ch)| *ch == c)
107            .map(|(i, _)| i as u32)
108    }
109    #[inline]
110    fn alphabet<'c>(&self) -> &'c [char]
111    where
112        'b: 'c,
113    {
114        self.0
115    }
116}