diff options
author | Adolfo OchagavĂa <[email protected]> | 2018-11-07 09:40:58 +0000 |
---|---|---|
committer | Adolfo OchagavĂa <[email protected]> | 2018-11-07 09:40:58 +0000 |
commit | fdb9f06880ddcf29513a8c2855c3c576cc461014 (patch) | |
tree | 6488720c7f76604b1d58f7139337c6c483eb3522 | |
parent | c56db92d1f9b1a24de24cefd996c43c7b988b4c3 (diff) |
Store hex digits in a stack-allocated buffer
-rw-r--r-- | crates/ra_syntax/src/utils.rs | 37 | ||||
-rw-r--r-- | crates/ra_syntax/src/validation.rs | 13 |
2 files changed, 45 insertions, 5 deletions
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 @@ | |||
1 | use crate::{File, SyntaxKind, SyntaxNodeRef, WalkEvent}; | 1 | use crate::{File, SyntaxKind, SyntaxNodeRef, WalkEvent}; |
2 | use std::fmt::Write; | 2 | use std::fmt::Write; |
3 | use std::ops::Deref; | ||
4 | use std::str; | ||
3 | 5 | ||
4 | /// Parse a file and create a string representation of the resulting parse tree. | 6 | /// Parse a file and create a string representation of the resulting parse tree. |
5 | pub fn dump_tree(syntax: SyntaxNodeRef) -> String { | 7 | pub fn dump_tree(syntax: SyntaxNodeRef) -> String { |
@@ -78,3 +80,38 @@ pub(crate) fn validate_block_structure(root: SyntaxNodeRef) { | |||
78 | } | 80 | } |
79 | } | 81 | } |
80 | } | 82 | } |
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 | } | ||
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::{ | |||
5 | ast::{self, AstNode}, | 5 | ast::{self, AstNode}, |
6 | File, | 6 | File, |
7 | string_lexing::{self, CharComponentKind}, | 7 | string_lexing::{self, CharComponentKind}, |
8 | utils::MutAsciiString, | ||
8 | yellow::{ | 9 | yellow::{ |
9 | SyntaxError, | 10 | SyntaxError, |
10 | SyntaxErrorKind::*, | 11 | SyntaxErrorKind::*, |
@@ -73,12 +74,18 @@ fn validate_char(node: ast::Char, errors: &mut Vec<SyntaxError>) { | |||
73 | return; | 74 | return; |
74 | } | 75 | } |
75 | 76 | ||
76 | let mut code = String::new(); | 77 | let mut buf = &mut [0; 6]; |
78 | let mut code = MutAsciiString::new(buf); | ||
77 | let mut closed = false; | 79 | let mut closed = false; |
78 | for c in text[3..].chars() { | 80 | for c in text[3..].chars() { |
79 | assert!(!closed, "no characters after escape is closed"); | 81 | assert!(!closed, "no characters after escape is closed"); |
80 | 82 | ||
81 | if c.is_digit(16) { | 83 | if c.is_digit(16) { |
84 | if code.len() == 6 { | ||
85 | errors.push(SyntaxError::new(OverlongUnicodeEscape, range)); | ||
86 | return; | ||
87 | } | ||
88 | |||
82 | code.push(c); | 89 | code.push(c); |
83 | } else if c == '_' { | 90 | } else if c == '_' { |
84 | // Reject leading _ | 91 | // Reject leading _ |
@@ -103,10 +110,6 @@ fn validate_char(node: ast::Char, errors: &mut Vec<SyntaxError>) { | |||
103 | return; | 110 | return; |
104 | } | 111 | } |
105 | 112 | ||
106 | if code.len() > 6 { | ||
107 | errors.push(SyntaxError::new(OverlongUnicodeEscape, range)); | ||
108 | } | ||
109 | |||
110 | match u32::from_str_radix(&code, 16) { | 113 | match u32::from_str_radix(&code, 16) { |
111 | Ok(code_u32) if code_u32 > 0x10FFFF => { | 114 | Ok(code_u32) if code_u32 > 0x10FFFF => { |
112 | errors.push(SyntaxError::new(UnicodeEscapeOutOfRange, range)); | 115 | errors.push(SyntaxError::new(UnicodeEscapeOutOfRange, range)); |