string_wizard/magic_string/
update.rs1use crate::{CowStr, MagicString, chunk::EditOptions};
2
3#[derive(Debug, Default, Clone)]
4pub struct UpdateOptions {
5 pub keep_original: bool,
7
8 pub overwrite: bool,
10}
11
12impl<'text> MagicString<'text> {
13 pub fn update(
15 &mut self,
16 start: u32,
17 end: u32,
18 content: impl Into<CowStr<'text>>,
19 ) -> Result<&mut Self, String> {
20 self.update_with(start, end, content, Default::default())
21 }
22
23 pub fn update_with(
24 &mut self,
25 start: u32,
26 end: u32,
27 content: impl Into<CowStr<'text>>,
28 opts: UpdateOptions,
29 ) -> Result<&mut Self, String> {
30 self.inner_update_with(start, end, content.into(), opts, true)
31 }
32
33 pub(super) fn inner_update_with(
36 &mut self,
37 start: u32,
38 end: u32,
39 content: CowStr<'text>,
40 opts: UpdateOptions,
41 error_if_start_equal_end: bool,
42 ) -> Result<&mut Self, String> {
43 if error_if_start_equal_end && start == end {
44 return Err(
45 "Cannot overwrite a zero-length range – use appendLeft or prependRight instead".to_string(),
46 );
47 }
48 if start >= end {
49 return Err(format!("end must be greater than start, got start: {start}, end: {end}"));
50 }
51 self.split_at(start)?;
52 self.split_at(end)?;
53
54 if opts.keep_original {
58 self.store_name(start, end);
59 }
60
61 let start_idx = self.chunk_by_start.get(&start).copied().unwrap();
62 let end_idx = self.chunk_by_end.get(&end).copied().unwrap();
63
64 if start_idx != end_idx {
65 let mut chunk_idx = start_idx;
75 loop {
76 let next_in_list = self.chunks[chunk_idx].next;
77 let chunk_end = self.chunks[chunk_idx].end();
78 let next_by_position = self.chunk_by_start.get(&chunk_end).copied();
79
80 if next_in_list != next_by_position {
81 return Err("Cannot overwrite across a split point".to_string());
82 }
83
84 let Some(next_idx) = next_in_list else {
87 return Err("Cannot overwrite across a split point".to_string());
88 };
89 chunk_idx = next_idx;
90 self.chunks[chunk_idx].edit("".into(), Default::default());
94
95 if chunk_idx == end_idx {
96 break;
97 }
98 }
99 }
100
101 self.chunks[start_idx]
104 .edit(content, EditOptions { overwrite: opts.overwrite, store_name: opts.keep_original });
105 Ok(self)
106 }
107}