Fix performance issue in Reader reamaining method.

This commit is contained in:
jcamiel 2023-04-15 09:46:12 +02:00
parent aa6d228487
commit 28292ef114
No known key found for this signature in database
GPG Key ID: 07FF11CFD55356CC
4 changed files with 24 additions and 24 deletions

View File

@ -58,7 +58,7 @@ fn string_template(reader: &mut Reader) -> ParseResult<'static, Template> {
let mut chars = vec![];
let start = reader.state.pos.clone();
loop {
if reader.remaining().starts_with('"') || reader.is_eof() {
if reader.peek() == Some('"') || reader.is_eof() {
break;
}
let char = any_char(reader)?;
@ -209,7 +209,7 @@ pub fn number_value(reader: &mut Reader) -> ParseResult<'static, JsonValue> {
Err(_) => "".to_string(),
};
let exponent = if reader.remaining().starts_with('e') || reader.remaining().starts_with('E') {
let exponent = if reader.peek() == Some('e') || reader.peek() == Some('E') {
reader.read();
let exponent_sign = match try_literal("-", reader) {
Ok(_) => "-".to_string(),
@ -240,15 +240,15 @@ fn list_value(reader: &mut Reader) -> ParseResult<'static, JsonValue> {
let mut elements = vec![];
// at least one element
if !reader.remaining().starts_with(']') {
if reader.peek() != Some(']') {
let first_element = list_element(reader)?;
elements.push(first_element);
loop {
if reader.remaining().starts_with(']') {
if reader.peek() == Some(']') {
break;
}
if !reader.remaining().starts_with(',') {
if reader.peek() != Some(',') {
break;
}
literal(",", reader)?;
@ -286,15 +286,15 @@ pub fn object_value(reader: &mut Reader) -> ParseResult<'static, JsonValue> {
try_literal("{", reader)?;
let space0 = whitespace(reader);
let mut elements = vec![];
if !reader.remaining().starts_with('}') {
if reader.peek() != Some('}') {
let first_element = object_element(reader)?;
elements.push(first_element);
loop {
if reader.remaining().starts_with('}') {
if reader.peek() == Some('}') {
break;
}
if !reader.remaining().starts_with(',') {
if reader.peek() != Some(',') {
break;
}
literal(",", reader)?;

View File

@ -83,7 +83,7 @@ fn graphql(reader: &mut Reader) -> ParseResult<'static, MultilineString> {
let mut chars = vec![];
let start = reader.state.pos.clone();
while !reader.remaining().starts_with("```") && !reader.is_eof() {
while reader.peek_n(3) != "```" && !reader.is_eof() {
let pos = reader.state.pos.clone();
let c = reader.read().unwrap();
chars.push((c, c.to_string(), pos));
@ -233,7 +233,7 @@ fn multiline_string_value(reader: &mut Reader) -> ParseResult<'static, Template>
let mut chars = vec![];
let start = reader.state.pos.clone();
while !reader.remaining().starts_with("```") && !reader.is_eof() {
while reader.peek_n(3) != "```" && !reader.is_eof() {
let pos = reader.state.pos.clone();
let c = reader.read().unwrap();
chars.push((c, c.to_string(), pos));
@ -262,7 +262,7 @@ fn oneline_string_value(reader: &mut Reader) -> ParseResult<'static, Template> {
let mut chars = vec![];
let start = reader.state.pos.clone();
while !reader.remaining().starts_with("```") && !reader.is_eof() {
while reader.peek_n(3) != "```" && !reader.is_eof() {
let pos = reader.state.pos.clone();
let c = reader.read().unwrap();
if c == '\n' {

View File

@ -15,6 +15,8 @@
* limitations under the License.
*
*/
use std::cmp::min;
use crate::ast::Pos;
#[derive(Clone, Debug, PartialEq, Eq)]
@ -30,6 +32,7 @@ pub struct ReaderState {
}
impl Reader {
// FIXME: change name to the more idiomatic new
pub fn init(s: &str) -> Reader {
Reader {
buffer: s.chars().collect(),
@ -65,6 +68,12 @@ impl Reader {
self.buffer.get(self.state.cursor).copied()
}
pub fn peek_n(&self, n: usize) -> String {
let start = self.state.cursor;
let end = min(start + n, self.buffer.len());
self.buffer[start..end].iter().collect()
}
pub fn read_while(&mut self, predicate: fn(&char) -> bool) -> String {
let mut s = String::from("");
loop {
@ -118,7 +127,7 @@ impl Reader {
}
pub fn try_literal(&mut self, value: &str) -> bool {
if self.remaining().starts_with(value.to_string().as_str()) {
if self.peek_n(value.len()) == value {
self.read_n(value.len());
true
} else {
@ -126,16 +135,7 @@ impl Reader {
}
}
pub fn remaining(&self) -> String {
self.buffer.as_slice()[self.state.cursor..self.buffer.len()]
.iter()
.collect()
}
pub fn slice(&self, start: usize, end: usize) -> String {
self.buffer.as_slice()[start..end].iter().collect()
}
// FIXME: explain this method, find a better name mayebe?
pub fn from(&self, start: usize) -> String {
let end = self.state.cursor;
self.buffer.as_slice()[start..end].iter().collect()
@ -155,7 +155,7 @@ mod tests {
let mut reader = Reader::init("hi");
assert_eq!(reader.state.cursor, 0);
assert!(!reader.is_eof());
assert_eq!(reader.remaining(), "hi".to_string());
assert_eq!(reader.peek_n(2), "hi".to_string());
assert_eq!(reader.read().unwrap(), 'h');
assert_eq!(reader.state.cursor, 1);

View File

@ -110,7 +110,7 @@ mod tests {
String::from("<users><user /></users>")
);
assert_eq!(reader.state.cursor, 23);
assert_eq!(reader.remaining(), String::from("xx"));
assert_eq!(reader.peek_n(2), String::from("xx"));
let mut reader = Reader::init("<?xml version=\"1.0\"?><users/>xxx");
assert_eq!(