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