1use serde::{Deserialize, Serialize};
2
3use ruff_source_file::{LineColumn, OneIndexed, SourceLocation};
4
5#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
10pub struct NotebookIndex {
11 pub(super) cell_starts: Vec<CellStart>,
15}
16
17impl NotebookIndex {
18 fn find_cell(&self, row: OneIndexed) -> Option<CellStart> {
19 match self
20 .cell_starts
21 .binary_search_by_key(&row, |start| start.start_row)
22 {
23 Ok(cell_index) => Some(self.cell_starts[cell_index]),
24 Err(insertion_point) => Some(self.cell_starts[insertion_point.checked_sub(1)?]),
25 }
26 }
27
28 pub fn cell(&self, row: OneIndexed) -> Option<OneIndexed> {
30 self.find_cell(row).map(|start| start.raw_cell_index)
31 }
32
33 pub fn cell_row(&self, row: OneIndexed) -> Option<OneIndexed> {
36 self.find_cell(row)
37 .map(|start| OneIndexed::from_zero_indexed(row.get() - start.start_row.get()))
38 }
39
40 pub fn iter(&self) -> impl Iterator<Item = CellStart> + '_ {
44 self.cell_starts.iter().copied()
45 }
46
47 pub fn translate_line_column(&self, source_location: &LineColumn) -> LineColumn {
52 LineColumn {
53 line: self
54 .cell_row(source_location.line)
55 .unwrap_or(OneIndexed::MIN),
56 column: source_location.column,
57 }
58 }
59
60 pub fn translate_source_location(&self, source_location: &SourceLocation) -> SourceLocation {
65 SourceLocation {
66 line: self
67 .cell_row(source_location.line)
68 .unwrap_or(OneIndexed::MIN),
69 character_offset: source_location.character_offset,
70 }
71 }
72}
73
74#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
75pub struct CellStart {
76 pub(super) start_row: OneIndexed,
79
80 pub(super) raw_cell_index: OneIndexed,
82}
83
84impl CellStart {
85 pub fn start_row(&self) -> OneIndexed {
86 self.start_row
87 }
88
89 pub fn cell_index(&self) -> OneIndexed {
90 self.raw_cell_index
91 }
92}