Skip to content

Commit fdb9f06

Browse files
committed
Store hex digits in a stack-allocated buffer
1 parent c56db92 commit fdb9f06

File tree

2 files changed

+45
-5
lines changed

2 files changed

+45
-5
lines changed

crates/ra_syntax/src/utils.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::{File, SyntaxKind, SyntaxNodeRef, WalkEvent};
22
use std::fmt::Write;
3+
use std::ops::Deref;
4+
use std::str;
35

46
/// Parse a file and create a string representation of the resulting parse tree.
57
pub fn dump_tree(syntax: SyntaxNodeRef) -> String {
@@ -78,3 +80,38 @@ pub(crate) fn validate_block_structure(root: SyntaxNodeRef) {
7880
}
7981
}
8082
}
83+
84+
#[derive(Debug)]
85+
pub struct MutAsciiString<'a> {
86+
buf: &'a mut [u8],
87+
len: usize,
88+
}
89+
90+
impl<'a> MutAsciiString<'a> {
91+
pub fn new(buf: &'a mut [u8]) -> MutAsciiString<'a> {
92+
MutAsciiString { buf, len: 0 }
93+
}
94+
95+
pub fn as_str(&self) -> &str {
96+
str::from_utf8(&self.buf[..self.len]).unwrap()
97+
}
98+
99+
pub fn len(&self) -> usize {
100+
self.len
101+
}
102+
103+
pub fn push(&mut self, c: char) {
104+
assert!(self.len() < self.buf.len());
105+
assert!(c.is_ascii());
106+
107+
self.buf[self.len] = c as u8;
108+
self.len += 1;
109+
}
110+
}
111+
112+
impl<'a> Deref for MutAsciiString<'a> {
113+
type Target = str;
114+
fn deref(&self) -> &str {
115+
self.as_str()
116+
}
117+
}

crates/ra_syntax/src/validation.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
ast::{self, AstNode},
66
File,
77
string_lexing::{self, CharComponentKind},
8+
utils::MutAsciiString,
89
yellow::{
910
SyntaxError,
1011
SyntaxErrorKind::*,
@@ -73,12 +74,18 @@ fn validate_char(node: ast::Char, errors: &mut Vec<SyntaxError>) {
7374
return;
7475
}
7576

76-
let mut code = String::new();
77+
let mut buf = &mut [0; 6];
78+
let mut code = MutAsciiString::new(buf);
7779
let mut closed = false;
7880
for c in text[3..].chars() {
7981
assert!(!closed, "no characters after escape is closed");
8082

8183
if c.is_digit(16) {
84+
if code.len() == 6 {
85+
errors.push(SyntaxError::new(OverlongUnicodeEscape, range));
86+
return;
87+
}
88+
8289
code.push(c);
8390
} else if c == '_' {
8491
// Reject leading _
@@ -103,10 +110,6 @@ fn validate_char(node: ast::Char, errors: &mut Vec<SyntaxError>) {
103110
return;
104111
}
105112

106-
if code.len() > 6 {
107-
errors.push(SyntaxError::new(OverlongUnicodeEscape, range));
108-
}
109-
110113
match u32::from_str_radix(&code, 16) {
111114
Ok(code_u32) if code_u32 > 0x10FFFF => {
112115
errors.push(SyntaxError::new(UnicodeEscapeOutOfRange, range));

0 commit comments

Comments
 (0)