Get content bounds (start, end byte offsets) of a quoted string literal, excluding prefix characters and quote delimiters.
(source: &str, range: TextRange)
| 60 | /// Get content bounds (start, end byte offsets) of a quoted string literal, |
| 61 | /// excluding prefix characters and quote delimiters. |
| 62 | fn content_bounds(source: &str, range: TextRange) -> Option<(usize, usize)> { |
| 63 | let s = range.start().to_usize(); |
| 64 | let e = range.end().to_usize(); |
| 65 | if s >= e || e > source.len() { |
| 66 | return None; |
| 67 | } |
| 68 | let bytes = &source.as_bytes()[s..e]; |
| 69 | // Skip prefix (u, b, r, etc.) to find the first quote character. |
| 70 | let qi = bytes.iter().position(|&c| c == b'\'' || c == b'"')?; |
| 71 | let qc = bytes[qi]; |
| 72 | let ql = if bytes.get(qi + 1) == Some(&qc) && bytes.get(qi + 2) == Some(&qc) { |
| 73 | 3 |
| 74 | } else { |
| 75 | 1 |
| 76 | }; |
| 77 | let cs = s + qi + ql; |
| 78 | let ce = e.checked_sub(ql)?; |
| 79 | if cs <= ce { Some((cs, ce)) } else { None } |
| 80 | } |
| 81 | |
| 82 | /// Scan `source[start..end]` for the first invalid escape sequence. |
| 83 | /// Returns `Some((invalid_char, byte_offset_in_source))` for the first |