Description: Use Debian-packaged line-index and text-size crates
 instead of the rustpython-parser-vendored crate.
Forwarded: not-needed
Author: Jelmer Vernooij <jelmer@debian.org>
Last-Update: 2026-06-17

Index: rustpython-parser-core/Cargo.toml
===================================================================
--- rustpython-parser-core.orig/Cargo.toml
+++ rustpython-parser-core/Cargo.toml
@@ -29,15 +29,18 @@ repository = "https://github.com/RustPyt
 name = "rustpython_parser_core"
 path = "src/lib.rs"
 
+[dependencies.line-index]
+version = "0.1.2"
+
+[dependencies.text-size]
+version = "1.1.1"
+
 [dependencies.is-macro]
 version = "0.3.0"
 
 [dependencies.memchr]
 version = "2.5.0"
 
-[dependencies.rustpython-parser-vendored]
-version = "0.4.0"
-
 [dependencies.serde]
 version = "1.0.133"
 features = ["derive"]
Index: rustpython-parser-core/src/lib.rs
===================================================================
--- rustpython-parser-core.orig/src/lib.rs
+++ rustpython-parser-core/src/lib.rs
@@ -5,12 +5,11 @@ mod error;
 mod format;
 pub mod mode;
 #[cfg(feature = "location")]
+pub mod source_location;
+#[cfg(feature = "location")]
 pub mod source_code;
 
 pub use error::BaseError;
 pub use format::ConversionFlag;
 pub use mode::Mode;
-
-#[cfg(feature = "location")]
-pub use rustpython_parser_vendored::source_location;
-pub use rustpython_parser_vendored::text_size;
+pub use text_size;
Index: rustpython-parser-core/src/source_location.rs
===================================================================
--- /dev/null
+++ rustpython-parser-core/src/source_location.rs
@@ -0,0 +1,185 @@
+use crate::text_size::{TextLen, TextRange, TextSize};
+use std::fmt::{Debug, Formatter};
+use std::num::NonZeroU32;
+
+pub mod newlines {
+    pub fn find_newline(source: &str) -> Option<(usize, &str)> {
+        let bytes = source.as_bytes();
+        let pos = bytes.iter().position(|byte| *byte == b'\n' || *byte == b'\r')?;
+        let ending = if bytes[pos] == b'\r' && bytes.get(pos + 1) == Some(&b'\n') {
+            "\r\n"
+        } else if bytes[pos] == b'\r' {
+            "\r"
+        } else {
+            "\n"
+        };
+        Some((pos, ending))
+    }
+
+    pub struct UniversalNewlineIterator<'a> {
+        source: &'a str,
+    }
+
+    impl<'a> From<&'a str> for UniversalNewlineIterator<'a> {
+        fn from(source: &'a str) -> Self {
+            Self { source }
+        }
+    }
+
+    impl<'a> Iterator for UniversalNewlineIterator<'a> {
+        type Item = &'a str;
+
+        fn next(&mut self) -> Option<Self::Item> {
+            let (pos, ending) = find_newline(self.source)?;
+            let rest = pos + ending.len();
+            self.source = &self.source[rest..];
+            Some(ending)
+        }
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct OneIndexed(NonZeroU32);
+
+impl OneIndexed {
+    pub const MIN: Self = Self(NonZeroU32::MIN);
+    pub const MAX: Self = Self(NonZeroU32::MAX);
+
+    pub const fn new(value: u32) -> Option<Self> {
+        match NonZeroU32::new(value) {
+            Some(value) => Some(Self(value)),
+            None => None,
+        }
+    }
+
+    pub const fn from_zero_indexed(value: u32) -> Self {
+        match NonZeroU32::new(value.saturating_add(1)) {
+            Some(value) => Self(value),
+            None => Self::MAX,
+        }
+    }
+
+    pub const fn get(self) -> u32 {
+        self.0.get()
+    }
+
+    pub const fn to_zero_indexed(self) -> u32 {
+        self.0.get() - 1
+    }
+
+    pub const fn to_usize(self) -> usize {
+        self.0.get() as usize
+    }
+
+    pub const fn to_zero_indexed_usize(self) -> usize {
+        self.to_zero_indexed() as usize
+    }
+
+    pub const fn saturating_add(self, rhs: u32) -> Self {
+        Self::from_zero_indexed(self.to_zero_indexed().saturating_add(rhs))
+    }
+}
+
+impl std::fmt::Display for OneIndexed {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        std::fmt::Display::fmt(&self.get(), f)
+    }
+}
+
+#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Copy)]
+pub struct SourceLocation {
+    pub row: OneIndexed,
+    pub column: OneIndexed,
+}
+
+impl Default for SourceLocation {
+    fn default() -> Self {
+        Self {
+            row: OneIndexed::MIN,
+            column: OneIndexed::MIN,
+        }
+    }
+}
+
+impl Debug for SourceLocation {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("SourceLocation")
+            .field("row", &self.row.get())
+            .field("column", &self.column.get())
+            .finish()
+    }
+}
+
+#[derive(Debug, Clone)]
+pub struct LineIndex {
+    inner: line_index::LineIndex,
+    len: TextSize,
+}
+
+impl LineIndex {
+    pub fn from_source_text(text: &str) -> Self {
+        Self {
+            inner: line_index::LineIndex::new(text),
+            len: text.text_len(),
+        }
+    }
+
+    pub fn source_location(&self, offset: TextSize, content: &str) -> SourceLocation {
+        let line_col = self.inner.line_col(offset);
+        let line_start = self.line_start(OneIndexed::from_zero_indexed(line_col.line), content);
+        let column = if content[usize::from(line_start)..usize::from(offset)].is_ascii() {
+            line_col.col
+        } else {
+            content[usize::from(line_start)..usize::from(offset)]
+                .chars()
+                .count() as u32
+        };
+        SourceLocation {
+            row: OneIndexed::from_zero_indexed(line_col.line),
+            column: OneIndexed::from_zero_indexed(column),
+        }
+    }
+
+    pub fn line_index(&self, offset: TextSize) -> OneIndexed {
+        OneIndexed::from_zero_indexed(self.inner.line_col(offset).line)
+    }
+
+    pub fn line_start(&self, line: OneIndexed, _contents: &str) -> TextSize {
+        self.inner
+            .line(line.to_zero_indexed())
+            .map_or(self.len, |range| range.start())
+    }
+
+    pub fn line_end(&self, line: OneIndexed, _contents: &str) -> TextSize {
+        self.inner
+            .line(line.to_zero_indexed())
+            .map_or(self.len, |range| range.end())
+    }
+
+    pub fn line_range(&self, line: OneIndexed, contents: &str) -> TextRange {
+        TextRange::new(self.line_start(line, contents), self.line_end(line, contents))
+    }
+
+    pub fn line_count(&self) -> usize {
+        self.inner.line_col(self.len).line as usize + 1
+    }
+}
+
+#[derive(Debug)]
+pub struct SourceCode<'src, 'index> {
+    text: &'src str,
+    index: &'index LineIndex,
+}
+
+impl<'src, 'index> SourceCode<'src, 'index> {
+    pub fn new(content: &'src str, index: &'index LineIndex) -> Self {
+        Self {
+            text: content,
+            index,
+        }
+    }
+
+    pub fn source_location(&self, offset: TextSize) -> SourceLocation {
+        self.index.source_location(offset, self.text)
+    }
+}
Index: rustpython-parser-core/src/source_code.rs
===================================================================
--- rustpython-parser-core.orig/src/source_code.rs
+++ rustpython-parser-core/src/source_code.rs
@@ -53,7 +53,7 @@ impl<'a> RandomLocator<'a> {
     }
 
     pub fn locate(&mut self, offset: crate::text_size::TextSize) -> SourceLocation {
-        let offset = offset.to_u32().into();
+        let offset = u32::from(offset).into();
         self.to_source_code().source_location(offset)
     }
 
