actix_web_httpauth/
utils.rs

1use std::str;
2
3use actix_web::web::BytesMut;
4
5enum State {
6    YieldStr,
7    YieldQuote,
8}
9
10struct Quoted<'a> {
11    inner: ::std::iter::Peekable<str::Split<'a, char>>,
12    state: State,
13}
14
15impl<'a> Quoted<'a> {
16    pub fn new(s: &'a str) -> Quoted<'_> {
17        Quoted {
18            inner: s.split('"').peekable(),
19            state: State::YieldStr,
20        }
21    }
22}
23
24impl<'a> Iterator for Quoted<'a> {
25    type Item = &'a str;
26
27    fn next(&mut self) -> Option<Self::Item> {
28        match self.state {
29            State::YieldStr => match self.inner.next() {
30                Some(val) => {
31                    self.state = State::YieldQuote;
32                    Some(val)
33                }
34                None => None,
35            },
36
37            State::YieldQuote => match self.inner.peek() {
38                Some(_) => {
39                    self.state = State::YieldStr;
40                    Some("\\\"")
41                }
42                None => None,
43            },
44        }
45    }
46}
47
48/// Escapes the quotes in `val`.
49pub fn put_quoted(buf: &mut BytesMut, val: &str) {
50    for part in Quoted::new(val) {
51        buf.extend_from_slice(part.as_bytes());
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use std::str;
58
59    use actix_web::web::BytesMut;
60
61    use super::put_quoted;
62
63    #[test]
64    fn test_quote_str() {
65        let input = "a \"quoted\" string";
66        let mut output = BytesMut::new();
67        put_quoted(&mut output, input);
68        let result = str::from_utf8(&output).unwrap();
69
70        assert_eq!(result, "a \\\"quoted\\\" string");
71    }
72
73    #[test]
74    fn test_without_quotes() {
75        let input = "non-quoted string";
76        let mut output = BytesMut::new();
77        put_quoted(&mut output, input);
78        let result = str::from_utf8(&output).unwrap();
79
80        assert_eq!(result, "non-quoted string");
81    }
82
83    #[test]
84    fn test_starts_with_quote() {
85        let input = "\"first-quoted string";
86        let mut output = BytesMut::new();
87        put_quoted(&mut output, input);
88        let result = str::from_utf8(&output).unwrap();
89
90        assert_eq!(result, "\\\"first-quoted string");
91    }
92
93    #[test]
94    fn test_ends_with_quote() {
95        let input = "last-quoted string\"";
96        let mut output = BytesMut::new();
97        put_quoted(&mut output, input);
98        let result = str::from_utf8(&output).unwrap();
99
100        assert_eq!(result, "last-quoted string\\\"");
101    }
102
103    #[test]
104    fn test_double_quote() {
105        let input = "quote\"\"string";
106        let mut output = BytesMut::new();
107        put_quoted(&mut output, input);
108        let result = str::from_utf8(&output).unwrap();
109
110        assert_eq!(result, "quote\\\"\\\"string");
111    }
112}