Store hex digits in a stack-allocated buffer

This commit is contained in:
Adolfo Ochagavía 2018-11-07 10:40:58 +01:00
parent c56db92d1f
commit fdb9f06880
2 changed files with 45 additions and 5 deletions

View file

@ -1,5 +1,7 @@
use crate::{File, SyntaxKind, SyntaxNodeRef, WalkEvent}; use crate::{File, SyntaxKind, SyntaxNodeRef, WalkEvent};
use std::fmt::Write; use std::fmt::Write;
use std::ops::Deref;
use std::str;
/// Parse a file and create a string representation of the resulting parse tree. /// Parse a file and create a string representation of the resulting parse tree.
pub fn dump_tree(syntax: SyntaxNodeRef) -> String { 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()
}
}

View file

@ -5,6 +5,7 @@ use crate::{
ast::{self, AstNode}, ast::{self, AstNode},
File, File,
string_lexing::{self, CharComponentKind}, string_lexing::{self, CharComponentKind},
utils::MutAsciiString,
yellow::{ yellow::{
SyntaxError, SyntaxError,
SyntaxErrorKind::*, SyntaxErrorKind::*,
@ -73,12 +74,18 @@ fn validate_char(node: ast::Char, errors: &mut Vec<SyntaxError>) {
return; return;
} }
let mut code = String::new(); let mut buf = &mut [0; 6];
let mut code = MutAsciiString::new(buf);
let mut closed = false; let mut closed = false;
for c in text[3..].chars() { for c in text[3..].chars() {
assert!(!closed, "no characters after escape is closed"); assert!(!closed, "no characters after escape is closed");
if c.is_digit(16) { if c.is_digit(16) {
if code.len() == 6 {
errors.push(SyntaxError::new(OverlongUnicodeEscape, range));
return;
}
code.push(c); code.push(c);
} else if c == '_' { } else if c == '_' {
// Reject leading _ // Reject leading _
@ -103,10 +110,6 @@ fn validate_char(node: ast::Char, errors: &mut Vec<SyntaxError>) {
return; return;
} }
if code.len() > 6 {
errors.push(SyntaxError::new(OverlongUnicodeEscape, range));
}
match u32::from_str_radix(&code, 16) { match u32::from_str_radix(&code, 16) {
Ok(code_u32) if code_u32 > 0x10FFFF => { Ok(code_u32) if code_u32 > 0x10FFFF => {
errors.push(SyntaxError::new(UnicodeEscapeOutOfRange, range)); errors.push(SyntaxError::new(UnicodeEscapeOutOfRange, range));