1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;

#[cfg(not(feature = "std"))]
use core as std;

use bigint::BigUint;
use DecodeError;

pub(crate) trait Decoder<'a, 'b>
where
    <Self::Iter as Iterator>::Item: std::cmp::PartialEq + Copy,
{
    type Iter: std::iter::Iterator;

    fn iter(&'a str) -> Self::Iter;
    fn carry(&self, <Self::Iter as std::iter::Iterator>::Item) -> Option<u32>;
    fn alphabet<'c>(&self) -> &'c [<Self::Iter as std::iter::Iterator>::Item]
    where
        'b: 'c;
    fn decode(&self, input: &'a str) -> Result<Vec<u8>, DecodeError> {
        if input.is_empty() {
            return Ok(Vec::new());
        }
        let alpha = self.alphabet();
        let base = alpha.len() as u32;

        let mut big = BigUint::with_capacity(4);

        for c in Self::iter(input) {
            if let Some(carry) = self.carry(c) {
                big.mul_add(base, carry);
            } else {
                return Err(DecodeError);
            }
        }

        let mut bytes = big.into_bytes_be();

        let leader = alpha[0];

        let leaders = Self::iter(input).take_while(|byte| *byte == leader).count();

        for _ in 0..leaders {
            bytes.insert(0, 0);
        }

        Ok(bytes)
    }
}

pub(crate) struct U8Decoder<'b> {
    alphabet: &'b [u8],
    lookup: [u8; 256],
}

impl<'a> U8Decoder<'a> {
    #[inline]
    pub(crate) fn new(alphabet: &'a [u8]) -> Self {
        const INVALID_INDEX: u8 = 0xFF;
        let mut lookup = [INVALID_INDEX; 256];

        for (i, byte) in alphabet.iter().enumerate() {
            lookup[*byte as usize] = i as u8;
        }
        U8Decoder { alphabet, lookup }
    }
}

impl<'a, 'b> Decoder<'a, 'b> for U8Decoder<'b> {
    type Iter = std::str::Bytes<'a>;
    #[inline]
    fn iter(s: &'a str) -> Self::Iter {
        s.bytes()
    }
    #[inline]
    fn carry(&self, c: u8) -> Option<u32> {
        match self.lookup[c as usize] {
            0xFF => None,
            index => Some(index.into()),
        }
    }
    #[inline]
    fn alphabet<'c>(&self) -> &'c [u8]
    where
        'b: 'c,
    {
        self.alphabet
    }
}

pub(crate) struct CharDecoder<'b>(pub &'b [char]);

impl<'a, 'b> Decoder<'a, 'b> for CharDecoder<'b> {
    type Iter = std::str::Chars<'a>;

    #[inline]
    fn iter(s: &'a str) -> Self::Iter {
        s.chars()
    }
    #[inline]
    fn carry(&self, c: char) -> Option<u32> {
        self.0
            .iter()
            .enumerate()
            .find(|&(_, ch)| *ch == c)
            .map(|(i, _)| i as u32)
    }
    #[inline]
    fn alphabet<'c>(&self) -> &'c [char]
    where
        'b: 'c,
    {
        self.0
    }
}