1use core::fmt::Write;
2
3use crate::{AllowEmpty, GString, GStringError, Validator};
4
5impl<V: Validator, const MIN: usize, const MAX: usize, const ASCII_ONLY: bool>
9 GString<V, MIN, MAX, ASCII_ONLY>
10{
11 pub fn push(&mut self, ch: char) -> Result<(), GStringError<V::Err>> {
13 let mut buf = [0u8; 4];
15 let encoded = ch.encode_utf8(&mut buf);
16
17 self.push_str(encoded)
18 }
19
20 pub fn push_str(&mut self, s: &str) -> Result<(), GStringError<V::Err>> {
22 let mut buf = [0u8; MAX];
23
24 buf[..self.len].copy_from_slice(&self.buf[..self.len]);
26
27 let bytes = s.as_bytes();
29 let end = self.len + bytes.len();
30
31 if end > MAX {
32 return Err(GStringError::TooLong(MAX));
33 }
34
35 buf[self.len..end].copy_from_slice(bytes);
36
37 let candidate = unsafe { core::str::from_utf8_unchecked(&buf[..end]) };
42
43 *self = Self::try_new(candidate)?;
45
46 Ok(())
47 }
48
49 pub fn insert(&mut self, idx: usize, ch: char) -> Result<(), GStringError<V::Err>> {
51 let mut buf = [0u8; 4];
52 let encoded = ch.encode_utf8(&mut buf);
53
54 self.insert_str(idx, encoded)
55 }
56
57 pub fn insert_str(&mut self, idx: usize, string: &str) -> Result<(), GStringError<V::Err>> {
59 if !self.as_str().is_char_boundary(idx) {
60 return Err(GStringError::Mutation("idx is not a char boundary"));
61 }
62
63 let insert_bytes = string.as_bytes();
64 let insert_len = insert_bytes.len();
65
66 let new_len = self.len + insert_len;
67
68 if new_len > MAX {
70 return Err(GStringError::TooLong(MAX));
71 }
72
73 let mut buf = [0u8; MAX];
74
75 buf[..idx].copy_from_slice(&self.buf[..idx]);
77
78 buf[idx..idx + insert_len].copy_from_slice(insert_bytes);
80
81 let tail_len = self.len - idx;
82
83 buf[idx + insert_len..idx + insert_len + tail_len]
85 .copy_from_slice(&self.buf[idx..self.len]);
86
87 let candidate = unsafe { core::str::from_utf8_unchecked(&buf[..new_len]) };
93
94 *self = Self::try_new(candidate)?;
95
96 Ok(())
97 }
98
99 pub fn pop(&mut self) -> Result<Option<char>, GStringError<V::Err>> {
101 if self.is_empty() {
102 return Ok(None);
103 }
104
105 let s = self.as_str();
106 let ch = s.chars().next_back();
107 let ch = if let Some(ch) = ch {
108 ch
109 } else {
110 return Ok(None);
111 };
112
113 let new_len = self.len - ch.len_utf8();
114
115 let candidate = unsafe { core::str::from_utf8_unchecked(&self.buf[..new_len]) };
118
119 match Self::try_new(candidate) {
120 Ok(new) => {
121 *self = new;
122 Ok(Some(ch))
123 }
124 Err(err) => Err(err),
125 }
126 }
127
128 pub fn remove(&mut self, idx: usize) -> Result<char, GStringError<V::Err>> {
130 if !self.as_str().is_char_boundary(idx) {
131 return Err(GStringError::Mutation("idx is not a char boundary"));
132 }
133
134 let s = self.as_str();
135
136 let ch = s[idx..].chars().next().ok_or(GStringError::Mutation(
137 "cannot remove char from empty index",
138 ))?;
139
140 let ch_len = ch.len_utf8();
141
142 let new_len = self.len - ch_len;
143
144 let mut buf = [0u8; MAX];
145
146 buf[..idx].copy_from_slice(&self.buf[..idx]);
148
149 buf[idx..new_len].copy_from_slice(&self.buf[idx + ch_len..self.len]);
151
152 let candidate = unsafe { core::str::from_utf8_unchecked(&buf[..new_len]) };
155
156 *self = Self::try_new(candidate)?;
157
158 Ok(ch)
159 }
160
161 pub fn truncate(&mut self, new_len: usize) -> Result<(), GStringError<V::Err>> {
163 if new_len >= self.len {
164 return Ok(());
165 }
166
167 if !self.as_str().is_char_boundary(new_len) {
168 return Err(GStringError::Mutation("new_len is not a char boundary"));
169 }
170
171 let candidate = unsafe { core::str::from_utf8_unchecked(&self.buf[..new_len]) };
174
175 *self = Self::try_new(candidate)?;
176
177 Ok(())
178 }
179
180 #[cfg(feature = "alloc")]
182 pub fn replace(&mut self, from: &str, to: &str) -> Result<(), GStringError<V::Err>> {
183 let replaced = self.as_str().replace(from, to);
185
186 *self = Self::try_new(&replaced)?;
187
188 Ok(())
189 }
190
191 pub fn replace_range<R>(
193 &mut self,
194 range: R,
195 replace_with: &str,
196 ) -> Result<(), GStringError<V::Err>>
197 where
198 R: core::ops::RangeBounds<usize>,
199 {
200 use core::ops::Bound;
201
202 let start = match range.start_bound() {
203 Bound::Included(&n) => n,
204 Bound::Excluded(&n) => n
205 .checked_add(1)
206 .ok_or(GStringError::Mutation("range overflow"))?,
207 Bound::Unbounded => 0,
208 };
209
210 let end = match range.end_bound() {
211 Bound::Included(&n) => n
212 .checked_add(1)
213 .ok_or(GStringError::Mutation("range overflow"))?,
214 Bound::Excluded(&n) => n,
215 Bound::Unbounded => self.len,
216 };
217
218 let s = self.as_str();
219
220 if !s.is_char_boundary(start) {
221 return Err(GStringError::Mutation("start range is not within boundary"));
222 }
223 if !s.is_char_boundary(end) {
224 return Err(GStringError::Mutation("end range is not within boundary"));
225 }
226 if start > end {
227 return Err(GStringError::Mutation(
228 "start range cannot be bigger than end",
229 ));
230 }
231
232 let mut buf = [0u8; MAX];
233
234 let before = &self.buf[..start];
235 let middle = replace_with.as_bytes();
236 let after = &self.buf[end..self.len];
237
238 let new_len = before
239 .len()
240 .checked_add(middle.len())
241 .and_then(|n| n.checked_add(after.len()))
242 .ok_or(GStringError::TooLong(MAX))?;
243
244 if new_len > MAX {
245 return Err(GStringError::TooLong(MAX));
246 }
247
248 buf[..before.len()].copy_from_slice(before);
250
251 buf[before.len()..before.len() + middle.len()].copy_from_slice(middle);
253
254 buf[before.len() + middle.len()..new_len].copy_from_slice(after);
256
257 let candidate = unsafe { core::str::from_utf8_unchecked(&buf[..new_len]) };
262
263 *self = Self::try_new(candidate)?;
264
265 Ok(())
266 }
267}
268
269impl<V: Validator + AllowEmpty, const MAX: usize, const ASCII_ONLY: bool>
270 GString<V, 0, MAX, ASCII_ONLY>
271{
272 #[inline]
274 pub fn clear(&mut self) {
275 *self = Self::default()
276 }
277}
278
279impl<V: Validator, const MIN: usize, const MAX: usize, const ASCII_ONLY: bool>
280 GString<V, MIN, MAX, ASCII_ONLY>
281{
282 pub fn try_extend<I, S>(&mut self, iter: I) -> Result<(), GStringError<V::Err>>
293 where
294 I: IntoIterator<Item = S>,
295 S: AsRef<str>,
296 {
297 let mut tmp = self.clone();
298
299 for s in iter {
300 tmp.push_str(s.as_ref())?;
301 }
302
303 *self = tmp;
304
305 Ok(())
306 }
307
308 pub fn try_extend_chars<I>(&mut self, iter: I) -> Result<(), GStringError<V::Err>>
319 where
320 I: IntoIterator<Item = char>,
321 {
322 let mut tmp = self.clone();
323
324 for ch in iter {
325 tmp.push(ch)?;
326 }
327
328 *self = tmp;
329
330 Ok(())
331 }
332}
333
334impl<V: Validator, const MIN: usize, const MAX: usize, const ASCII_ONLY: bool> Write
335 for GString<V, MIN, MAX, ASCII_ONLY>
336{
337 fn write_str(&mut self, s: &str) -> core::fmt::Result {
338 self.push_str(s).map_err(|_| core::fmt::Error)
339 }
340
341 fn write_char(&mut self, c: char) -> core::fmt::Result {
342 self.push(c).map_err(|_| core::fmt::Error)
343 }
344}