From fdb9f06880ddcf29513a8c2855c3c576cc461014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adolfo=20Ochagav=C3=ADa?= Date: Wed, 7 Nov 2018 10:40:58 +0100 Subject: Store hex digits in a stack-allocated buffer --- crates/ra_syntax/src/utils.rs | 37 +++++++++++++++++++++++++++++++++++++ crates/ra_syntax/src/validation.rs | 13 ++++++++----- 2 files changed, 45 insertions(+), 5 deletions(-) (limited to 'crates') diff --git a/crates/ra_syntax/src/utils.rs b/crates/ra_syntax/src/utils.rs index 288d7edd4..5bef4a639 100644 --- a/crates/ra_syntax/src/utils.rs +++ b/crates/ra_syntax/src/utils.rs @@ -1,5 +1,7 @@ use crate::{File, SyntaxKind, SyntaxNodeRef, WalkEvent}; use std::fmt::Write; +use std::ops::Deref; +use std::str; /// Parse a file and create a string representation of the resulting parse tree. pub fn dump_tree(syntax: SyntaxNodeRef) -> String { @@ -78,3 +80,38 @@ pub(crate) fn validate_block_structure(root: SyntaxNodeRef) { } } } + +#[derive(Debug)] +pub struct MutAsciiString<'a> { + buf: &'a mut [u8], + len: usize, +} + +impl<'a> MutAsciiString<'a> { + pub fn new(buf: &'a mut [u8]) -> MutAsciiString<'a> { + MutAsciiString { buf, len: 0 } + } + + pub fn as_str(&self) -> &str { + str::from_utf8(&self.buf[..self.len]).unwrap() + } + + pub fn len(&self) -> usize { + self.len + } + + pub fn push(&mut self, c: char) { + assert!(self.len() < self.buf.len()); + assert!(c.is_ascii()); + + self.buf[self.len] = c as u8; + self.len += 1; + } +} + +impl<'a> Deref for MutAsciiString<'a> { + type Target = str; + fn deref(&self) -> &str { + self.as_str() + } +} diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index a550ce0ab..b560e5e85 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs @@ -5,6 +5,7 @@ use crate::{ ast::{self, AstNode}, File, string_lexing::{self, CharComponentKind}, + utils::MutAsciiString, yellow::{ SyntaxError, SyntaxErrorKind::*, @@ -73,12 +74,18 @@ fn validate_char(node: ast::Char, errors: &mut Vec) { return; } - let mut code = String::new(); + let mut buf = &mut [0; 6]; + let mut code = MutAsciiString::new(buf); let mut closed = false; for c in text[3..].chars() { assert!(!closed, "no characters after escape is closed"); if c.is_digit(16) { + if code.len() == 6 { + errors.push(SyntaxError::new(OverlongUnicodeEscape, range)); + return; + } + code.push(c); } else if c == '_' { // Reject leading _ @@ -103,10 +110,6 @@ fn validate_char(node: ast::Char, errors: &mut Vec) { return; } - if code.len() > 6 { - errors.push(SyntaxError::new(OverlongUnicodeEscape, range)); - } - match u32::from_str_radix(&code, 16) { Ok(code_u32) if code_u32 > 0x10FFFF => { errors.push(SyntaxError::new(UnicodeEscapeOutOfRange, range)); -- cgit v1.2.3