mut_str/traits.rs
1use core::ops::RangeBounds;
2
3use crate::{
4 char_slice, char_slice_mut, char_split_at, char_split_at_mut, copy_to,
5 errors::{LenNotEqual, ReplaceWithPadCharError, ReplaceWithPadError, ReplacementTooLong},
6 iter::{CharMutRefs, CharRefs},
7 replace, replace_with_pad, replace_with_pad_char, replace_with_pad_left,
8 replace_with_pad_left_char, replace_with_pad_left_space, replace_with_pad_space, Char,
9};
10
11/// The `StrExt` trait adds some methods to string types, many of which operate on character indexes and with character references.
12///
13/// To use its methods, import it with a use statement.
14/// ```
15/// use mut_str::StrExt;
16/// ```
17pub trait StrExt {
18 /// The output string type for string operations.
19 type Output: ?Sized;
20 /// The iterator type for iterating over [`Char`] references.
21 type Iter<'a>: Iterator<Item = &'a Char>
22 where
23 Self: 'a;
24 /// The iterator type for iterating over mutable [`Char`] references.
25 type IterMut<'a>: Iterator<Item = &'a mut Char>
26 where
27 Self: 'a;
28
29 #[must_use]
30 /// Get a character reference from the string and an index.
31 ///
32 /// ```
33 /// use mut_str::StrExt;
34 ///
35 /// let s = "Hello, World!";
36 /// let c = s.get_char(1).unwrap();
37 ///
38 /// assert_eq!(c, 'e');
39 /// ```
40 fn get_char(&self, i: usize) -> Option<&Char>;
41 #[must_use]
42 /// Get a mutable character reference from the mutable string and an index.
43 ///
44 /// ```
45 /// use mut_str::StrExt;
46 ///
47 /// let mut owned_s = Box::<str>::from("Hello, World!");
48 /// let c = owned_s.get_char_mut(1).unwrap();
49 ///
50 /// assert_eq!(c, 'e');
51 /// ```
52 fn get_char_mut(&mut self, i: usize) -> Option<&mut Char>;
53
54 #[must_use]
55 /// Slice the string in units of UTF-8 characters.
56 /// If `range` is out of bounds, `None` will be returned.
57 ///
58 /// ```
59 /// use mut_str::StrExt;
60 ///
61 /// let s = "Hello, World!";
62 ///
63 /// let hello = s.char_slice(..5).unwrap();
64 /// assert_eq!(hello, "Hello");
65 ///
66 /// let world = s.char_slice(7..12).unwrap();
67 /// assert_eq!(world, "World");
68 /// ```
69 fn char_slice<R: RangeBounds<usize>>(&self, range: R) -> Option<&Self::Output>;
70 #[must_use]
71 /// Slice the mutable string in units of UTF-8 characters.
72 /// If `range` is out of bounds, `None` will be returned.
73 ///
74 /// ```
75 /// use mut_str::StrExt;
76 ///
77 /// let mut owned_s = Box::<str>::from("Hello, World!");
78 ///
79 /// let hello = owned_s.char_slice_mut(..5).unwrap();
80 /// assert_eq!(hello, "Hello");
81 ///
82 /// let world = owned_s.char_slice_mut(7..12).unwrap();
83 /// assert_eq!(world, "World");
84 /// ```
85 fn char_slice_mut<R: RangeBounds<usize>>(&mut self, range: R) -> Option<&mut Self::Output>;
86
87 #[must_use]
88 /// Divide the string into two at an index in units of UTF-8 characters.
89 /// If `mid` is out of bounds, `None` will be returned.
90 ///
91 /// ```
92 /// use mut_str::StrExt;
93 ///
94 /// let s = "Hello, World!";
95 ///
96 /// let (l, r) = s.char_split_at(6).unwrap();
97 /// assert_eq!(l, "Hello,");
98 /// assert_eq!(r, " World!");
99 /// ```
100 fn char_split_at(&self, mid: usize) -> Option<(&Self::Output, &Self::Output)>;
101 #[must_use]
102 /// Divide the mutable string into two at an index in units of UTF-8 characters.
103 /// If `mid` is out of bounds, `None` will be returned.
104 ///
105 /// ```
106 /// use mut_str::StrExt;
107 ///
108 /// let mut owned_s = Box::<str>::from("Hello, World!");
109 ///
110 /// let (l, r) = owned_s.char_split_at_mut(6).unwrap();
111 /// assert_eq!(l, "Hello,");
112 /// assert_eq!(r, " World!");
113 /// ```
114 fn char_split_at_mut(&mut self, mid: usize) -> Option<(&mut Self::Output, &mut Self::Output)>;
115
116 #[must_use]
117 /// Get an iterator over character references in the string.
118 ///
119 /// ```
120 /// use mut_str::StrExt;
121 ///
122 /// let s = "Hello, World!";
123 ///
124 /// s.ref_iter()
125 /// .zip(s.chars())
126 /// .for_each(|(x, y)| assert_eq!(x, y));
127 /// ```
128 fn ref_iter(&self) -> Self::Iter<'_>;
129 #[must_use]
130 /// Get an iterator over mutable character references in the string.
131 ///
132 /// ```
133 /// use mut_str::StrExt;
134 ///
135 /// let s = "Hello, World!";
136 /// let mut owned_s = Box::<str>::from(s);
137 ///
138 /// owned_s.mut_iter()
139 /// .zip(s.chars())
140 /// .for_each(|(x, y)| assert_eq!(x, y));
141 /// ```
142 fn mut_iter(&mut self) -> Self::IterMut<'_>;
143
144 /// Copy the string to a byte buffer and get the new string containing the inserted character.
145 /// Returns `None` if `buffer` is shorter than the string.
146 ///
147 /// ```
148 /// use mut_str::StrExt;
149 ///
150 /// let s = "Hello, World!";
151 /// let mut buffer = [0; 50];
152 /// let new_s = s.copy_to(&mut buffer).unwrap();
153 ///
154 /// assert_eq!(new_s, s);
155 /// ```
156 fn copy_to<'a>(&self, buffer: &'a mut [u8]) -> Option<&'a mut Self::Output>;
157
158 /// Replace the mutable string with another of the same length.
159 ///
160 /// ```
161 /// use mut_str::StrExt;
162 ///
163 /// let mut owned_s = Box::<str>::from("World!");
164 ///
165 /// owned_s.replace_with("🌍!!").unwrap();
166 /// assert_eq!(&*owned_s, "🌍!!");
167 ///
168 /// owned_s.replace_with("aaaaaa").unwrap();
169 /// assert_eq!(&*owned_s, "aaaaaa");
170 /// ```
171 ///
172 /// # Errors
173 /// - If `s` and `r`, when utf8 encoded, do not have the same length, [`LenNotEqual`] will be returned.
174 fn replace_with<'a>(&'a mut self, r: &str) -> Result<&'a mut str, LenNotEqual>;
175 /// Replace the mutable string with another of the same length or shorter.
176 /// The remaining bytes will be filled with spaces.
177 ///
178 /// ```
179 /// use mut_str::StrExt;
180 ///
181 /// let mut owned_s = Box::<str>::from("World!");
182 ///
183 /// owned_s.replace_with_pad_space("🌍").unwrap();
184 /// assert_eq!(&*owned_s, "🌍 ");
185 ///
186 /// owned_s.replace_with_pad_space("aaaa").unwrap();
187 /// assert_eq!(&*owned_s, "aaaa ");
188 /// ```
189 ///
190 /// # Errors
191 /// - If `r`, when utf8 encoded, is longer than `s`, when utf8 encoded, [`ReplacementTooLong`] will be returned.
192 fn replace_with_pad_space<'a>(&'a mut self, r: &str)
193 -> Result<&'a mut str, ReplacementTooLong>;
194 /// Replace the mutable string with another of the same length or shorter.
195 /// The remaining bytes will be filled with `pad`.
196 ///
197 /// ```
198 /// use mut_str::StrExt;
199 ///
200 /// let mut owned_s = Box::<str>::from("World!");
201 ///
202 /// owned_s.replace_with_pad("🌍", b'!').unwrap();
203 /// assert_eq!(&*owned_s, "🌍!!");
204 ///
205 /// owned_s.replace_with_pad("aaaa", b'b').unwrap();
206 /// assert_eq!(&*owned_s, "aaaabb");
207 /// ```
208 ///
209 /// # Errors
210 /// - If `pad` is not valid utf8, [`ReplaceWithPadError::InvalidPad`] will be returned.
211 /// - If `r`, when utf8 encoded, is longer than `s`, when utf8 encoded, [`ReplaceWithPadError::ReplacementLen`] will be returned.
212 fn replace_with_pad<'a>(
213 &'a mut self,
214 r: &str,
215 pad: u8,
216 ) -> Result<&'a mut str, ReplaceWithPadError>;
217 /// Replace the mutable string with another of the same length or shorter.
218 /// The remaining bytes will be filled with `pad`, which must be one byte long.
219 ///
220 /// ```
221 /// use mut_str::StrExt;
222 ///
223 /// let mut owned_s = Box::<str>::from("World!");
224 ///
225 /// owned_s.replace_with_pad_char("🌍", '!').unwrap();
226 /// assert_eq!(&*owned_s, "🌍!!");
227 ///
228 /// owned_s.replace_with_pad_char("aaaa", 'b').unwrap();
229 /// assert_eq!(&*owned_s, "aaaabb");
230 /// ```
231 ///
232 /// # Errors
233 /// - If `pad_char`, when utf8 encoded, is longer than `Self`, [`ReplaceWithPadCharError::PadCharTooLong`] will be returned.
234 /// - If `r`, when utf8 encoded, is longer than `s`, when utf8 encoded, [`ReplaceWithPadCharError::ReplacementLen`] will be returned.
235 fn replace_with_pad_char<'a, C>(
236 &'a mut self,
237 r: &str,
238 pad_char: C,
239 ) -> Result<&'a mut str, ReplaceWithPadCharError>
240 where
241 C: Into<char>;
242 /// Replace the mutable string with another of the same length or shorter, right aligned.
243 /// The remaining bytes before the string will be filled with spaces.
244 ///
245 /// ```
246 /// use mut_str::StrExt;
247 ///
248 /// let mut owned_s = Box::<str>::from("World!");
249 ///
250 /// owned_s.replace_with_pad_left_space("🌍").unwrap();
251 /// assert_eq!(&*owned_s, " 🌍");
252 ///
253 /// owned_s.replace_with_pad_left_space("aaaa").unwrap();
254 /// assert_eq!(&*owned_s, " aaaa");
255 /// ```
256 ///
257 /// # Errors
258 /// - If `r`, when utf8 encoded, is longer than `s`, when utf8 encoded, [`ReplacementTooLong`] will be returned.
259 fn replace_with_pad_left_space<'a>(
260 &'a mut self,
261 r: &str,
262 ) -> Result<&'a mut Self::Output, ReplacementTooLong>;
263 /// Replace the mutable string with another of the same length or shorter, right aligned.
264 /// The remaining bytes before the string will be filled with `pad`.
265 ///
266 /// ```
267 /// use mut_str::StrExt;
268 ///
269 /// let mut owned_s = Box::<str>::from("World!");
270 ///
271 /// owned_s.replace_with_pad_left("🌍", b'!').unwrap();
272 /// assert_eq!(&*owned_s, "!!🌍");
273 ///
274 /// owned_s.replace_with_pad_left("aaaa", b'b').unwrap();
275 /// assert_eq!(&*owned_s, "bbaaaa");
276 /// ```
277 ///
278 /// # Errors
279 /// - If `pad` is not valid utf8, [`ReplaceWithPadError::InvalidPad`] will be returned.
280 /// - If `r`, when utf8 encoded, is longer than `s`, when utf8 encoded, [`ReplaceWithPadError::ReplacementLen`] will be returned.
281 fn replace_with_pad_left<'a>(
282 &'a mut self,
283 r: &str,
284 pad: u8,
285 ) -> Result<&'a mut Self::Output, ReplaceWithPadError>;
286 /// Replace the mutable string with another of the same length or shorter, right aligned.
287 /// The remaining bytes before the string will be filled with `char`, which must be one byte long.
288 ///
289 /// ```
290 /// use mut_str::StrExt;
291 ///
292 /// let mut owned_s = Box::<str>::from("World!");
293 ///
294 /// owned_s.replace_with_pad_left_char("🌍", '!').unwrap();
295 /// assert_eq!(&*owned_s, "!!🌍");
296 ///
297 /// owned_s.replace_with_pad_left_char("aaaa", 'b').unwrap();
298 /// assert_eq!(&*owned_s, "bbaaaa");
299 /// ```
300 ///
301 /// # Errors
302 /// - If `pad_char`, when utf8 encoded, is longer than `Self`, [`ReplaceWithPadCharError::PadCharTooLong`] will be returned.
303 /// - If `r`, when utf8 encoded, is longer than `s`, when utf8 encoded, [`ReplaceWithPadCharError::ReplacementLen`] will be returned.
304 fn replace_with_pad_left_char<'a, C>(
305 &'a mut self,
306 r: &str,
307 pad_char: C,
308 ) -> Result<&'a mut Self::Output, ReplaceWithPadCharError>
309 where
310 C: Into<char>;
311}
312
313impl StrExt for str {
314 type Output = Self;
315 type Iter<'a> = CharRefs<'a>;
316 type IterMut<'a> = CharMutRefs<'a>;
317
318 #[inline]
319 fn get_char(&self, i: usize) -> Option<&Char> {
320 Char::get(self, i)
321 }
322
323 #[inline]
324 fn get_char_mut(&mut self, i: usize) -> Option<&mut Char> {
325 Char::get_mut(self, i)
326 }
327
328 #[inline]
329 fn char_slice<R: RangeBounds<usize>>(&self, range: R) -> Option<&Self::Output> {
330 char_slice(self, range)
331 }
332
333 #[inline]
334 fn char_slice_mut<R: RangeBounds<usize>>(&mut self, range: R) -> Option<&mut Self::Output> {
335 char_slice_mut(self, range)
336 }
337
338 #[inline]
339 fn char_split_at(&self, mid: usize) -> Option<(&Self::Output, &Self::Output)> {
340 char_split_at(self, mid)
341 }
342
343 #[inline]
344 fn char_split_at_mut(&mut self, mid: usize) -> Option<(&mut Self::Output, &mut Self::Output)> {
345 char_split_at_mut(self, mid)
346 }
347
348 #[inline]
349 fn ref_iter(&self) -> Self::Iter<'_> {
350 CharRefs::from(self)
351 }
352
353 #[inline]
354 fn mut_iter(&mut self) -> Self::IterMut<'_> {
355 CharMutRefs::from(self)
356 }
357
358 #[inline]
359 fn copy_to<'a>(&self, buffer: &'a mut [u8]) -> Option<&'a mut Self::Output> {
360 copy_to(self, buffer)
361 }
362
363 #[inline]
364 fn replace_with<'a>(&'a mut self, r: &str) -> Result<&'a mut str, LenNotEqual> {
365 replace(self, r)
366 }
367
368 #[inline]
369 fn replace_with_pad_space<'a>(
370 &'a mut self,
371 r: &str,
372 ) -> Result<&'a mut str, ReplacementTooLong> {
373 replace_with_pad_space(self, r)
374 }
375
376 #[inline]
377 fn replace_with_pad<'a>(
378 &'a mut self,
379 r: &str,
380 pad: u8,
381 ) -> Result<&'a mut str, ReplaceWithPadError> {
382 replace_with_pad(self, r, pad)
383 }
384
385 #[inline]
386 fn replace_with_pad_char<'a, C>(
387 &'a mut self,
388 r: &str,
389 pad_char: C,
390 ) -> Result<&'a mut str, ReplaceWithPadCharError>
391 where
392 C: Into<char>,
393 {
394 replace_with_pad_char(self, r, pad_char)
395 }
396
397 #[inline]
398 fn replace_with_pad_left_space(
399 &mut self,
400 r: &str,
401 ) -> Result<&mut Self::Output, ReplacementTooLong> {
402 replace_with_pad_left_space(self, r)
403 }
404
405 #[inline]
406 fn replace_with_pad_left(
407 &mut self,
408 r: &str,
409 pad: u8,
410 ) -> Result<&mut Self::Output, ReplaceWithPadError> {
411 replace_with_pad_left(self, r, pad)
412 }
413
414 #[inline]
415 fn replace_with_pad_left_char<C>(
416 &mut self,
417 r: &str,
418 pad_char: C,
419 ) -> Result<&mut Self::Output, ReplaceWithPadCharError>
420 where
421 C: Into<char>,
422 {
423 replace_with_pad_left_char(self, r, pad_char)
424 }
425}