codex_percent/decode/
fixed.rs

1//! Decode impl - Fixed size array output
2
3use super::*;
4use crate::{DecoderError, FixedDecoder as Decoder};
5
6impl<'i, const S: usize> Decoder<'i, S> {
7    /// Init decoder
8    pub fn init() -> Self {
9        let cur: [u8; S] = [0; S];
10        Self {
11            cur_block: cur,
12            cur_raw: None,
13        }
14    }
15    /// Current block output
16    pub fn cur_block(&self) -> &[u8; S] {
17        &self.cur_block
18    }
19    /// Current raw input
20    pub fn cur_raw(&self) -> Option<&str> {
21        self.cur_raw
22    }
23    /// Decode and return resulting decoded size
24    /// *Panic*
25    /// This will panic if the output would go out of bounds
26    pub fn decode(&mut self, raw: &'i str) -> Result<usize, DecoderError> {
27        let mut cur_i = 0;
28        self.cur_raw = Some(raw);
29
30        let mut lexer = DecodeToken::lexer(raw);
31        while let Some(token) = lexer.next() {
32            match token {
33                Ok(DecodeToken::MaybePercent2Hex(pairs)) => {
34                    let mut chunks = pairs.as_bytes().chunks(3);
35                    while let Some(block) = chunks.next() {
36                        let pair: [u8; 2] = [block[1], block[2]];
37                        let byte_out = hex2byte(pair)?;
38                        self.cur_block[cur_i] = byte_out;
39                        cur_i = cur_i + 1;
40                    }
41                }
42                Ok(DecodeToken::EverythingElse(alphanum)) => {
43                    let needed = alphanum.as_bytes().len();
44                    let fill_to = cur_i + needed;
45                    self.cur_block[cur_i..fill_to].copy_from_slice(&alphanum.as_bytes()[0..needed]);
46                    cur_i += needed;
47                }
48                _ => {
49                    return Err(DecoderError::BorkedExperimental(lexer.span().start));
50                }
51            }
52        }
53        Ok(cur_i)
54    }
55}
56
57#[cfg(test)]
58mod test {
59    use super::*;
60
61    #[test]
62    fn f_10_direct_copy() {
63        let s = "1234567890";
64        let expected: [u8; 10] = [49, 50, 51, 52, 53, 54, 55, 56, 57, 48];
65
66        let mut d = Decoder::<10>::init();
67        let c = d.decode(s).unwrap();
68        let utf8 = core::str::from_utf8(d.cur_block());
69
70        assert_eq!(c, 10);
71        assert_eq!(d.cur_block(), &expected);
72        assert_eq!(utf8, Ok(s));
73    }
74
75    #[test]
76    fn f_10_poop() {
77        let poop_str = "%F0%9F%92%A9";
78        let expected: [u8; 4] = [240, 159, 146, 169];
79        let expected_utf8 = "💩";
80
81        let mut d = Decoder::<4>::init();
82        let c = d.decode(poop_str).unwrap();
83        let utf8 = core::str::from_utf8(d.cur_block());
84
85        assert_eq!(c, 4);
86        assert_eq!(d.cur_block(), &expected);
87        assert_eq!(utf8, Ok(expected_utf8));
88    }
89
90    #[test]
91    fn f_10_spaces() {
92        let poop_str = "%20%20%20%20%20%20%20%20%20%20";
93        let expected: [u8; 10] = [32, 32, 32, 32, 32, 32, 32, 32, 32, 32];
94        let expected_utf8 = "          ";
95
96        let mut d = Decoder::<10>::init();
97        let c = d.decode(poop_str).unwrap();
98        let utf8 = core::str::from_utf8(d.cur_block());
99
100        assert_eq!(c, 10);
101        assert_eq!(d.cur_block(), &expected);
102        assert_eq!(utf8, Ok(expected_utf8));
103    }
104
105    #[test]
106    fn f_10_mixmash() {
107        let poop_str = "%20 %20 %20";
108        let expected: [u8; 5] = [32, 32, 32, 32, 32];
109        let expected_utf8 = "     ";
110
111        let mut d = Decoder::<5>::init();
112        let c = d.decode(poop_str).unwrap();
113        let utf8 = core::str::from_utf8(d.cur_block());
114
115        assert_eq!(c, 5);
116        assert_eq!(d.cur_block(), &expected);
117        assert_eq!(utf8, Ok(expected_utf8));
118    }
119}