Skip to content

Commit 246375a

Browse files
committed
Non observable parser assembly layout perf optimizations.
1 parent 7a9950b commit 246375a

File tree

7 files changed

+86
-106
lines changed

7 files changed

+86
-106
lines changed

fluent-syntax/src/parser/comment.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ where
5252

5353
pub(super) fn skip_comment(&mut self) {
5454
loop {
55-
while self.ptr < self.length && !self.is_current_byte(b'\n') {
55+
while self.ptr < self.length {
5656
self.ptr += 1;
57+
if self.is_byte_at(b'\n', self.ptr - 1) {
58+
break;
59+
}
5760
}
58-
self.ptr += 1;
59-
if self.is_current_byte(b'#') {
60-
self.ptr += 1;
61-
} else {
61+
if !self.take_byte_if(b'#') {
6262
break;
6363
}
6464
}

fluent-syntax/src/parser/expression.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,13 @@ where
6464
}
6565

6666
pub(super) fn get_inline_expression(&mut self) -> Result<ast::InlineExpression<S>> {
67-
match self.source.as_ref().as_bytes().get(self.ptr) {
67+
match self.source.get(self.ptr) {
6868
Some(b'"') => {
6969
self.ptr += 1; // "
7070
let start = self.ptr;
71-
while let Some(b) = self.source.as_ref().as_bytes().get(self.ptr) {
71+
while let Some(b) = self.source.get(self.ptr) {
7272
match b {
73-
b'\\' => match self.source.as_ref().as_bytes().get(self.ptr + 1) {
73+
b'\\' => match self.source.get(self.ptr + 1) {
7474
Some(b'\\') | Some(b'{') | Some(b'"') => self.ptr += 2,
7575
Some(b'u') => {
7676
self.ptr += 2;
@@ -126,7 +126,7 @@ where
126126
let id = self.get_identifier()?;
127127
let arguments = self.get_call_arguments()?;
128128
if arguments.is_some() {
129-
if !Self::is_callee(id.name.as_ref().as_bytes()) {
129+
if !Self::is_callee(&id.name) {
130130
return error!(ErrorKind::ForbiddenCallee, self.ptr);
131131
}
132132

fluent-syntax/src/parser/helper.rs

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,19 @@ impl<'s, S> Parser<S>
55
where
66
S: Slice<'s>,
77
{
8+
#[inline]
89
pub(super) fn is_current_byte(&self, b: u8) -> bool {
9-
self.source.as_ref().as_bytes().get(self.ptr) == Some(&b)
10+
self.source.get(self.ptr) == Some(&b)
1011
}
1112

13+
#[inline]
1214
pub(super) fn is_byte_at(&self, b: u8, pos: usize) -> bool {
13-
self.source.as_ref().as_bytes().get(pos) == Some(&b)
15+
self.source.get(pos) == Some(&b)
1416
}
1517

1618
pub(super) fn skip_to_next_entry_start(&mut self) {
17-
while let Some(b) = self.source.as_ref().as_bytes().get(self.ptr) {
18-
let new_line =
19-
self.ptr == 0 || self.source.as_ref().as_bytes().get(self.ptr - 1) == Some(&b'\n');
19+
while let Some(b) = self.source.get(self.ptr) {
20+
let new_line = self.ptr == 0 || self.source.get(self.ptr - 1) == Some(&b'\n');
2021

2122
if new_line && (b.is_ascii_alphabetic() || [b'-', b'#'].contains(b)) {
2223
break;
@@ -27,7 +28,7 @@ where
2728
}
2829

2930
pub(super) fn skip_eol(&mut self) -> bool {
30-
match self.source.as_ref().as_bytes().get(self.ptr) {
31+
match self.source.get(self.ptr) {
3132
Some(b'\n') => {
3233
self.ptr += 1;
3334
true
@@ -43,7 +44,7 @@ where
4344
pub(super) fn skip_unicode_escape_sequence(&mut self, length: usize) -> Result<()> {
4445
let start = self.ptr;
4546
for _ in 0..length {
46-
match self.source.as_ref().as_bytes().get(self.ptr) {
47+
match self.source.get(self.ptr) {
4748
Some(b) if b.is_ascii_hexdigit() => self.ptr += 1,
4849
_ => break,
4950
}
@@ -61,7 +62,7 @@ where
6162
}
6263

6364
pub(super) fn is_identifier_start(&self) -> bool {
64-
matches!(self.source.as_ref().as_bytes().get(self.ptr), Some(b) if b.is_ascii_alphabetic())
65+
matches!(self.source.get(self.ptr), Some(b) if b.is_ascii_alphabetic())
6566
}
6667

6768
pub(super) fn take_byte_if(&mut self, b: u8) -> bool {
@@ -89,32 +90,29 @@ where
8990

9091
pub(super) fn skip_blank(&mut self) {
9192
loop {
92-
match self.source.as_ref().as_bytes().get(self.ptr) {
93+
match self.source.get(self.ptr) {
9394
Some(b' ') | Some(b'\n') => self.ptr += 1,
94-
Some(b'\r')
95-
if self.source.as_ref().as_bytes().get(self.ptr + 1) == Some(&b'\n') =>
96-
{
97-
self.ptr += 2
98-
}
95+
Some(b'\r') if self.source.get(self.ptr + 1) == Some(&b'\n') => self.ptr += 2,
9996
_ => break,
10097
}
10198
}
10299
}
103100

104101
pub(super) fn skip_blank_inline(&mut self) -> usize {
105102
let start = self.ptr;
106-
while let Some(b' ') = self.source.as_ref().as_bytes().get(self.ptr) {
103+
while let Some(b' ') = self.source.get(self.ptr) {
107104
self.ptr += 1;
108105
}
109106
self.ptr - start
110107
}
111108

112109
pub(super) fn is_byte_pattern_continuation(b: u8) -> bool {
113-
![b'}', b'.', b'[', b'*'].contains(&b)
110+
!matches!(b, b'}' | b'.' | b'[' | b'*')
114111
}
115112

116-
pub(super) fn is_callee(name: &[u8]) -> bool {
117-
name.iter()
113+
pub(super) fn is_callee(name: &S) -> bool {
114+
name.bytes()
115+
.iter()
118116
.all(|c| c.is_ascii_uppercase() || c.is_ascii_digit() || *c == b'_' || *c == b'-')
119117
}
120118

@@ -127,11 +125,11 @@ where
127125
}
128126

129127
pub(super) fn is_number_start(&self) -> bool {
130-
matches!(self.source.as_ref().as_bytes().get(self.ptr), Some(b) if (b == &b'-') || b.is_ascii_digit())
128+
matches!(self.source.get(self.ptr), Some(b) if (b == &b'-') || b.is_ascii_digit())
131129
}
132130

133131
pub(super) fn is_eol(&self) -> bool {
134-
match self.source.as_ref().as_bytes().get(self.ptr) {
132+
match self.source.get(self.ptr) {
135133
Some(b'\n') => true,
136134
Some(b'\r') if self.is_byte_at(b'\n', self.ptr + 1) => true,
137135
_ => false,
@@ -141,7 +139,7 @@ where
141139
pub(super) fn skip_digits(&mut self) -> Result<()> {
142140
let start = self.ptr;
143141
loop {
144-
match self.source.as_ref().as_bytes().get(self.ptr) {
142+
match self.source.get(self.ptr) {
145143
Some(b) if b.is_ascii_digit() => self.ptr += 1,
146144
_ => break,
147145
}

fluent-syntax/src/parser/mod.rs

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ where
9292
}
9393

9494
fn get_entry(&mut self, entry_start: usize) -> Result<ast::Entry<S>> {
95-
let entry = match self.source.as_ref().as_bytes().get(self.ptr) {
95+
let entry = match self.source.get(self.ptr) {
9696
Some(b'#') => {
9797
let (comment, level) = self.get_comment()?;
9898
match level {
@@ -170,7 +170,7 @@ where
170170
loop {
171171
let line_start = self.ptr;
172172
self.skip_blank_inline();
173-
if !self.is_current_byte(b'.') {
173+
if !self.take_byte_if(b'.') {
174174
self.ptr = line_start;
175175
break;
176176
}
@@ -186,7 +186,6 @@ where
186186
}
187187

188188
fn get_attribute(&mut self) -> Result<ast::Attribute<S>> {
189-
self.expect_byte(b'.')?;
190189
let id = self.get_identifier()?;
191190
self.skip_blank_inline();
192191
self.expect_byte(b'=')?;
@@ -199,32 +198,25 @@ where
199198
}
200199

201200
fn get_identifier(&mut self) -> Result<ast::Identifier<S>> {
202-
let mut ptr = self.ptr;
201+
let start = self.ptr;
203202

204-
match self.source.as_ref().as_bytes().get(ptr) {
205-
Some(b) if b.is_ascii_alphabetic() => {
206-
ptr += 1;
207-
}
208-
_ => {
209-
return error!(
210-
ErrorKind::ExpectedCharRange {
211-
range: "a-zA-Z".to_string()
212-
},
213-
ptr
214-
);
215-
}
203+
if self.is_identifier_start() {
204+
self.ptr += 1;
205+
} else {
206+
return error!(
207+
ErrorKind::ExpectedCharRange {
208+
range: "a-zA-Z".to_string()
209+
},
210+
self.ptr
211+
);
216212
}
217213

218-
while let Some(b) = self.source.as_ref().as_bytes().get(ptr) {
219-
if b.is_ascii_alphabetic() || b.is_ascii_digit() || [b'_', b'-'].contains(b) {
220-
ptr += 1;
221-
} else {
222-
break;
223-
}
214+
while matches!(self.source.get(self.ptr), Some(b) if b.is_ascii_alphanumeric() || *b == b'-' || *b == b'_')
215+
{
216+
self.ptr += 1
224217
}
225218

226-
let name = self.source.slice(self.ptr..ptr);
227-
self.ptr = ptr;
219+
let name = self.source.slice(start..self.ptr);
228220

229221
Ok(ast::Identifier { name })
230222
}

fluent-syntax/src/parser/pattern.rs

Lines changed: 15 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,6 @@ enum PatternElementPlaceholders<S> {
2929
TextElement(usize, usize, usize, TextElementPosition),
3030
}
3131

32-
// This enum tracks whether the text element is blank or not.
33-
// This is important to identify text elements which should not be taken into account
34-
// when calculating common indent.
35-
#[derive(Debug, PartialEq)]
36-
enum TextElementType {
37-
Blank,
38-
NonBlank,
39-
}
40-
4132
impl<'s, S> Parser<S>
4233
where
4334
S: Slice<'s>,
@@ -73,7 +64,7 @@ where
7364
if self.ptr >= self.length {
7465
break;
7566
}
76-
let b = self.source.as_ref().as_bytes().get(self.ptr);
67+
let b = self.source.get(self.ptr);
7768
if indent == 0 {
7869
if b != Some(&b'\r') && b != Some(&b'\n') {
7970
break;
@@ -83,11 +74,9 @@ where
8374
break;
8475
}
8576
}
86-
let (start, end, text_element_type, termination_reason) = self.get_text_slice()?;
87-
if start != end {
88-
if text_element_role == TextElementPosition::LineStart
89-
&& text_element_type == TextElementType::NonBlank
90-
{
77+
let (end, is_blank, termination_reason) = self.get_text_slice()?;
78+
if slice_start != end {
79+
if text_element_role == TextElementPosition::LineStart && !is_blank {
9180
if let Some(common) = common_indent {
9281
if indent < common {
9382
common_indent = Some(indent);
@@ -97,10 +86,10 @@ where
9786
}
9887
}
9988
if text_element_role != TextElementPosition::LineStart
100-
|| text_element_type == TextElementType::NonBlank
89+
|| !is_blank
10190
|| termination_reason == TextElementTermination::LineFeed
10291
{
103-
if text_element_type == TextElementType::NonBlank {
92+
if !is_blank {
10493
last_non_blank = Some(elements.len());
10594
}
10695
elements.push(PatternElementPlaceholders::TextElement(
@@ -142,10 +131,8 @@ where
142131
let mut value = self.source.slice(start..end);
143132
if last_non_blank == i {
144133
value.trim();
145-
ast::PatternElement::TextElement { value }
146-
} else {
147-
ast::PatternElement::TextElement { value }
148134
}
135+
ast::PatternElement::TextElement { value }
149136
}
150137
})
151138
.collect();
@@ -155,55 +142,32 @@ where
155142
Ok(None)
156143
}
157144

158-
fn get_text_slice(
159-
&mut self,
160-
) -> Result<(usize, usize, TextElementType, TextElementTermination)> {
161-
let start_pos = self.ptr;
162-
let mut text_element_type = TextElementType::Blank;
145+
fn get_text_slice(&mut self) -> Result<(usize, bool, TextElementTermination)> {
146+
let mut is_blank = true;
163147

164-
while let Some(b) = self.source.as_ref().as_bytes().get(self.ptr) {
148+
while let Some(b) = self.source.get(self.ptr) {
165149
match b {
166150
b' ' => self.ptr += 1,
167151
b'\n' => {
168152
self.ptr += 1;
169-
return Ok((
170-
start_pos,
171-
self.ptr,
172-
text_element_type,
173-
TextElementTermination::LineFeed,
174-
));
153+
return Ok((self.ptr, is_blank, TextElementTermination::LineFeed));
175154
}
176155
b'\r' if self.is_byte_at(b'\n', self.ptr + 1) => {
177156
self.ptr += 1;
178-
return Ok((
179-
start_pos,
180-
self.ptr - 1,
181-
text_element_type,
182-
TextElementTermination::CRLF,
183-
));
157+
return Ok((self.ptr - 1, is_blank, TextElementTermination::CRLF));
184158
}
185159
b'{' => {
186-
return Ok((
187-
start_pos,
188-
self.ptr,
189-
text_element_type,
190-
TextElementTermination::PlaceableStart,
191-
));
160+
return Ok((self.ptr, is_blank, TextElementTermination::PlaceableStart));
192161
}
193162
b'}' => {
194163
return error!(ErrorKind::UnbalancedClosingBrace, self.ptr);
195164
}
196165
_ => {
197-
text_element_type = TextElementType::NonBlank;
166+
is_blank = false;
198167
self.ptr += 1
199168
}
200169
}
201170
}
202-
Ok((
203-
start_pos,
204-
self.ptr,
205-
text_element_type,
206-
TextElementTermination::EOF,
207-
))
171+
Ok((self.ptr, is_blank, TextElementTermination::EOF))
208172
}
209173
}

fluent-syntax/src/parser/runtime.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ where
4141
}
4242

4343
fn get_entry_runtime(&mut self, entry_start: usize) -> Result<Option<ast::Entry<S>>> {
44-
let entry = match self.source.as_ref().as_bytes().get(self.ptr) {
44+
let entry = match self.source.get(self.ptr) {
4545
Some(b'#') => {
4646
self.skip_comment();
4747
None

0 commit comments

Comments
 (0)