@@ -141,7 +141,7 @@ impl<'a> LinearLocator<'a> {
             "{:?} -> {:?} {}",
             self.state.cursor,
             offset,
-            &self.source[offset.to_usize()..self.state.cursor.to_usize()]
+            &self.source[usize::from(offset)..usize::from(self.state.cursor)]
         );
         let (column, new_state) = self.locate_inner(offset);
         if let Some(state) = new_state {
@@ -170,20 +170,20 @@ impl<'a> LinearLocator<'a> {
     ) -> (OneIndexed, Option<LinearLocatorState>) {
         let (column, new_state) = if let Some(new_line_start) = self.state.new_line_start(offset) {
             // not fit in current line
-            let focused = &self.source[new_line_start.to_usize()..offset.to_usize()];
+            let focused = &self.source[usize::from(new_line_start)..usize::from(offset)];
             let (lines, line_start, column) =
                 if let Some(last_newline) = memrchr2(b'\r', b'\n', focused.as_bytes()) {
-                    let last_newline = new_line_start.to_usize() + last_newline;
+                    let last_newline = usize::from(new_line_start) + last_newline;
                     let lines = UniversalNewlineIterator::from(
-                        &self.source[self.state.cursor.to_usize()..last_newline + 1],
+                        &self.source[usize::from(self.state.cursor)..last_newline + 1],
                     )
                     .count();
                     let line_start = last_newline as u32 + 1;
-                    let column = offset.to_u32() - line_start;
+                    let column = u32::from(offset) - line_start;
                     (lines as u32, line_start, column)
                 } else {
-                    let column = (offset - new_line_start).to_u32();
-                    (1, new_line_start.to_u32(), column)
+                    let column = u32::from(offset - new_line_start);
+                    (1, u32::from(new_line_start), column)
                 };
             let line_number = self.state.line_number.saturating_add(lines);
             let (line_end, is_ascii) = if let Some((newline, line_ending)) =
@@ -209,14 +209,14 @@ impl<'a> LinearLocator<'a> {
             };
             (column, Some(state))
         } else {
-            let column = (offset - self.state.line_start).to_u32();
+            let column = u32::from(offset - self.state.line_start);
             (column, None)
         };
         let state = new_state.as_ref().unwrap_or(&self.state);
         let column = if state.is_ascii {
             column
         } else {
-            self.source[state.line_start.to_usize()..][..column as usize]
+            self.source[usize::from(state.line_start)..][..column as usize]
                 .chars()
                 .count() as u32
         };
@@ -232,9 +232,9 @@ impl<'a> LinearLocator<'a> {
                 location,
                 source_code.source_location(offset),
                 "input: {} -> {} {}",
-                self.state.cursor.to_usize(),
-                offset.to_usize(),
-                &self.source[self.state.cursor.to_usize()..offset.to_usize()]
+                usize::from(self.state.cursor),
+                usize::from(offset),
+                &self.source[usize::from(self.state.cursor)..usize::from(offset)]
             );
         }
         (column, new_state)
