1use crate::input_text::buffer::REALLY_MAX_LENGTH;
18use std::ops::Range;
19
20#[derive(Clone)]
21pub struct ReplaceOp<'a> {
22 what: Range<usize>,
23 with: ReplaceTgt<'a>,
24}
25
26#[derive(Clone)]
27enum ReplaceTgt<'a> {
28 Ref(&'a str),
29 Char(char),
30 Str(String),
31}
32
33pub struct InputEditor<'a> {
34 replaces: &'a mut Vec<ReplaceOp<'a>>,
35}
36
37impl<'a> InputEditor<'a> {
38 pub(super) fn new(replaces: &'a mut Vec<ReplaceOp<'a>>) -> InputEditor {
39 InputEditor { replaces }
40 }
41
42 pub fn replace_ref(&mut self, range: Range<usize>, result: &'a str) {
44 let op = ReplaceOp {
45 what: range,
46 with: ReplaceTgt::Ref(result),
47 };
48 self.replaces.push(op);
49 }
50
51 pub fn replace_char(&mut self, range: Range<usize>, result: char) {
53 let op = ReplaceOp {
54 what: range,
55 with: ReplaceTgt::Char(result),
56 };
57 self.replaces.push(op);
58 }
59
60 pub fn replace_own(&mut self, range: Range<usize>, result: String) {
62 let op = ReplaceOp {
63 what: range,
64 with: ReplaceTgt::Str(result),
65 };
66 self.replaces.push(op);
67 }
68
69 pub fn replace_char_iter<It>(&mut self, range: Range<usize>, ch: char, mut rest: It)
71 where
72 It: Iterator<Item = char>,
73 {
74 match rest.next() {
75 None => self.replace_char(range, ch),
76 Some(ch2) => {
77 let mut s = String::with_capacity(12); s.push(ch);
79 s.push(ch2);
80 s.extend(rest);
81 self.replace_own(range, s)
82 }
83 }
84 }
85}
86
87pub fn resolve_edits(
91 source: &str,
92 source_mapping: &Vec<usize>,
93 target: &mut String,
94 target_mapping: &mut Vec<usize>,
95 edits: &mut Vec<ReplaceOp>,
96) -> usize {
97 let mut start: usize = 0;
98 let mut cur_len: isize = source.len() as isize;
99 for edit in edits.drain(..) {
100 target.push_str(&source[start..edit.what.start]);
101 target_mapping.extend(source_mapping[start..edit.what.start].iter());
102 start = edit.what.end;
103 cur_len += match edit.with {
104 ReplaceTgt::Str(s) => {
105 add_replace(source_mapping, target, target_mapping, edit.what, &s)
106 }
107 ReplaceTgt::Ref(s) => add_replace(source_mapping, target, target_mapping, edit.what, s),
108 ReplaceTgt::Char(c) => add_replace(
109 source_mapping,
110 target,
111 target_mapping,
112 edit.what,
113 c.encode_utf8(&mut [0; 4]),
114 ),
115 };
116 if cur_len > REALLY_MAX_LENGTH as isize {
117 return cur_len as usize;
118 }
119 }
120 target.push_str(&source[start..]);
121 target_mapping.extend(source_mapping[start..].iter());
122 if let Some(v) = target_mapping.first_mut() {
124 *v = 0;
125 }
126 cur_len as usize
127}
128
129fn add_replace(
130 source_mapping: &Vec<usize>,
131 target: &mut String,
132 target_mapping: &mut Vec<usize>,
133 what: Range<usize>,
134 with: &str,
135) -> isize {
136 if with.is_empty() {
137 return -(what.len() as isize);
138 }
139 target.push_str(with);
140
141 target_mapping.push(source_mapping[what.start]);
143 let pos = source_mapping[what.end];
144 for _ in 1..with.len() {
145 target_mapping.push(pos);
146 }
147 with.len() as isize - what.len() as isize
148}
149
150#[cfg(test)]
151mod test {
152 use super::super::InputBuffer;
153 use crate::input_text::InputTextIndex;
154
155 #[test]
156 fn edit_ref_1() {
157 let mut buffer = InputBuffer::from("宇宙人");
158 buffer
159 .with_editor(|_, mut r| {
160 r.replace_ref(3..6, "銀");
161 Ok(r)
162 })
163 .expect("should not break");
164 assert_eq!(0, buffer.replaces.len());
165 assert_eq!(buffer.current(), "宇銀人");
166 assert_eq!(buffer.orig_slice(3..6), "宙");
167 }
168
169 #[test]
170 fn edit_char_1() {
171 let mut buffer = InputBuffer::from("宇宙人");
172 buffer
173 .with_editor(|_, mut r| {
174 r.replace_char(3..6, '銀');
175 Ok(r)
176 })
177 .expect("should not break");
178 assert_eq!(0, buffer.replaces.len());
179 assert_eq!(buffer.current(), "宇銀人");
180 assert_eq!(buffer.orig_slice(3..6), "宙");
181 }
182
183 #[test]
184 fn edit_ref_2_borrow() {
185 let s = String::from("銀");
186 let mut buffer = InputBuffer::from("宇宙人");
187 buffer
188 .with_editor(|_, mut r| {
189 r.replace_ref(3..6, &s);
190 Ok(r)
191 })
192 .expect("should not break");
193 assert_eq!(0, buffer.replaces.len());
194 assert_eq!(buffer.current(), "宇銀人");
195 }
196
197 #[test]
198 fn edit_str_1() {
199 let mut buffer = InputBuffer::from("宇宙人");
200 buffer
201 .with_editor(|_, mut r| {
202 r.replace_own(3..6, String::from("銀"));
203 Ok(r)
204 })
205 .expect("should not break");
206 assert_eq!(0, buffer.replaces.len());
207 assert_eq!(buffer.current(), "宇銀人");
208 assert_eq!(buffer.orig_slice(3..6), "宙");
209 }
210
211 #[test]
212 fn replace_start_w_longer() {
213 let mut buffer = InputBuffer::from("宇宙人");
214 buffer
215 .with_editor(|_, mut r| {
216 r.replace_ref(0..3, "銀河");
217 Ok(r)
218 })
219 .expect("should not break");
220 assert_eq!(0, buffer.replaces.len());
221 assert_eq!(buffer.m2o, &[0, 3, 3, 3, 3, 3, 3, 4, 5, 6, 7, 8, 9]);
222 assert_eq!(buffer.current(), "銀河宙人");
223 assert_eq!(buffer.orig_slice(0..6), "宇");
224 assert_eq!(buffer.orig_slice(0..3), "宇");
225 assert_eq!(buffer.orig_slice(3..6), "");
226 }
227
228 #[test]
229 fn replace_mid_w_longer() {
230 let mut buffer = InputBuffer::from("宇宙人");
231 buffer
232 .with_editor(|_, mut r| {
233 r.replace_ref(3..6, "銀河");
234 Ok(r)
235 })
236 .expect("should not break");
237 assert_eq!(0, buffer.replaces.len());
238 assert_eq!(buffer.m2o, &[0, 1, 2, 3, 6, 6, 6, 6, 6, 6, 7, 8, 9]);
239 assert_eq!(buffer.current(), "宇銀河人");
240 assert_eq!(buffer.orig_slice(3..9), "宙");
241 assert_eq!(buffer.orig_slice(3..6), "宙");
242 assert_eq!(buffer.orig_slice(6..9), "");
243 }
244
245 #[test]
246 fn replace_end_w_longer() {
247 let mut buffer = InputBuffer::from("宇宙人");
248 buffer
249 .with_editor(|_, mut r| {
250 r.replace_ref(6..9, "銀河");
251 Ok(r)
252 })
253 .expect("should not break");
254 assert_eq!(0, buffer.replaces.len());
255 assert_eq!(buffer.m2o, &[0, 1, 2, 3, 4, 5, 6, 9, 9, 9, 9, 9, 9]);
256 assert_eq!(buffer.current(), "宇宙銀河");
257 assert_eq!(buffer.orig_slice(6..12), "人");
258 assert_eq!(buffer.orig_slice(6..9), "人");
259 assert_eq!(buffer.orig_slice(9..12), "");
260 }
261
262 #[test]
263 fn replace_start_w_shorter() {
264 let mut buffer = InputBuffer::from("宇宙人");
265 buffer
266 .with_editor(|_, mut r| {
267 r.replace_ref(0..6, "河");
268 Ok(r)
269 })
270 .expect("should not break");
271 assert_eq!(0, buffer.replaces.len());
272 assert_eq!(buffer.current(), "河人");
273 assert_eq!(buffer.m2o, &[0, 6, 6, 6, 7, 8, 9]);
274 assert_eq!(buffer.orig_slice(0..3), "宇宙");
275 assert_eq!(buffer.orig_slice(3..6), "人");
276 }
277
278 #[test]
279 fn replace_end_w_shorter() {
280 let mut buffer = InputBuffer::from("宇宙人");
281 buffer
282 .with_editor(|_, mut r| {
283 r.replace_ref(3..9, "河");
284 Ok(r)
285 })
286 .expect("should not break");
287 assert_eq!(0, buffer.replaces.len());
288 assert_eq!(buffer.current(), "宇河");
289 assert_eq!(buffer.m2o, &[0, 1, 2, 3, 9, 9, 9]);
290 assert_eq!(buffer.orig_slice(0..3), "宇");
291 assert_eq!(buffer.orig_slice(3..6), "宙人");
292 }
293
294 #[test]
295 fn replace_start_w_none() {
296 let mut buffer = InputBuffer::from("宇宙人");
297 buffer
298 .with_editor(|_, mut r| {
299 r.replace_ref(0..6, "");
300 Ok(r)
301 })
302 .expect("should not break");
303 assert_eq!(0, buffer.replaces.len());
304 assert_eq!(buffer.current(), "人");
305 assert_eq!(buffer.m2o, &[0, 7, 8, 9]);
306 assert_eq!(buffer.orig_slice(0..3), "宇宙人");
307 }
308
309 #[test]
310 fn replace_start_w_none_2() {
311 let mut buffer = InputBuffer::from("宇宙人");
312 buffer
313 .with_editor(|_, mut r| {
314 r.replace_ref(0..3, "");
315 Ok(r)
316 })
317 .expect("should not break");
318 assert_eq!(0, buffer.replaces.len());
319 assert_eq!(buffer.current(), "宙人");
320 assert_eq!(buffer.m2o, &[0, 4, 5, 6, 7, 8, 9]);
321 assert_eq!(buffer.orig_slice(0..3), "宇宙");
322 assert_eq!(buffer.orig_slice(3..6), "人");
323 }
324
325 #[test]
326 fn replace_end_w_none() {
327 let mut buffer = InputBuffer::from("宇宙人");
328 buffer
329 .with_editor(|_, mut r| {
330 r.replace_ref(3..9, "");
331 Ok(r)
332 })
333 .expect("should not break");
334 assert_eq!(0, buffer.replaces.len());
335 assert_eq!(buffer.current(), "宇");
336 assert_eq!(buffer.m2o, &[0, 1, 2, 9]);
337 assert_eq!(buffer.orig_slice(0..3), "宇宙人");
338 }
339
340 #[test]
341 fn replace_diff_width() {
342 let mut buffer = InputBuffer::from("âbC1あ");
343 buffer
344 .with_editor(|_, mut r| {
345 r.replace_ref(0..2, "a");
346 r.replace_ref(2..5, "b");
347 r.replace_ref(5..6, "c");
348 Ok(r)
349 })
350 .expect("should not break");
351 assert_eq!(0, buffer.replaces.len());
352 assert_eq!(buffer.current(), "abc1あ");
353 assert_eq!(buffer.m2o, &[0, 2, 5, 6, 7, 8, 9, 10]);
354 assert_eq!(buffer.orig_slice(0..3), "âbC");
355 assert_eq!(buffer.orig_slice(0..1), "â");
356 assert_eq!(buffer.orig_slice(1..2), "b");
357 assert_eq!(buffer.orig_slice(2..3), "C");
358 }
359
360 #[test]
361 fn replace_with_more_cnt() {
362 let mut buffer = InputBuffer::from("あ");
363 buffer
364 .with_editor(|_, mut r| {
365 r.replace_ref(0..3, "abc");
366 Ok(r)
367 })
368 .expect("should not break");
369 assert_eq!(0, buffer.replaces.len());
370 assert_eq!(buffer.current(), "abc");
371 assert_eq!(buffer.m2o, &[0, 3, 3, 3]);
372 assert_eq!(buffer.orig_slice(0..3), "あ");
373 assert_eq!(buffer.orig_slice(0..1), "あ");
374 assert_eq!(buffer.orig_slice(1..2), "");
375 assert_eq!(buffer.orig_slice(2..3), "");
376 }
377}