From 73023c0299d4adeada026648c3684621f129e038 Mon Sep 17 00:00:00 2001 From: Jade Date: Wed, 12 May 2021 05:44:01 -0700 Subject: Support length for ByteStrings I am not confident that my added byte string parsing is right. --- crates/syntax/src/ast/token_ext.rs | 81 ++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 20 deletions(-) (limited to 'crates/syntax/src') diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs index 29d25a58a..4b1e1ccee 100644 --- a/crates/syntax/src/ast/token_ext.rs +++ b/crates/syntax/src/ast/token_ext.rs @@ -143,6 +143,30 @@ impl QuoteOffsets { } } +pub trait IsString: AstToken { + fn quote_offsets(&self) -> Option { + let text = self.text(); + let offsets = QuoteOffsets::new(text)?; + let o = self.syntax().text_range().start(); + let offsets = QuoteOffsets { + quotes: (offsets.quotes.0 + o, offsets.quotes.1 + o), + contents: offsets.contents + o, + }; + Some(offsets) + } + fn text_range_between_quotes(&self) -> Option { + self.quote_offsets().map(|it| it.contents) + } + fn open_quote_text_range(&self) -> Option { + self.quote_offsets().map(|it| it.quotes.0) + } + fn close_quote_text_range(&self) -> Option { + self.quote_offsets().map(|it| it.quotes.1) + } +} + +impl IsString for ast::String {} + impl ast::String { pub fn is_raw(&self) -> bool { self.text().starts_with('r') @@ -187,32 +211,49 @@ impl ast::String { (false, false) => Some(Cow::Owned(buf)), } } - - pub fn quote_offsets(&self) -> Option { - let text = self.text(); - let offsets = QuoteOffsets::new(text)?; - let o = self.syntax().text_range().start(); - let offsets = QuoteOffsets { - quotes: (offsets.quotes.0 + o, offsets.quotes.1 + o), - contents: offsets.contents + o, - }; - Some(offsets) - } - pub fn text_range_between_quotes(&self) -> Option { - self.quote_offsets().map(|it| it.contents) - } - pub fn open_quote_text_range(&self) -> Option { - self.quote_offsets().map(|it| it.quotes.0) - } - pub fn close_quote_text_range(&self) -> Option { - self.quote_offsets().map(|it| it.quotes.1) - } } +impl IsString for ast::ByteString {} + impl ast::ByteString { pub fn is_raw(&self) -> bool { self.text().starts_with("br") } + + pub fn value(&self) -> Option> { + if self.is_raw() { + let text = self.text(); + let text = + &text[self.text_range_between_quotes()? - self.syntax().text_range().start()]; + return Some(Cow::Borrowed(text.as_bytes())); + } + + let text = self.text(); + let text = &text[self.text_range_between_quotes()? - self.syntax().text_range().start()]; + + let mut buf: Vec = Vec::new(); + let mut text_iter = text.chars(); + let mut has_error = false; + unescape_literal(text, Mode::ByteStr, &mut |char_range, unescaped_char| match ( + unescaped_char, + buf.capacity() == 0, + ) { + (Ok(c), false) => buf.push(c as u8), + (Ok(c), true) if char_range.len() == 1 && Some(c) == text_iter.next() => (), + (Ok(c), true) => { + buf.reserve_exact(text.len()); + buf.extend_from_slice(&text[..char_range.start].as_bytes()); + buf.push(c as u8); + } + (Err(_), _) => has_error = true, + }); + + match (has_error, buf.capacity() == 0) { + (true, _) => None, + (false, true) => Some(Cow::Borrowed(text.as_bytes())), + (false, false) => Some(Cow::Owned(buf)), + } + } } #[derive(Debug)] -- cgit v1.2.3