MCPcopy Index your code
hub / github.com/RustPython/RustPython / first_invalid_escape

Function first_invalid_escape

crates/vm/src/vm/compile.rs:92–170  ·  view source on GitHub ↗

Scan `source[start..end]` for the first invalid escape sequence. Returns `Some((invalid_char, byte_offset_in_source))` for the first invalid escape found, or `None` if all escapes are valid. When `is_bytes` is true, `\u`, `\U`, and `\N` are treated as invalid (bytes literals only support byte-oriented escapes). Only reports the **first** invalid escape per string literal, matching `_PyUnicode_De

(
        source: &str,
        start: usize,
        end: usize,
        is_bytes: bool,
    )

Source from the content-addressed store, hash-verified

90 /// `_PyUnicode_DecodeUnicodeEscapeInternal2` which stores only the first
91 /// `first_invalid_escape_char`.
92 fn first_invalid_escape(
93 source: &str,
94 start: usize,
95 end: usize,
96 is_bytes: bool,
97 ) -> Option<(char, usize)> {
98 let raw = &source[start..end];
99 let mut chars = raw.char_indices().peekable();
100 while let Some((i, ch)) = chars.next() {
101 if ch != '\\' {
102 continue;
103 }
104 let Some((_, next)) = chars.next() else {
105 break;
106 };
107 let valid = match next {
108 '\\' | '\'' | '"' | 'a' | 'b' | 'f' | 'n' | 'r' | 't' | 'v' => true,
109 '\n' => true,
110 '\r' => {
111 if matches!(chars.peek(), Some(&(_, '\n'))) {
112 chars.next();
113 }
114 true
115 }
116 '0'..='7' => {
117 for _ in 0..2 {
118 if matches!(chars.peek(), Some(&(_, '0'..='7'))) {
119 chars.next();
120 } else {
121 break;
122 }
123 }
124 true
125 }
126 'x' | 'u' | 'U' => {
127 // \u and \U are only valid in string literals, not bytes
128 if is_bytes && next != 'x' {
129 false
130 } else {
131 let count = match next {
132 'x' => 2,
133 'u' => 4,
134 'U' => 8,
135 _ => unreachable!(),
136 };
137 for _ in 0..count {
138 if chars.peek().is_some_and(|&(_, c)| c.is_ascii_hexdigit()) {
139 chars.next();
140 } else {
141 break;
142 }
143 }
144 true
145 }
146 }
147 'N' => {
148 // \N{name} is only valid in string literals, not bytes
149 if is_bytes {

Callers 2

check_quoted_literalMethod · 0.85
check_fstring_literalMethod · 0.85

Calls 3

SomeClass · 0.50
nextMethod · 0.45
peekMethod · 0.45

Tested by

no test coverage detected