use super::lexer_impl::Lexer; use super::lexer_impl::LexerError; use crate::text_format::lexer::ParserLanguage; use std::fmt; use std::string::FromUtf8Error; #[derive(Debug)] pub enum StrLitDecodeError { FromUtf8Error(FromUtf8Error), // TODO: be more specific OtherError, } impl fmt::Display for StrLitDecodeError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { StrLitDecodeError::FromUtf8Error(e) => write!(f, "{}", e), StrLitDecodeError::OtherError => write!(f, "String literal decode error"), } } } impl std::error::Error for StrLitDecodeError {} impl From for StrLitDecodeError { fn from(_: LexerError) -> Self { StrLitDecodeError::OtherError } } impl From for StrLitDecodeError { fn from(e: FromUtf8Error) -> Self { StrLitDecodeError::FromUtf8Error(e) } } pub type StrLitDecodeResult = Result; /// String literal, both `string` and `bytes`. #[derive(Clone, Eq, PartialEq, Debug)] pub struct StrLit { pub escaped: String, } impl StrLit { /// May fail if not valid UTF8 pub fn decode_utf8(&self) -> StrLitDecodeResult { let mut lexer = Lexer::new(&self.escaped, ParserLanguage::Json); let mut r = Vec::new(); while !lexer.eof() { r.push(lexer.next_byte_value()?); } Ok(String::from_utf8(r)?) } pub fn decode_bytes(&self) -> StrLitDecodeResult> { let mut lexer = Lexer::new(&self.escaped, ParserLanguage::Json); let mut r = Vec::new(); while !lexer.eof() { r.push(lexer.next_byte_value()?); } Ok(r) } pub fn quoted(&self) -> String { format!("\"{}\"", self.escaped) } } #[cfg(test)] mod test { use crate::text_format::lexer::StrLit; #[test] fn decode_utf8() { assert_eq!( "\u{1234}".to_owned(), StrLit { escaped: "\\341\\210\\264".to_owned() } .decode_utf8() .unwrap() ) } }