mut_str/
char_ref.rs

1use core::{
2    borrow::{Borrow, BorrowMut},
3    cmp,
4    fmt::{self, Display},
5    hash, ptr, slice,
6    str::{self, FromStr},
7};
8#[cfg(feature = "alloc")]
9extern crate alloc;
10// `ToOwned` is in the std prelude, so ignore unused import
11#[allow(unused_imports)]
12#[cfg(feature = "alloc")]
13use alloc::borrow::ToOwned;
14
15use crate::{
16    errors::{
17        LenNotEqual, ReplaceWithPadCharError, ReplaceWithPadError, ReplacementTooLong,
18        TryFromBytesError, TryFromStrError,
19    },
20    OwnedChar,
21};
22
23#[repr(transparent)]
24/// A UTF-8 encoded character.
25///
26/// This type can only be obtained as a reference or mutable reference similarly to [`prim@str`].
27///
28/// ```
29/// use mut_str::Char;
30///
31/// let s = "Hello, World!";
32/// let c = Char::get(s, 1).unwrap();
33///
34/// assert_eq!(c, 'e');
35/// ```
36pub struct Char {
37    c: u8,
38}
39
40impl Char {
41    #[must_use]
42    #[inline]
43    /// Create a new character reference from a pointer to a character.
44    ///
45    /// # Safety
46    /// `p` must be a pointer to the first byte of a valid UTF-8 character.
47    pub const unsafe fn new_unchecked(p: *const u8) -> *const Self {
48        p.cast()
49    }
50
51    #[must_use]
52    #[inline]
53    /// Create a new mutable character reference from a mutable pointer to a character.
54    ///
55    /// # Safety
56    /// `p` must be a mutable pointer to the first byte of a valid UTF-8 character that
57    /// can be mutated. String literals cannot be mutated.
58    pub const unsafe fn new_unchecked_mut(p: *mut u8) -> *mut Self {
59        p.cast()
60    }
61
62    #[must_use]
63    /// Get a character reference from a [`prim@str`] and an index.
64    ///
65    /// ```
66    /// use mut_str::Char;
67    ///
68    /// let s = "Hello, World!";
69    /// let c = Char::get(s, 1).unwrap();
70    ///
71    /// assert_eq!(c, 'e');
72    /// ```
73    pub fn get(s: &str, i: usize) -> Option<&Self> {
74        let mut chars = s.char_indices();
75        let start = chars.nth(i)?.0;
76
77        let p = s.as_bytes().get(start)?;
78
79        // SAFETY:
80        // Pointer offset is from `CharIndices`, so it is valid.
81        Some(unsafe { &*Self::new_unchecked(p) })
82    }
83
84    #[must_use]
85    /// Get a mutable character reference from a mutable [`prim@str`] and an index.
86    ///
87    /// ```
88    /// use mut_str::Char;
89    ///
90    /// let mut s = Box::<str>::from("Hello, World!");
91    /// let c = Char::get_mut(&mut *s, 1).unwrap();
92    ///
93    /// assert_eq!(c, 'e');
94    /// ```
95    pub fn get_mut(s: &mut str, i: usize) -> Option<&mut Self> {
96        let mut chars = s.char_indices();
97        let start = chars.nth(i)?.0;
98
99        // SAFETY:
100        // `Self` maintains utf8 validity.
101        let p = unsafe { s.as_bytes_mut() }.get_mut(start)?;
102
103        // SAFETY:
104        // Pointer offset is from `CharIndices`, so it is valid.
105        Some(unsafe { &mut *Self::new_unchecked_mut(p) })
106    }
107
108    #[must_use]
109    #[inline]
110    // This can never be empty.
111    #[allow(clippy::len_without_is_empty)]
112    /// Get the length of the character in bytes.
113    ///
114    /// This will be in the range `1..=4`.
115    ///
116    /// ```
117    /// use mut_str::Char;
118    ///
119    /// let s = "oΦ⏣🌑";
120    ///
121    /// assert_eq!(Char::get(s, 0).unwrap().len(), 1);
122    /// assert_eq!(Char::get(s, 1).unwrap().len(), 2);
123    /// assert_eq!(Char::get(s, 2).unwrap().len(), 3);
124    /// assert_eq!(Char::get(s, 3).unwrap().len(), 4);
125    /// ```
126    pub fn len(&self) -> usize {
127        match self.c.leading_ones() {
128            0 => 1,
129            l @ 2..=4 => l as usize,
130            _ => unreachable!("invalid char pointer"),
131        }
132    }
133
134    #[must_use]
135    #[inline]
136    /// Get a pointer to the character ([`prim@pointer`]).
137    pub const fn as_ptr(&self) -> *const u8 {
138        ptr::from_ref(self).cast()
139    }
140
141    #[must_use]
142    #[inline]
143    /// Get a mutable pointer to the character ([`prim@pointer`]).
144    pub fn as_mut_ptr(&mut self) -> *mut u8 {
145        ptr::from_mut(self).cast()
146    }
147
148    #[must_use]
149    #[inline]
150    /// Get the character as a byte slice ([`prim@slice`]).
151    ///
152    /// ```
153    /// use mut_str::Char;
154    ///
155    /// let s = "Hello, 🌍!";
156    ///
157    /// let c = Char::get(s, 1).unwrap();
158    /// assert_eq!(c.as_bytes(), &[101]);
159    ///
160    /// let c = Char::get(s, 7).unwrap();
161    /// assert_eq!(c.as_bytes(), &[240, 159, 140, 141]);
162    /// ```
163    pub fn as_bytes(&self) -> &[u8] {
164        // SAFETY:
165        // The pointer is to the start of the character in the utf8 string.
166        // There is guaranteed to be `self.len()` bytes after (and including)
167        // the pointer.
168        unsafe { slice::from_raw_parts(self.as_ptr(), self.len()) }
169    }
170
171    #[must_use]
172    #[inline]
173    /// Get the character as a mutable byte slice ([`prim@slice`]).
174    ///
175    /// # Safety
176    /// See [`str::as_bytes_mut`].
177    pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] {
178        slice::from_raw_parts_mut(self.as_mut_ptr(), self.len())
179    }
180
181    #[must_use]
182    #[inline]
183    /// Get the character as a [`prim@str`].
184    ///
185    /// ```
186    /// use mut_str::Char;
187    ///
188    /// let s = "Hello, 🌍!";
189    ///
190    /// let c = Char::get(s, 1).unwrap();
191    /// assert_eq!(c.as_str(), "e");
192    ///
193    /// let c = Char::get(s, 7).unwrap();
194    /// assert_eq!(c.as_str(), "🌍");
195    /// ```
196    pub fn as_str(&self) -> &str {
197        // SAFETY:
198        // `self.s` is guaranteed to be the bytes of a valid utf8 string.
199        unsafe { str::from_utf8_unchecked(self.as_bytes()) }
200    }
201
202    #[must_use]
203    #[inline]
204    /// Get the character as a mutable [`prim@str`].
205    ///
206    /// ```
207    /// use mut_str::Char;
208    ///
209    /// let mut s = Box::<str>::from("Hello, 🌍!");
210    ///
211    /// let c = Char::get_mut(&mut *s, 1).unwrap();
212    /// assert_eq!(c.as_str_mut(), "e");
213    ///
214    /// let c = Char::get_mut(&mut *s, 7).unwrap();
215    /// assert_eq!(c.as_str_mut(), "🌍");
216    /// ```
217    pub fn as_str_mut(&mut self) -> &mut str {
218        // SAFETY:
219        // `self.s` is guaranteed to be the bytes of a valid utf8 string.
220        // It can be assumed that a `str` will stay valid.
221        unsafe { str::from_utf8_unchecked_mut(self.as_bytes_mut()) }
222    }
223
224    #[must_use]
225    /// Get the character as a [`char`].
226    ///
227    /// ```
228    /// use mut_str::Char;
229    ///
230    /// let s = "Hello, 🌍!";
231    ///
232    /// let c = Char::get(s, 1).unwrap();
233    /// assert_eq!(c.as_char(), 'e');
234    ///
235    /// let c = Char::get(s, 7).unwrap();
236    /// assert_eq!(c.as_char(), '🌍');
237    /// ```
238    pub fn as_char(&self) -> char {
239        // SAFETY:
240        // `self` is guaranteed to contain exactly one character, so calling`
241        // `next for the first time on the `Chars` iterator will yield an
242        // `Option::Some`.
243        unsafe { self.as_str().chars().next().unwrap_unchecked() }
244    }
245
246    #[must_use]
247    #[inline]
248    /// Creates an [`OwnedChar`] from a borrowed [`Char`].
249    ///
250    /// ```
251    /// use mut_str::{Char, OwnedChar};
252    ///
253    /// let s = "Hello, 🌍!";
254    ///
255    /// let c = Char::get(s, 1).unwrap();
256    /// assert_eq!(c.as_owned(), OwnedChar::from('e'));
257    ///
258    /// let c = Char::get(s, 7).unwrap();
259    /// assert_eq!(c.as_owned(), OwnedChar::from('🌍'));
260    /// ```
261    pub fn as_owned(&self) -> OwnedChar {
262        let bytes = self.as_bytes();
263
264        // SAFETY:
265        // `bytes` is guaranteed be to a valid UTF-8 character.
266        unsafe { OwnedChar::from_bytes_unchecked(bytes) }
267    }
268
269    #[inline]
270    /// Copy the character to a byte buffer and get the [`prim@str`] containing the inserted character.
271    /// Returns `None` if `buffer` is shorter than `self`.
272    ///
273    /// ```
274    /// use mut_str::Char;
275    ///
276    /// let s = "Hello, World!";
277    /// let c = Char::get(s, 1).unwrap();
278    ///
279    /// let mut buffer = [0; 4];
280    /// let c2 = c.copy_to(&mut buffer).unwrap();
281    ///
282    /// assert_eq!(c2, c);
283    /// ```
284    pub fn copy_to<'a>(&self, buffer: &'a mut [u8]) -> Option<&'a mut Self> {
285        let len = self.len();
286        if len > buffer.len() {
287            None
288        } else {
289            buffer[..len].copy_from_slice(self.as_bytes());
290
291            // SAFETY:
292            // This is valid as a utf8 character was just copied to the buffer.
293            Some(unsafe { &mut *Self::new_unchecked_mut(buffer.as_mut_ptr()) })
294        }
295    }
296
297    /// Replace the character with another of the same length.
298    ///
299    /// ```
300    /// use mut_str::Char;
301    ///
302    /// let mut s = Box::<str>::from("oΦ⏣🌑");
303    ///
304    /// let c = Char::get_mut(&mut *s, 0).unwrap();
305    /// assert!(c.replace('e').is_ok());
306    /// assert_eq!(&*s, "eΦ⏣🌑");
307    ///
308    /// let c = Char::get_mut(&mut *s, 1).unwrap();
309    /// assert!(c.replace('a').is_err());
310    /// ```
311    ///
312    /// # Errors
313    /// - If `r`, when utf8 encoded, does not have the same length as `self`, [`LenNotEqual`] will be returned.
314    pub fn replace<C>(&mut self, r: C) -> Result<(), LenNotEqual>
315    where
316        C: Into<char>,
317    {
318        let r = r.into();
319
320        if self.len() != r.len_utf8() {
321            return Err(LenNotEqual);
322        }
323
324        // SAFETY:
325        // Replacing the character with a valid utf8 character of the same
326        // length is valid.
327        r.encode_utf8(unsafe { self.as_bytes_mut() });
328        Ok(())
329    }
330
331    /// Replace the character with another of the same length or shorter.
332    /// The remaining bytes will be filled with spaces.
333    ///
334    /// ```
335    /// use mut_str::Char;
336    ///
337    /// let mut s = Box::<str>::from("oΦ⏣🌑");
338    ///
339    /// let c = Char::get_mut(&mut *s, 0).unwrap();
340    /// assert!(c.replace_with_pad_space('e').is_ok());
341    /// assert_eq!(&*s, "eΦ⏣🌑");
342    ///
343    /// let c = Char::get_mut(&mut *s, 1).unwrap();
344    /// assert!(c.replace_with_pad_space('a').is_ok());
345    /// assert_eq!(&*s, "ea ⏣🌑");
346    /// ```
347    ///
348    /// # Errors
349    /// - If `r`, when utf8 encoded, is longer than `self`, [`ReplacementTooLong`] will be returned.
350    pub fn replace_with_pad_space<C>(&mut self, r: C) -> Result<(), ReplacementTooLong>
351    where
352        C: Into<char>,
353    {
354        let r = r.into();
355
356        if self.len() < r.len_utf8() {
357            return Err(ReplacementTooLong);
358        }
359
360        // SAFETY:
361        // `Self` maintains utf8 validity.
362        let (char_slice, remaining) = unsafe { self.as_bytes_mut().split_at_mut(r.len_utf8()) };
363
364        r.encode_utf8(char_slice);
365        remaining.fill(b' ');
366
367        Ok(())
368    }
369
370    /// Replace the character with another of the same length or shorter.
371    /// The remaining bytes will be filled with `pad`.
372    ///
373    /// ```
374    /// use mut_str::Char;
375    ///
376    /// let mut s = Box::<str>::from("oΦ⏣🌑");
377    ///
378    /// let c = Char::get_mut(&mut *s, 0).unwrap();
379    /// assert!(c.replace_with_pad('e', b'b').is_ok());
380    /// assert_eq!(&*s, "eΦ⏣🌑");
381    ///
382    /// let c = Char::get_mut(&mut *s, 1).unwrap();
383    /// assert!(c.replace_with_pad('a', b'b').is_ok());
384    /// assert_eq!(&*s, "eab⏣🌑");
385    /// ```
386    ///
387    /// # Errors
388    /// - If `pad` is not valid utf8, [`ReplaceWithPadError::InvalidPad`] will be returned.
389    /// - If `r`, when utf8 encoded, is longer than `self`, [`ReplaceWithPadError::ReplacementLen`] will be returned.
390    pub fn replace_with_pad<C>(&mut self, r: C, pad: u8) -> Result<(), ReplaceWithPadError>
391    where
392        C: Into<char>,
393    {
394        let r = r.into();
395
396        if self.len() < r.len_utf8() {
397            return Err(ReplaceWithPadError::CHAR_LEN);
398        }
399
400        str::from_utf8(&[pad]).map_err(ReplaceWithPadError::InvalidPad)?;
401
402        // SAFETY:
403        // `Self` maintains utf8 validity.
404        let (char_slice, remaining) = unsafe { self.as_bytes_mut().split_at_mut(r.len_utf8()) };
405
406        r.encode_utf8(char_slice);
407        remaining.fill(pad);
408
409        Ok(())
410    }
411
412    /// Replace the character with another of the same length or shorter.
413    /// The remaining bytes will be filled with `pad`, which must be one byte long.
414    ///
415    /// ```
416    /// use mut_str::Char;
417    ///
418    /// let mut s = Box::<str>::from("oΦ⏣🌑");
419    ///
420    /// let c = Char::get_mut(&mut *s, 0).unwrap();
421    /// assert!(c.replace_with_pad_char('e', 'b').is_ok());
422    /// assert_eq!(&*s, "eΦ⏣🌑");
423    ///
424    /// let c = Char::get_mut(&mut *s, 1).unwrap();
425    /// assert!(c.replace_with_pad_char('a', 'b').is_ok());
426    /// assert_eq!(&*s, "eab⏣🌑");
427    /// ```
428    ///
429    /// # Errors
430    /// - If `pad_char`, when utf8 encoded, is longer than `Self`, [`ReplaceWithPadCharError::PadCharTooLong`] will be returned.
431    /// - If `r`, when utf8 encoded, is longer than `self`, [`ReplaceWithPadCharError::ReplacementLen`] will be returned.
432    pub fn replace_with_pad_char<C1, C2>(
433        &mut self,
434        r: C1,
435        pad_char: C2,
436    ) -> Result<(), ReplaceWithPadCharError>
437    where
438        C1: Into<char>,
439        C2: Into<char>,
440    {
441        let (r, pad_char) = (r.into(), pad_char.into());
442
443        if pad_char.len_utf8() != 1 {
444            return Err(ReplaceWithPadCharError::PadCharTooLong);
445        }
446
447        if self.len() < r.len_utf8() {
448            return Err(ReplaceWithPadCharError::CHAR_LEN);
449        }
450
451        let mut pad: u8 = 0;
452        pad_char.encode_utf8(slice::from_mut(&mut pad));
453
454        // SAFETY:
455        // `Self` maintains utf8 validity.
456        let (char_slice, remaining) = unsafe { self.as_bytes_mut().split_at_mut(r.len_utf8()) };
457
458        r.encode_utf8(char_slice);
459        remaining.fill(pad);
460
461        Ok(())
462    }
463
464    /// Replace the character with another of the same length or shorter, right aligned.
465    /// The remaining bytes before the character will be filled with spaces.
466    ///
467    /// ```
468    /// use mut_str::Char;
469    ///
470    /// let mut s = Box::<str>::from("oΦ⏣🌑");
471    ///
472    /// let c = Char::get_mut(&mut *s, 0).unwrap();
473    /// assert!(c.replace_with_pad_left_space('e').is_ok());
474    /// assert_eq!(&*s, "eΦ⏣🌑");
475    ///
476    /// let c = Char::get_mut(&mut *s, 1).unwrap();
477    /// let c2 = c.replace_with_pad_left_space('a').unwrap();
478    /// assert_eq!(c2, 'a');
479    /// assert_eq!(c, ' ');
480    /// assert_eq!(&*s, "e a⏣🌑");
481    /// ```
482    ///
483    /// # Errors
484    /// - If `r`, when utf8 encoded, is longer than `self`, [`ReplacementTooLong`] will be returned.
485    pub fn replace_with_pad_left_space<C>(&mut self, r: C) -> Result<&mut Self, ReplacementTooLong>
486    where
487        C: Into<char>,
488    {
489        let r = r.into();
490        let len = self.len();
491
492        if len < r.len_utf8() {
493            return Err(ReplacementTooLong);
494        }
495
496        let (remaining, char_slice) =
497            // SAFETY:
498            // `Self` maintains utf8 validity.
499            unsafe { self.as_bytes_mut().split_at_mut(len - r.len_utf8()) };
500
501        r.encode_utf8(char_slice);
502        remaining.fill(b' ');
503
504        // SAFETY:
505        // The pointer is directly after a char boundary.
506        Ok(unsafe { &mut *Self::new_unchecked_mut(char_slice.as_mut_ptr()) })
507    }
508
509    /// Replace the character with another of the same length or shorter, right aligned.
510    /// The remaining bytes before the character will be filled with `pad`.
511    ///
512    /// ```
513    /// use mut_str::Char;
514    ///
515    /// let mut s = Box::<str>::from("oΦ⏣🌑");
516    ///
517    /// let c = Char::get_mut(&mut *s, 0).unwrap();
518    /// assert!(c.replace_with_pad_left('e', b'b').is_ok());
519    /// assert_eq!(&*s, "eΦ⏣🌑");
520    ///
521    /// let c = Char::get_mut(&mut *s, 1).unwrap();
522    /// let c2 = c.replace_with_pad_left('a', b'b').unwrap();
523    /// assert_eq!(c2, 'a');
524    /// assert_eq!(c, 'b');
525    /// assert_eq!(&*s, "eba⏣🌑");
526    /// ```
527    ///
528    /// # Errors
529    /// - If `pad` is not valid utf8, [`ReplaceWithPadError::InvalidPad`] will be returned.
530    /// - If `r`, when utf8 encoded, is longer than `self`, [`ReplaceWithPadError::ReplacementLen`] will be returned.
531    pub fn replace_with_pad_left<C>(
532        &mut self,
533        r: C,
534        pad: u8,
535    ) -> Result<&mut Self, ReplaceWithPadError>
536    where
537        C: Into<char>,
538    {
539        let r = r.into();
540        let len = self.len();
541
542        if len < r.len_utf8() {
543            return Err(ReplaceWithPadError::CHAR_LEN);
544        }
545
546        str::from_utf8(&[pad]).map_err(ReplaceWithPadError::InvalidPad)?;
547
548        let (remaining, char_slice) =
549            // SAFETY:
550            // `Self` maintains utf8 validity.
551            unsafe { self.as_bytes_mut().split_at_mut(len - r.len_utf8()) };
552
553        r.encode_utf8(char_slice);
554        remaining.fill(pad);
555
556        // SAFETY:
557        // The pointer is directly after a char boundary.
558        Ok(unsafe { &mut *Self::new_unchecked_mut(char_slice.as_mut_ptr()) })
559    }
560
561    /// Replace the character with another of the same length or shorter, right aligned.
562    /// The remaining bytes before the character will be filled with `char`, which must be one byte long.
563    ///
564    /// ```
565    /// use mut_str::Char;
566    ///
567    /// let mut s = Box::<str>::from("oΦ⏣🌑");
568    ///
569    /// let c = Char::get_mut(&mut *s, 0).unwrap();
570    /// assert!(c.replace_with_pad_left_char('e', 'b').is_ok());
571    /// assert_eq!(&*s, "eΦ⏣🌑");
572    ///
573    /// let c = Char::get_mut(&mut *s, 1).unwrap();
574    /// let c2 = c.replace_with_pad_left_char('a', 'b').unwrap();
575    /// assert_eq!(c2, 'a');
576    /// assert_eq!(c, 'b');
577    /// assert_eq!(&*s, "eba⏣🌑");
578    /// ```
579    ///
580    /// # Errors
581    /// - If `pad_char`, when utf8 encoded, is longer than `Self`, [`ReplaceWithPadCharError::PadCharTooLong`] will be returned.
582    /// - If `r`, when utf8 encoded, is longer than `self`, [`ReplaceWithPadCharError::ReplacementLen`] will be returned.
583    pub fn replace_with_pad_left_char<C1, C2>(
584        &mut self,
585        r: C1,
586        pad_char: C2,
587    ) -> Result<&mut Self, ReplaceWithPadCharError>
588    where
589        C1: Into<char>,
590        C2: Into<char>,
591    {
592        let (r, pad_char) = (r.into(), pad_char.into());
593        let len = self.len();
594
595        if pad_char.len_utf8() != 1 {
596            return Err(ReplaceWithPadCharError::PadCharTooLong);
597        }
598
599        if len < r.len_utf8() {
600            return Err(ReplaceWithPadCharError::CHAR_LEN);
601        }
602
603        let mut pad: u8 = 0;
604        pad_char.encode_utf8(slice::from_mut(&mut pad));
605
606        let (remaining, char_slice) =
607            // SAFETY:
608            // `Self` maintains utf8 validity.
609            unsafe { self.as_bytes_mut().split_at_mut(len - r.len_utf8()) };
610
611        r.encode_utf8(char_slice);
612        remaining.fill(pad);
613
614        // SAFETY:
615        // The pointer is directly after a char boundary.
616        Ok(unsafe { &mut *Self::new_unchecked_mut(char_slice.as_mut_ptr()) })
617    }
618
619    #[must_use]
620    #[inline]
621    /// Checks if the value is within ASCII range.
622    ///
623    /// ```
624    /// use mut_str::Char;
625    ///
626    /// let s = "oΦ⏣🌑";
627    ///
628    /// let c = Char::get(s, 0).unwrap();
629    /// assert!(c.is_ascii());
630    ///
631    /// let c = Char::get(s, 1).unwrap();
632    /// assert!(!c.is_ascii());
633    /// ```
634    pub const fn is_ascii(&self) -> bool {
635        self.c.is_ascii()
636    }
637
638    #[inline]
639    /// Converts this type to its ASCII upper case equivalent in-place.
640    ///
641    /// ASCII letters ‘a’ to ‘z’ are mapped to 'A' to 'Z', but non-ASCII letters are unchanged.
642    ///
643    /// ```
644    /// use mut_str::Char;
645    ///
646    /// let mut s = Box::<str>::from("oφ⏣🌑");
647    ///
648    /// let c = Char::get_mut(&mut *s, 0).unwrap();
649    /// c.make_ascii_uppercase();
650    ///
651    /// let c = Char::get_mut(&mut *s, 1).unwrap();
652    /// c.make_ascii_uppercase();
653    ///
654    /// assert_eq!(&*s, "Oφ⏣🌑");
655    /// ```
656    pub fn make_ascii_uppercase(&mut self) {
657        self.c.make_ascii_uppercase();
658    }
659
660    #[inline]
661    /// Converts this type to its ASCII lower case equivalent in-place.
662    ///
663    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z', but non-ASCII letters are unchanged.
664    ///
665    /// ```
666    /// use mut_str::Char;
667    ///
668    /// let mut s = Box::<str>::from("OΦ⏣🌑");
669    ///
670    /// let c = Char::get_mut(&mut *s, 0).unwrap();
671    /// c.make_ascii_lowercase();
672    ///
673    /// let c = Char::get_mut(&mut *s, 1).unwrap();
674    /// c.make_ascii_lowercase();
675    ///
676    /// assert_eq!(&*s, "oΦ⏣🌑");
677    /// ```
678    pub fn make_ascii_lowercase(&mut self) {
679        self.c.make_ascii_lowercase();
680    }
681
682    /// Converts this type to its Unicode upper case equivalent in-place.
683    ///
684    /// ```
685    /// use mut_str::Char;
686    ///
687    /// let mut s = Box::<str>::from("oφ⏣🌑");
688    ///
689    /// let c = Char::get_mut(&mut *s, 0).unwrap();
690    /// c.try_make_uppercase().unwrap();
691    ///
692    /// let c = Char::get_mut(&mut *s, 1).unwrap();
693    /// c.try_make_uppercase().unwrap();
694    ///
695    /// assert_eq!(&*s, "OΦ⏣🌑");
696    /// ```
697    ///
698    /// # Errors
699    /// If the character and its uppercase version is not the same length when utf8 encoded, [`LenNotEqual`] will be returned.
700    pub fn try_make_uppercase(&mut self) -> Result<(), LenNotEqual> {
701        let chars = self.as_char().to_uppercase();
702
703        let mut buffer = [0; 4];
704        let mut index = 0;
705
706        let self_len = self.len();
707
708        for char in chars {
709            let len = char.len_utf8();
710            if index + len > self_len {
711                return Err(LenNotEqual);
712            }
713
714            char.encode_utf8(&mut buffer[index..]);
715            index += len;
716        }
717
718        if index != self_len {
719            return Err(LenNotEqual);
720        }
721
722        // SAFETY:
723        // Replacing the character with a valid utf8 character of the same
724        // length is valid.
725        unsafe { self.as_bytes_mut() }.copy_from_slice(&buffer[..index]);
726        Ok(())
727    }
728
729    /// Converts this type to its Unicode lower case equivalent in-place.
730    ///
731    /// ```
732    /// use mut_str::Char;
733    ///
734    /// let mut s = Box::<str>::from("OΦ⏣🌑");
735    ///
736    /// let c = Char::get_mut(&mut *s, 0).unwrap();
737    /// c.try_make_lowercase().unwrap();
738    ///
739    /// let c = Char::get_mut(&mut *s, 1).unwrap();
740    /// c.try_make_lowercase().unwrap();
741    ///
742    /// assert_eq!(&*s, "oφ⏣🌑");
743    /// ```
744    ///
745    /// # Errors
746    /// If the character and its lowercase version is not the same length when utf8 encoded, [`LenNotEqual`] will be returned.
747    pub fn try_make_lowercase(&mut self) -> Result<(), LenNotEqual> {
748        let chars = self.as_char().to_lowercase();
749
750        let mut buffer = [0; 4];
751        let mut index = 0;
752
753        let self_len = self.len();
754
755        for char in chars {
756            let len = char.len_utf8();
757            if index + len > self_len {
758                return Err(LenNotEqual);
759            }
760
761            char.encode_utf8(&mut buffer[index..]);
762            index += len;
763        }
764
765        if index != self_len {
766            return Err(LenNotEqual);
767        }
768
769        // SAFETY:
770        // Replacing the character with a valid utf8 character of the same
771        // length is valid.
772        unsafe { self.as_bytes_mut() }.copy_from_slice(&buffer[..index]);
773        Ok(())
774    }
775}
776
777impl fmt::Display for Char {
778    #[inline]
779    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
780        self.as_str().fmt(f)
781    }
782}
783
784impl fmt::Debug for Char {
785    #[inline]
786    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
787        let mut b = [b'\''; 6];
788        b[1..=self.len()].copy_from_slice(self.as_bytes());
789
790        // SAFETY:
791        // `self` is valid utf8, so when embedded in a string of single-byte
792        // utf8 characters, the resulting string will be valid.
793        let s = unsafe { str::from_utf8_unchecked(&b[..self.len() + 2]) };
794        Display::fmt(s, f)
795    }
796}
797
798impl PartialEq for Char {
799    #[inline]
800    fn eq(&self, other: &Self) -> bool {
801        self.as_bytes().eq(other.as_bytes())
802    }
803}
804
805impl PartialEq<OwnedChar> for Char {
806    #[inline]
807    fn eq(&self, other: &OwnedChar) -> bool {
808        self.eq(other.as_ref())
809    }
810}
811
812impl PartialEq<str> for Char {
813    #[inline]
814    fn eq(&self, other: &str) -> bool {
815        self.as_bytes().eq(other.as_bytes())
816    }
817}
818
819impl PartialEq<Char> for str {
820    #[inline]
821    fn eq(&self, other: &Char) -> bool {
822        self.as_bytes().eq(other.as_bytes())
823    }
824}
825
826impl PartialEq<char> for Char {
827    #[inline]
828    fn eq(&self, other: &char) -> bool {
829        self.as_char().eq(other)
830    }
831}
832
833impl PartialEq<Char> for char {
834    #[inline]
835    fn eq(&self, other: &Char) -> bool {
836        self.eq(&other.as_char())
837    }
838}
839
840impl PartialEq<char> for &Char {
841    #[inline]
842    fn eq(&self, other: &char) -> bool {
843        self.as_char().eq(other)
844    }
845}
846
847impl PartialEq<char> for &mut Char {
848    #[inline]
849    fn eq(&self, other: &char) -> bool {
850        self.as_char().eq(other)
851    }
852}
853
854impl Eq for Char {}
855
856impl Ord for Char {
857    #[inline]
858    fn cmp(&self, other: &Self) -> cmp::Ordering {
859        self.as_bytes().cmp(other.as_bytes())
860    }
861}
862
863impl PartialOrd for Char {
864    #[inline]
865    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
866        Some(self.cmp(other))
867    }
868}
869
870impl PartialOrd<OwnedChar> for Char {
871    #[inline]
872    fn partial_cmp(&self, other: &OwnedChar) -> Option<cmp::Ordering> {
873        self.partial_cmp(other.as_ref())
874    }
875}
876
877impl PartialOrd<str> for Char {
878    #[inline]
879    fn partial_cmp(&self, other: &str) -> Option<cmp::Ordering> {
880        Some(self.as_bytes().cmp(other.as_bytes()))
881    }
882}
883
884impl PartialOrd<Char> for str {
885    #[inline]
886    fn partial_cmp(&self, other: &Char) -> Option<cmp::Ordering> {
887        Some(self.as_bytes().cmp(other.as_bytes()))
888    }
889}
890
891impl PartialOrd<char> for Char {
892    #[inline]
893    fn partial_cmp(&self, other: &char) -> Option<cmp::Ordering> {
894        Some(self.as_char().cmp(other))
895    }
896}
897
898impl PartialOrd<Char> for char {
899    #[inline]
900    fn partial_cmp(&self, other: &Char) -> Option<cmp::Ordering> {
901        Some(self.cmp(&other.as_char()))
902    }
903}
904
905impl hash::Hash for &Char {
906    #[inline]
907    fn hash<H: hash::Hasher>(&self, state: &mut H) {
908        self.as_bytes().hash(state);
909    }
910}
911
912impl AsRef<str> for Char {
913    #[inline]
914    fn as_ref(&self) -> &str {
915        self.as_str()
916    }
917}
918
919impl AsMut<str> for Char {
920    #[inline]
921    fn as_mut(&mut self) -> &mut str {
922        self.as_str_mut()
923    }
924}
925
926impl Borrow<str> for Char {
927    #[inline]
928    fn borrow(&self) -> &str {
929        self.as_str()
930    }
931}
932
933impl BorrowMut<str> for Char {
934    #[inline]
935    fn borrow_mut(&mut self) -> &mut str {
936        self.as_str_mut()
937    }
938}
939
940#[cfg(feature = "alloc")]
941impl ToOwned for Char {
942    type Owned = OwnedChar;
943
944    #[inline]
945    fn to_owned(&self) -> Self::Owned {
946        self.as_owned()
947    }
948
949    #[inline]
950    fn clone_into(&self, target: &mut Self::Owned) {
951        let bytes = self.as_bytes();
952
953        // SAFETY:
954        // `bytes` is guaranteed to be a valid UTF-8 character. The succeeding
955        // bytes do not have to be zeroed as they will not be read.
956        unsafe { target.buffer_mut()[..bytes.len()].copy_from_slice(bytes) }
957    }
958}
959
960impl From<&Char> for char {
961    #[inline]
962    fn from(value: &Char) -> Self {
963        value.as_char()
964    }
965}
966
967impl TryFrom<&str> for &Char {
968    type Error = TryFromStrError;
969
970    #[inline]
971    fn try_from(value: &str) -> Result<Self, Self::Error> {
972        if value.is_empty() {
973            return Err(TryFromStrError::Empty);
974        }
975
976        // SAFETY:
977        // `value` is a `str` with at least one character, so its pointer must
978        // point to a valid character.
979        let c = unsafe { &*Char::new_unchecked(value.as_ptr()) };
980
981        if value.len() == c.len() {
982            Ok(c)
983        } else {
984            Err(TryFromStrError::MultipleChars)
985        }
986    }
987}
988
989impl TryFrom<&mut str> for &mut Char {
990    type Error = TryFromStrError;
991
992    #[inline]
993    fn try_from(value: &mut str) -> Result<Self, Self::Error> {
994        if value.is_empty() {
995            return Err(TryFromStrError::Empty);
996        }
997
998        // SAFETY:
999        // `value` is a `str` with at least one character, so its pointer must
1000        // point to a valid character.
1001        let c = unsafe { &mut *Char::new_unchecked_mut(value.as_mut_ptr()) };
1002
1003        if value.len() == c.len() {
1004            Ok(c)
1005        } else {
1006            Err(TryFromStrError::MultipleChars)
1007        }
1008    }
1009}
1010
1011impl FromStr for &Char {
1012    type Err = TryFromStrError;
1013
1014    #[inline]
1015    fn from_str(s: &str) -> Result<Self, Self::Err> {
1016        Self::try_from(s)
1017    }
1018}
1019
1020impl TryFrom<&[u8]> for &Char {
1021    type Error = TryFromBytesError;
1022
1023    #[inline]
1024    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
1025        if value.len() > 4 {
1026            return Err(TryFromStrError::MultipleChars.into());
1027        }
1028
1029        let s = str::from_utf8(value)?;
1030        Self::try_from(s).map_err(TryFromBytesError::Length)
1031    }
1032}
1033
1034impl TryFrom<&mut [u8]> for &mut Char {
1035    type Error = TryFromBytesError;
1036
1037    #[inline]
1038    fn try_from(value: &mut [u8]) -> Result<Self, Self::Error> {
1039        if value.len() > 4 {
1040            return Err(TryFromStrError::MultipleChars.into());
1041        }
1042
1043        let s = str::from_utf8_mut(value)?;
1044        Self::try_from(s).map_err(TryFromBytesError::Length)
1045    }
1046}
1047
1048#[cfg(test)]
1049mod test {
1050    use core::str;
1051
1052    use crate::{
1053        iter::{CharMutRefs, CharRefs},
1054        test::{test_str_owned, TEST_STR},
1055        Char,
1056    };
1057
1058    #[test]
1059    fn test_len() {
1060        for (expected_char, char) in TEST_STR.chars().zip(CharRefs::from(TEST_STR)) {
1061            assert_eq!(char.len(), expected_char.len_utf8());
1062        }
1063    }
1064
1065    #[test]
1066    fn test_get() {
1067        for (i, expected) in TEST_STR.chars().enumerate() {
1068            let actual = Char::get(TEST_STR, i).expect("expected a character reference");
1069            assert_eq!(actual.as_char(), expected);
1070        }
1071
1072        let mut s = test_str_owned();
1073
1074        for (i, expected) in TEST_STR.chars().enumerate() {
1075            let actual = Char::get_mut(&mut s, i).expect("expected a character reference");
1076            assert_eq!(actual.as_char(), expected);
1077        }
1078
1079        assert_eq!(
1080            &*s, TEST_STR,
1081            "`Char::get_mut` mutated the mutable string slice"
1082        );
1083    }
1084
1085    #[test]
1086    fn test_as() {
1087        let pr = TEST_STR.as_bytes().as_ptr_range();
1088
1089        for (c, actual) in TEST_STR.chars().zip(CharRefs::from(TEST_STR)) {
1090            assert_eq!(actual.as_char(), c);
1091
1092            let mut buffer = [0; 4];
1093
1094            let s = c.encode_utf8(&mut buffer);
1095            let len = s.len();
1096            assert_eq!(actual.as_str(), s);
1097
1098            let b = &buffer[..len];
1099            assert_eq!(actual.as_bytes(), b);
1100
1101            assert!(pr.contains(&actual.as_ptr()));
1102        }
1103
1104        let mut s = test_str_owned();
1105        let pr2 = s.as_bytes().as_ptr_range();
1106
1107        for (c, actual) in TEST_STR.chars().zip(CharMutRefs::from(&mut *s)) {
1108            assert_eq!(actual.as_char(), c);
1109
1110            let mut buffer = [0; 4];
1111
1112            let s2 = c.encode_utf8(&mut buffer);
1113            let len = s2.len();
1114            assert_eq!(actual.as_str_mut(), s2);
1115
1116            let b = &buffer[..len];
1117            // SAFETY:
1118            // Not mutating.
1119            assert_eq!(unsafe { actual.as_bytes_mut() }, b);
1120
1121            assert!(pr2.contains(&actual.as_ptr()));
1122        }
1123
1124        assert_eq!(
1125            &*s, TEST_STR,
1126            "`Char` as methods mutated the mutable string slice"
1127        );
1128    }
1129
1130    macro_rules! replace {
1131        ( ($fn:path)($c:expr $(, $arg:expr)*) <- $c2:expr, $expected:ident => $cfg:block ) => {
1132            let mut buffer = [0; 6];
1133            let s = $c2.encode_utf8(&mut buffer[1..]);
1134            let c2 = <&mut Char>::try_from(s).unwrap();
1135
1136            $fn(c2, $c $(, $arg)*).expect(concat!(stringify!($fn), " returned an error"));
1137
1138            let mut $expected = [0; 6];
1139            $cfg
1140
1141            assert_eq!(buffer, $expected, concat!(stringify!($fn), " failed a replace"));
1142        };
1143    }
1144
1145    #[test]
1146    fn test_replace() {
1147        let test_chars = ['a', 'à', 'ḁ', '🔤'];
1148
1149        for (i, c) in TEST_STR.chars().enumerate() {
1150            replace!((Char::replace)(c) <- test_chars[i], expected_buffer => {
1151                c.encode_utf8(&mut expected_buffer[1..=4]);
1152            });
1153
1154            for test_char in &test_chars[i..] {
1155                let test_char_len = test_char.len_utf8();
1156
1157                replace!(
1158                    (Char::replace_with_pad_space)(c) <- test_char,
1159                    expected_buffer => {
1160                        let len = c.encode_utf8(&mut expected_buffer[1..]).len();
1161                        expected_buffer[(len + 1)..=test_char_len].fill(b' ');
1162                    }
1163                );
1164
1165                replace!(
1166                    (Char::replace_with_pad)(c, b'a') <- test_char,
1167                    expected_buffer => {
1168                        let len = c.encode_utf8(&mut expected_buffer[1..]).len();
1169                        expected_buffer[(len + 1)..=test_char_len].fill(b'a');
1170                    }
1171                );
1172
1173                replace!(
1174                    (Char::replace_with_pad_char)(c, 'a') <- test_char,
1175                    expected_buffer => {
1176                        let len = c.encode_utf8(&mut expected_buffer[1..]).len();
1177                        expected_buffer[(len + 1)..=test_char_len].fill(b'a');
1178                    }
1179                );
1180
1181                replace!(
1182                    (Char::replace_with_pad_left_space)(c) <- test_char,
1183                    expected_buffer => {
1184                        let i = test_char_len + 1 - c.len_utf8();
1185                        c.encode_utf8(&mut expected_buffer[i..]);
1186                    expected_buffer[1..i].fill(b' ');
1187                    }
1188                );
1189
1190                replace!(
1191                    (Char::replace_with_pad_left)(c, b'a') <- test_char,
1192                    expected_buffer => {
1193                        let i = test_char_len + 1 - c.len_utf8();
1194                        c.encode_utf8(&mut expected_buffer[i..]);
1195                    expected_buffer[1..i].fill(b'a');
1196                    }
1197                );
1198
1199                replace!(
1200                    (Char::replace_with_pad_left_char)(c, 'a') <- test_char,
1201                    expected_buffer => {
1202                        let i = test_char_len + 1 - c.len_utf8();
1203                        c.encode_utf8(&mut expected_buffer[i..]);
1204                    expected_buffer[1..i].fill(b'a');
1205                    }
1206                );
1207            }
1208        }
1209    }
1210
1211    #[test]
1212    fn test_eq() {
1213        for c in CharRefs::from(TEST_STR) {
1214            assert_eq!(c, c.as_str());
1215            assert_eq!(c, c.as_char());
1216
1217            {
1218                // Make sure that the character with a suffix does not equal it.
1219                let mut buffer = [b' '; 5];
1220                c.copy_to(&mut buffer).unwrap();
1221
1222                // SAFETY:
1223                // This is valid as the buffer was full of single-byte utf8
1224                // encoded characters and then had another embedded into it.
1225                let s = unsafe { str::from_utf8_unchecked(&buffer) };
1226
1227                assert_ne!(c, s);
1228            }
1229            assert_ne!(c, "b");
1230            assert_ne!(c, 'b');
1231        }
1232    }
1233}