Don't double loop over chunks

This commit is contained in:
Noah
2020-10-07 13:32:12 -05:00
parent 1f4f407d5d
commit dcb12abbae

View File

@@ -123,16 +123,24 @@ impl StrOrChar<'_> {
}
}
}
pub fn scanstring(s: &str, end: usize, strict: bool) -> Result<(String, usize), DecodeError> {
let mut chunks: Vec<StrOrChar> = Vec::new();
pub fn scanstring<'a>(
s: &'a str,
end: usize,
strict: bool,
) -> Result<(String, usize), DecodeError> {
let mut chunks: Vec<StrOrChar<'a>> = Vec::new();
let mut output_len = 0usize;
let mut push_chunk = |chunk: StrOrChar<'a>| {
output_len += chunk.len();
chunks.push(chunk);
};
let mut chunk_start = end;
let mut chars = s.char_indices().enumerate().skip(end).peekable();
while let Some((char_i, (i, c))) = chars.next() {
match c {
'"' => {
chunks.push(StrOrChar::Str(&s[chunk_start..i]));
let len = chunks.iter().map(|x| x.len()).sum();
let mut out = String::with_capacity(len);
push_chunk(StrOrChar::Str(&s[chunk_start..i]));
let mut out = String::with_capacity(output_len);
for x in chunks {
match x {
StrOrChar::Str(s) => out.push_str(s),
@@ -158,7 +166,7 @@ pub fn scanstring(s: &str, end: usize, strict: bool) -> Result<(String, usize),
't' => "\t",
'u' => {
let surrogate_err = || DecodeError::new("unpaired surrogate", char_i);
chunks.push(StrOrChar::Str(&s[chunk_start..i]));
push_chunk(StrOrChar::Str(&s[chunk_start..i]));
let mut uni = decode_unicode(&mut chars, char_i)?;
chunk_start = char_i + 6;
if (0xd800..=0xdbff).contains(&uni) {
@@ -184,7 +192,7 @@ pub fn scanstring(s: &str, end: usize, strict: bool) -> Result<(String, usize),
}
}
}
chunks.push(StrOrChar::Char(
push_chunk(StrOrChar::Char(
std::char::from_u32(uni).ok_or_else(surrogate_err)?,
));
continue;
@@ -196,9 +204,9 @@ pub fn scanstring(s: &str, end: usize, strict: bool) -> Result<(String, usize),
))
}
};
chunks.push(StrOrChar::Str(&s[chunk_start..i]));
push_chunk(StrOrChar::Str(&s[chunk_start..i]));
chunk_start = i + 2;
chunks.push(StrOrChar::Str(esc));
push_chunk(StrOrChar::Str(esc));
}
'\x00'..='\x1f' if strict => {
return Err(DecodeError::new(