codex_percent/encode/
fixed.rs

1//! Encode impl - Fixed size array output
2
3use super::*;
4use crate::{EncoderError, FixedEncoder as Encoder};
5
6impl<'i, const S: usize> Encoder<'i, S> {
7    /// Init encoder
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    /// Encode and return resulting encoded size
24    /// *Panic*
25    /// This will panic if the output would go out of bounds
26    pub fn encode(&mut self, raw: &'i str) -> Result<usize, EncoderError> {
27        let mut cur_i = 0;
28        self.cur_raw = Some(raw);
29
30        let mut lexer = EncodeToken::lexer(raw);
31        while let Some(token) = lexer.next() {
32            match token {
33                Ok(EncodeToken::Unreserved(alphanum)) => {
34                    let needed = alphanum.as_bytes().len();
35                    let fill_to = cur_i + needed;
36                    self.cur_block[cur_i..fill_to].copy_from_slice(&alphanum.as_bytes()[0..needed]);
37                    cur_i += needed;
38                }
39                Ok(EncodeToken::NotUnreserved(notalphanum)) => {
40                    let mut bytes = notalphanum.bytes();
41                    while let Some(a) = bytes.next() {
42                        let (higher, lower) = byte2hex(a, &HEX_CHARS_UPPER);
43                        let needed = 3;
44                        self.cur_block[cur_i] = 37;
45                        self.cur_block[cur_i + 1] = higher;
46                        self.cur_block[cur_i + 2] = lower;
47                        cur_i = cur_i + needed;
48                    }
49                }
50                _ => {
51                    return Err(EncoderError::BorkedExperimental(lexer.span().start));
52                }
53            }
54        }
55        Ok(cur_i)
56    }
57}
58
59#[cfg(test)]
60mod test {
61    use super::*;
62
63    #[test]
64    fn f_10_direct_copy() {
65        let s = "1234567890";
66
67        let mut e = Encoder::<10>::init();
68        let f = e.encode(s).unwrap();
69
70        assert_eq!(f, 10);
71        assert_eq!(e.cur_block, [49, 50, 51, 52, 53, 54, 55, 56, 57, 48]);
72    }
73    #[test]
74    fn f_10_poop() {
75        let s = "💩";
76
77        let mut e = Encoder::<12>::init();
78        let res = e.encode(s).unwrap();
79
80        assert_eq!(res, 12);
81        let t = core::str::from_utf8(e.cur_block.as_slice());
82
83        assert_eq!(t, Ok("%F0%9F%92%A9"));
84    }
85    #[test]
86    fn f_10_spaces() {
87        let s = "          ";
88
89        let mut e = Encoder::<30>::init();
90        let f = e.encode(s).unwrap();
91
92        assert_eq!(f, 30);
93
94        let t = core::str::from_utf8(e.cur_block.as_slice());
95        assert_eq!(t, Ok("%20%20%20%20%20%20%20%20%20%20"));
96
97        assert_eq!(
98            e.cur_block,
99            [
100                37, 50, 48, 37, 50, 48, 37, 50, 48, 37, 50, 48, 37, 50, 48, 37, 50, 48, 37, 50, 48,
101                37, 50, 48, 37, 50, 48, 37, 50, 48
102            ]
103        );
104    }
105}