protobuf_support/lexer/
str_lit.rs

1use std::fmt;
2use std::string::FromUtf8Error;
3
4use crate::lexer::lexer_impl::Lexer;
5use crate::lexer::parser_language::ParserLanguage;
6
7#[derive(Debug, thiserror::Error)]
8pub enum StrLitDecodeError {
9    #[error(transparent)]
10    FromUtf8Error(#[from] FromUtf8Error),
11    #[error("String literal decode error")]
12    OtherError,
13}
14
15pub type StrLitDecodeResult<T> = Result<T, StrLitDecodeError>;
16
17/// String literal, both `string` and `bytes`.
18#[derive(Clone, Eq, PartialEq, Debug)]
19pub struct StrLit {
20    pub escaped: String,
21}
22
23impl fmt::Display for StrLit {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        write!(f, "\"{}\"", &self.escaped)
26    }
27}
28
29impl StrLit {
30    /// May fail if not valid UTF8
31    pub fn decode_utf8(&self) -> StrLitDecodeResult<String> {
32        let mut lexer = Lexer::new(&self.escaped, ParserLanguage::Json);
33        let mut r = Vec::new();
34        while !lexer.eof() {
35            r.extend(
36                lexer
37                    .next_str_lit_bytes()
38                    .map_err(|_| StrLitDecodeError::OtherError)?
39                    .bytes(),
40            );
41        }
42        Ok(String::from_utf8(r)?)
43    }
44
45    pub fn decode_bytes(&self) -> StrLitDecodeResult<Vec<u8>> {
46        let mut lexer = Lexer::new(&self.escaped, ParserLanguage::Json);
47        let mut r = Vec::new();
48        while !lexer.eof() {
49            r.extend(
50                lexer
51                    .next_str_lit_bytes()
52                    .map_err(|_| StrLitDecodeError::OtherError)?
53                    .bytes(),
54            );
55        }
56        Ok(r)
57    }
58
59    pub fn quoted(&self) -> String {
60        format!("\"{}\"", self.escaped)
61    }
62}
63
64#[cfg(test)]
65mod test {
66    use crate::lexer::str_lit::StrLit;
67
68    #[test]
69    fn decode_utf8() {
70        assert_eq!(
71            "\u{1234}".to_owned(),
72            StrLit {
73                escaped: "\\341\\210\\264".to_owned()
74            }
75            .decode_utf8()
76            .unwrap()
77        )
78    }
79}