From e2923c3cab72914cb259186d31c680d107f0b013 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 24 Jun 2023 16:04:24 -0700 Subject: [PATCH 1/2] Factor out logic for processing trailing backslashes --- src/parse.rs | 85 ++++++++++++++++++++-------------------------------- 1 file changed, 33 insertions(+), 52 deletions(-) diff --git a/src/parse.rs b/src/parse.rs index d48e974..6b5ad7d 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -371,7 +371,7 @@ fn string(input: Cursor) -> Result { } } -fn cooked_string(input: Cursor) -> Result { +fn cooked_string(mut input: Cursor) -> Result { let mut chars = input.char_indices().peekable(); while let Some((i, ch)) = chars.next() { @@ -393,21 +393,10 @@ fn cooked_string(input: Cursor) -> Result { Some((_, 'u')) => { backslash_u(&mut chars)?; } - Some((_, ch @ '\n')) | Some((_, ch @ '\r')) => { - let mut last = ch; - loop { - if last == '\r' && chars.next().map_or(true, |(_, ch)| ch != '\n') { - return Err(Reject); - } - match chars.peek() { - Some((_, ch @ ' ')) | Some((_, ch @ '\t')) | Some((_, ch @ '\n')) - | Some((_, ch @ '\r')) => { - last = *ch; - chars.next(); - } - _ => break, - } - } + Some((newline, ch @ '\n')) | Some((newline, ch @ '\r')) => { + input = input.advance(newline + 1); + trailing_backslash(&mut input, ch as u8)?; + chars = input.char_indices().peekable(); } _ => break, }, @@ -465,26 +454,9 @@ fn cooked_byte_string(mut input: Cursor) -> Result { Some((_, b'n')) | Some((_, b'r')) | Some((_, b't')) | Some((_, b'\\')) | Some((_, b'0')) | Some((_, b'\'')) | Some((_, b'"')) => {} Some((newline, b @ b'\n')) | Some((newline, b @ b'\r')) => { - let mut last = b; - let rest = input.advance(newline + 1); - let mut whitespace = rest.bytes().enumerate(); - loop { - if last == b'\r' && whitespace.next().map_or(true, |(_, b)| b != b'\n') { - return Err(Reject); - } - match whitespace.next() { - Some((_, b @ b' ')) | Some((_, b @ b'\t')) | Some((_, b @ b'\n')) - | Some((_, b @ b'\r')) => { - last = b; - } - Some((offset, _)) => { - input = rest.advance(offset); - bytes = input.bytes().enumerate(); - break; - } - None => return Err(Reject), - } - } + input = input.advance(newline + 1); + trailing_backslash(&mut input, b)?; + bytes = input.bytes().enumerate(); } _ => break, }, @@ -567,7 +539,7 @@ fn raw_c_string(input: Cursor) -> Result { Err(Reject) } -fn cooked_c_string(input: Cursor) -> Result { +fn cooked_c_string(mut input: Cursor) -> Result { let mut chars = input.char_indices().peekable(); while let Some((i, ch)) = chars.next() { @@ -591,21 +563,10 @@ fn cooked_c_string(input: Cursor) -> Result { break; } } - Some((_, ch @ '\n')) | Some((_, ch @ '\r')) => { - let mut last = ch; - loop { - if last == '\r' && chars.next().map_or(true, |(_, ch)| ch != '\n') { - return Err(Reject); - } - match chars.peek() { - Some((_, ch @ ' ')) | Some((_, ch @ '\t')) | Some((_, ch @ '\n')) - | Some((_, ch @ '\r')) => { - last = *ch; - chars.next(); - } - _ => break, - } - } + Some((newline, ch @ '\n')) | Some((newline, ch @ '\r')) => { + input = input.advance(newline + 1); + trailing_backslash(&mut input, ch as u8)?; + chars = input.char_indices().peekable(); } _ => break, }, @@ -730,6 +691,26 @@ where Err(Reject) } +fn trailing_backslash(input: &mut Cursor, mut last: u8) -> Result<(), Reject> { + let mut whitespace = input.bytes().enumerate(); + loop { + if last == b'\r' && whitespace.next().map_or(true, |(_, b)| b != b'\n') { + return Err(Reject); + } + match whitespace.next() { + Some((_, b @ b' ')) | Some((_, b @ b'\t')) | Some((_, b @ b'\n')) + | Some((_, b @ b'\r')) => { + last = b; + } + Some((offset, _)) => { + *input = input.advance(offset); + return Ok(()); + } + None => return Err(Reject), + } + } +} + fn float(input: Cursor) -> Result { let mut rest = float_digits(input)?; if let Some(ch) = rest.chars().next() { From aebe7a0e7bbc9876fbce41f7e72112ca7f6f3f8e Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 24 Jun 2023 16:06:36 -0700 Subject: [PATCH 2/2] Eliminate unneeded peekability on cooked string iterators --- src/parse.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/parse.rs b/src/parse.rs index 6b5ad7d..9bf5bd0 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -372,7 +372,7 @@ fn string(input: Cursor) -> Result { } fn cooked_string(mut input: Cursor) -> Result { - let mut chars = input.char_indices().peekable(); + let mut chars = input.char_indices(); while let Some((i, ch)) = chars.next() { match ch { @@ -396,7 +396,7 @@ fn cooked_string(mut input: Cursor) -> Result { Some((newline, ch @ '\n')) | Some((newline, ch @ '\r')) => { input = input.advance(newline + 1); trailing_backslash(&mut input, ch as u8)?; - chars = input.char_indices().peekable(); + chars = input.char_indices(); } _ => break, }, @@ -540,7 +540,7 @@ fn raw_c_string(input: Cursor) -> Result { } fn cooked_c_string(mut input: Cursor) -> Result { - let mut chars = input.char_indices().peekable(); + let mut chars = input.char_indices(); while let Some((i, ch)) = chars.next() { match ch { @@ -566,7 +566,7 @@ fn cooked_c_string(mut input: Cursor) -> Result { Some((newline, ch @ '\n')) | Some((newline, ch @ '\r')) => { input = input.advance(newline + 1); trailing_backslash(&mut input, ch as u8)?; - chars = input.char_indices().peekable(); + chars = input.char_indices(); } _ => break, },