( chars: &mut T, )
| 96 | } |
| 97 | |
| 98 | pub fn parse_string_with_char_provider<'a, T: CharProvider<'a>>( |
| 99 | chars: &mut T, |
| 100 | ) -> Result<Cow<'a, str>, ParseStringError> { |
| 101 | debug_assert!( |
| 102 | chars.current_char() == Some('\'') || chars.current_char() == Some('"'), |
| 103 | "Expected \", was {:?}", |
| 104 | chars.current_char() |
| 105 | ); |
| 106 | let is_double_quote = chars.current_char() == Some('"'); |
| 107 | let mut last_start_byte_index = chars.byte_index() + 1; |
| 108 | let mut text: Option<String> = None; |
| 109 | let mut last_was_backslash = false; |
| 110 | let mut found_end_string = false; |
| 111 | let token_start = chars.byte_index(); |
| 112 | |
| 113 | while let Some(current_char) = chars.move_next_char() { |
| 114 | if last_was_backslash { |
| 115 | let escape_start = chars.byte_index() - 1; // -1 for backslash |
| 116 | match current_char { |
| 117 | '"' | '\'' | '\\' | '/' | 'b' | 'f' | 'u' | 'r' | 'n' | 't' => { |
| 118 | if current_char == '"' { |
| 119 | if !is_double_quote { |
| 120 | return Err(ParseStringError { |
| 121 | byte_index: escape_start, |
| 122 | kind: ParseStringErrorKind::InvalidEscapeInSingleQuoteString, |
| 123 | }); |
| 124 | } |
| 125 | } else if current_char == '\'' && is_double_quote { |
| 126 | return Err(ParseStringError { |
| 127 | byte_index: escape_start, |
| 128 | kind: ParseStringErrorKind::InvalidEscapeInDoubleQuoteString, |
| 129 | }); |
| 130 | } |
| 131 | |
| 132 | let previous_text = &chars.text()[last_start_byte_index..escape_start]; |
| 133 | if text.is_none() { |
| 134 | text = Some(String::new()); |
| 135 | } |
| 136 | let text = text.as_mut().unwrap(); |
| 137 | text.push_str(previous_text); |
| 138 | if current_char == 'u' { |
| 139 | let hex_char = parse_hex_char(chars).map_err(|kind| ParseStringError { |
| 140 | byte_index: escape_start, |
| 141 | kind, |
| 142 | })?; |
| 143 | text.push(hex_char); |
| 144 | last_start_byte_index = chars.byte_index() + chars.current_char().map(|c| c.len_utf8()).unwrap_or(0); |
| 145 | } else { |
| 146 | text.push(match current_char { |
| 147 | 'b' => '\u{08}', |
| 148 | 'f' => '\u{0C}', |
| 149 | 't' => '\t', |
| 150 | 'r' => '\r', |
| 151 | 'n' => '\n', |
| 152 | _ => current_char, |
| 153 | }); |
| 154 | last_start_byte_index = chars.byte_index() + current_char.len_utf8(); |
| 155 | } |
no test coverage detected
searching dependent graphs…