1use std::cmp;
2
3use super::wrap_map::{Edit as WrapEdit, Snapshot as WrapSnapshot};
4use buffer::Bias;
5use parking_lot::Mutex;
6use sum_tree::SumTree;
7
8struct BlockMap {
9 transforms: Mutex<SumTree<Transform>>,
10}
11
12struct BlockMapWriter<'a>(&'a mut BlockMap);
13
14struct BlockSnapshot {}
15
16#[derive(Clone)]
17struct Transform {
18 summary: TransformSummary,
19}
20
21#[derive(Copy, Clone, Debug, Default)]
22struct TransformSummary {
23 input_rows: u32,
24 output_rows: u32,
25}
26
27#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
28struct InputRow(u32);
29
30#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
31struct OutputRow(u32);
32
33impl BlockMap {
34 fn new(wrap_snapshot: WrapSnapshot) -> Self {
35 Self {
36 transforms: Mutex::new(SumTree::from_item(
37 Transform::isomorphic(wrap_snapshot.max_point().row() + 1),
38 &(),
39 )),
40 }
41 }
42
43 fn read(&self, wrap_snapshot: WrapSnapshot, edits: Vec<WrapEdit>) -> BlockSnapshot {
44 self.sync(wrap_snapshot, edits);
45 BlockSnapshot {}
46 }
47
48 fn write(&mut self, wrap_snapshot: WrapSnapshot, edits: Vec<WrapEdit>) -> BlockMapWriter {
49 self.sync(wrap_snapshot, edits);
50 BlockMapWriter(self)
51 }
52
53 fn sync(&self, wrap_snapshot: WrapSnapshot, edits: Vec<WrapEdit>) {
54 let transforms = self.transforms.lock();
55 let mut new_transforms = SumTree::new();
56 let mut cursor = transforms.cursor::<InputRow>();
57 let mut edits = edits.into_iter().peekable();
58 while let Some(mut edit) = edits.next() {
59 new_transforms.push_tree(
60 cursor.slice(&InputRow(edit.old.start), Bias::Left, &()),
61 &(),
62 );
63
64 let transform_start = cursor.start().0;
65 edit.new.start -= edit.old.start - transform_start;
66 edit.old.start = transform_start;
67
68 loop {
69 if edit.old.end > cursor.start().0 {
70 cursor.seek(&InputRow(edit.old.end), Bias::Left, &());
71 cursor.next(&());
72 let transform_end = cursor.start().0;
73 edit.new.end += transform_end - edit.old.end;
74 edit.old.end = transform_end;
75 }
76
77 if let Some(next_edit) = edits.peek() {
78 if edit.old.end >= next_edit.old.start {
79 edit.old.end = cmp::max(next_edit.old.end, edit.old.end);
80 edit.new.end += (edit.new.len() as i32 - edit.old.len() as i32) as u32;
81 edits.next();
82 } else {
83 break;
84 }
85 } else {
86 break;
87 }
88 }
89
90 // TODO: process injections
91
92 let new_transforms_end = new_transforms.summary().input_rows;
93 if new_transforms_end < edit.new.end {
94 new_transforms.push(
95 Transform::isomorphic(edit.new.end - new_transforms_end),
96 &(),
97 );
98 }
99 }
100 new_transforms.push_tree(cursor.suffix(&()), &());
101 }
102}
103
104impl Transform {
105 fn isomorphic(rows: u32) -> Self {
106 Self {
107 summary: TransformSummary {
108 input_rows: rows,
109 output_rows: rows,
110 },
111 }
112 }
113}
114
115impl sum_tree::Item for Transform {
116 type Summary = TransformSummary;
117
118 fn summary(&self) -> Self::Summary {
119 self.summary
120 }
121}
122
123impl sum_tree::Summary for TransformSummary {
124 type Context = ();
125
126 fn add_summary(&mut self, summary: &Self, _: &()) {
127 self.input_rows += summary.input_rows;
128 self.output_rows += summary.output_rows;
129 }
130}
131
132impl<'a> sum_tree::Dimension<'a, TransformSummary> for InputRow {
133 fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
134 self.0 += summary.input_rows;
135 }
136}
137
138impl<'a> sum_tree::Dimension<'a, TransformSummary> for OutputRow {
139 fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
140 self.0 += summary.output_rows;
141 }
142}