1use std::{
2 cmp::Ordering,
3 fmt, io,
4 io::BufRead,
5 iter,
6 ops::{Add, AddAssign, Sub, SubAssign},
7};
8
9#[derive(Clone, Debug, Eq, Hash, PartialEq)]
10pub struct Text {
11 lines: Vec<String>,
12}
13
14impl Text {
15 pub fn new() -> Self {
16 Self::default()
17 }
18
19 pub fn newline() -> Self {
20 Self {
21 lines: vec![String::new(), String::new()],
22 }
23 }
24
25 pub fn from_buf_reader<R>(reader: R) -> io::Result<Self>
26 where
27 R: BufRead,
28 {
29 Ok(Self {
30 lines: reader.lines().collect::<Result<_, _>>()?,
31 })
32 }
33
34 pub fn is_empty(&self) -> bool {
35 self.length() == Length::zero()
36 }
37
38 pub fn length(&self) -> Length {
39 Length {
40 line_count: self.lines.len() - 1,
41 byte_count: self.lines.last().unwrap().len(),
42 }
43 }
44
45 pub fn to_single_char(&self) -> Option<char> {
46 if self.lines.len() > 1 {
47 return None;
48 }
49 let mut chars = self.lines[0].chars();
50 match (chars.next(), chars.next()) {
51 (Some(char), None) => Some(char),
52 _ => None,
53 }
54 }
55
56 pub fn as_lines(&self) -> &[String] {
57 &self.lines
58 }
59
60 pub fn slice(&self, start: Position, length: Length) -> Self {
61 let end = start + length;
62 let mut lines = Vec::new();
63 if start.line_index == end.line_index {
64 lines.push(self.lines[start.line_index][start.byte_index..end.byte_index].to_string());
65 } else {
66 lines.reserve(end.line_index - start.line_index + 1);
67 lines.push(self.lines[start.line_index][start.byte_index..].to_string());
68 lines.extend(
69 self.lines[start.line_index + 1..end.line_index]
70 .iter()
71 .cloned(),
72 );
73 lines.push(self.lines[end.line_index][..end.byte_index].to_string());
74 }
75 Text { lines }
76 }
77
78 pub fn apply_change(&mut self, change: Change) {
79 match change {
80 Change::Insert(position, text) => self.insert(position, text),
81 Change::Delete(start, length) => self.delete(start, length),
82 }
83 }
84
85 pub fn into_lines(self) -> Vec<String> {
86 self.lines
87 }
88
89 fn insert(&mut self, point: Position, mut text: Self) {
90 if text.length().line_count == 0 {
91 self.lines[point.line_index].replace_range(
92 point.byte_index..point.byte_index,
93 text.lines.first().unwrap(),
94 );
95 } else {
96 text.lines
97 .first_mut()
98 .unwrap()
99 .replace_range(..0, &self.lines[point.line_index][..point.byte_index]);
100 text.lines
101 .last_mut()
102 .unwrap()
103 .push_str(&self.lines[point.line_index][point.byte_index..]);
104 self.lines
105 .splice(point.line_index..point.line_index + 1, text.lines);
106 }
107 }
108
109 fn delete(&mut self, start: Position, length: Length) {
110 let end = start + length;
111 if start.line_index == end.line_index {
112 self.lines[start.line_index].replace_range(start.byte_index..end.byte_index, "");
113 } else {
114 let mut line = self.lines[start.line_index][..start.byte_index].to_string();
115 line.push_str(&self.lines[end.line_index][end.byte_index..]);
116 self.lines
117 .splice(start.line_index..end.line_index + 1, iter::once(line));
118 }
119 }
120}
121
122impl Default for Text {
123 fn default() -> Self {
124 Self {
125 lines: vec![String::new()],
126 }
127 }
128}
129
130impl fmt::Display for Text {
131 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132 let (last_line, remaining_lines) = self.lines.split_last().unwrap();
133 for line in remaining_lines {
134 writeln!(f, "{}", line)?;
135 }
136 write!(f, "{}", last_line)
137 }
138}
139
140impl From<char> for Text {
141 fn from(char: char) -> Self {
142 Self {
143 lines: vec![String::from(char)],
144 }
145 }
146}
147
148impl From<&str> for Text {
149 fn from(string: &str) -> Self {
150 Self {
151 lines: string.split('\n').map(|string| string.to_owned()).collect(),
152 }
153 }
154}
155
156impl From<&String> for Text {
157 fn from(string: &String) -> Self {
158 string.as_str().into()
159 }
160}
161
162impl From<String> for Text {
163 fn from(string: String) -> Self {
164 string.as_str().into()
165 }
166}
167
168impl FromIterator<char> for Text {
169 fn from_iter<I>(iter: I) -> Self
170 where
171 I: IntoIterator<Item = char>,
172 {
173 Text::from(iter.into_iter().collect::<String>())
174 }
175}
176
177#[derive(Clone, Debug, Eq, Hash, PartialEq)]
178pub struct Edit {
179 pub change: Change,
180 pub drift: Drift,
181}
182
183impl Edit {
184 pub fn invert(self, text: &Text) -> Self {
185 Self {
186 change: self.change.invert(text),
187 drift: self.drift,
188 }
189 }
190}
191
192#[derive(Clone, Debug, Eq, Hash, PartialEq)]
193pub enum Change {
194 Insert(Position, Text),
195 Delete(Position, Length),
196}
197
198impl Change {
199 pub fn invert(self, text: &Text) -> Self {
200 match self {
201 Self::Insert(position, text) => Change::Delete(position, text.length()),
202 Self::Delete(start, length) => Change::Insert(start, text.slice(start, length)),
203 }
204 }
205}
206
207#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
208pub struct Position {
209 pub line_index: usize,
210 pub byte_index: usize,
211}
212
213impl Position {
214 pub fn zero() -> Self {
215 Self::default()
216 }
217
218 pub fn apply_edit(self, edit: &Edit) -> Self {
219 match edit.change {
220 Change::Insert(point, ref text) => match self.cmp(&point) {
221 Ordering::Less => self,
222 Ordering::Equal => match edit.drift {
223 Drift::Before => point + text.length() + (self - point),
224 Drift::After => self,
225 },
226 Ordering::Greater => point + text.length() + (self - point),
227 },
228 Change::Delete(start, length) => {
229 let end = start + length;
230 if self < start {
231 self
232 } else {
233 start + (self - end.min(self))
234 }
235 }
236 }
237 }
238}
239
240impl Add<Length> for Position {
241 type Output = Self;
242
243 fn add(self, length: Length) -> Self::Output {
244 if length.line_count == 0 {
245 Self {
246 line_index: self.line_index,
247 byte_index: self.byte_index + length.byte_count,
248 }
249 } else {
250 Self {
251 line_index: self.line_index + length.line_count,
252 byte_index: length.byte_count,
253 }
254 }
255 }
256}
257
258impl AddAssign<Length> for Position {
259 fn add_assign(&mut self, length: Length) {
260 *self = *self + length;
261 }
262}
263
264impl Sub for Position {
265 type Output = Length;
266
267 fn sub(self, other: Self) -> Self::Output {
268 if self.line_index == other.line_index {
269 Length {
270 line_count: 0,
271 byte_count: self.byte_index - other.byte_index,
272 }
273 } else {
274 Length {
275 line_count: self.line_index - other.line_index,
276 byte_count: self.byte_index,
277 }
278 }
279 }
280}
281
282#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
283pub struct Length {
284 pub line_count: usize,
285 pub byte_count: usize,
286}
287
288impl Length {
289 pub fn zero() -> Length {
290 Self::default()
291 }
292}
293
294impl Add for Length {
295 type Output = Length;
296
297 fn add(self, other: Self) -> Self::Output {
298 if other.line_count == 0 {
299 Self {
300 line_count: self.line_count,
301 byte_count: self.byte_count + other.byte_count,
302 }
303 } else {
304 Self {
305 line_count: self.line_count + other.line_count,
306 byte_count: other.byte_count,
307 }
308 }
309 }
310}
311
312impl AddAssign for Length {
313 fn add_assign(&mut self, other: Self) {
314 *self = *self + other;
315 }
316}
317
318impl Sub for Length {
319 type Output = Length;
320
321 fn sub(self, other: Self) -> Self::Output {
322 if self.line_count == other.line_count {
323 Self {
324 line_count: 0,
325 byte_count: self.byte_count - other.byte_count,
326 }
327 } else {
328 Self {
329 line_count: self.line_count - other.line_count,
330 byte_count: self.byte_count,
331 }
332 }
333 }
334}
335
336impl SubAssign for Length {
337 fn sub_assign(&mut self, other: Self) {
338 *self = *self - other;
339 }
340}
341
342#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
343pub enum Drift {
344 Before,
345 After,
346}