generic_str/
slice_utf32.rs

1use core::slice::SliceIndex;
2
3use crate::StringSlice;
4
5#[allow(non_camel_case_types)]
6/// Exactly the same as [`std::str`], except generic
7pub type str32 = StringSlice<char>;
8
9impl str32 {
10    /// Returns the length of `self`.
11    ///
12    /// This length is in bytes, not [`char`]s or graphemes. In other words,
13    /// it may not be what a human considers the length of the string.
14    ///
15    /// [`char`]: prim@char
16    ///
17    /// # Examples
18    ///
19    /// Basic usage:
20    ///
21    /// ```
22    /// # use generic_str::String32;
23    /// assert_eq!(String32::from("foo").len(), 3);
24    /// assert_eq!(String32::from("ƒoo").len(), 3); // fancy f!
25    /// ```
26    #[inline]
27    pub fn len(&self) -> usize {
28        self.storage.as_ref().len()
29    }
30
31    /// Returns `true` if `self` has a length of zero bytes.
32    ///
33    /// # Examples
34    ///
35    /// Basic usage:
36    ///
37    /// ```
38    /// # use generic_str::String32;
39    /// let s = String32::from("");
40    /// assert!(s.is_empty());
41    ///
42    /// let s = String32::from("not empty");
43    /// assert!(!s.is_empty());
44    /// ```
45    #[inline]
46    pub fn is_empty(&self) -> bool {
47        self.storage.is_empty()
48    }
49
50    /// Converts a string slice to a raw pointer.
51    ///
52    /// As string slices are a slice of bytes, the raw pointer points to a
53    /// [`char`]. This pointer will be pointing to the first byte of the string
54    /// slice.
55    ///
56    /// The caller must ensure that the returned pointer is never written to.
57    /// If you need to mutate the contents of the string slice, use [`as_mut_ptr`].
58    ///
59    /// [`as_mut_ptr`]: str::as_mut_ptr
60    ///
61    /// # Examples
62    ///
63    /// Basic usage:
64    ///
65    /// ```
66    /// # use generic_str::String32;
67    /// let s = String32::from("Hello");
68    /// let ptr = s.as_ptr();
69    /// ```
70    #[inline]
71    pub fn as_ptr(&self) -> *const char {
72        self.storage.as_ref() as *const [char] as *const char
73    }
74
75    /// Converts a mutable string slice to a raw pointer.
76    ///
77    /// As string slices are a slice of bytes, the raw pointer points to a
78    /// [`char`]. This pointer will be pointing to the first byte of the string
79    /// slice.
80    #[inline]
81    pub fn as_mut_ptr(&mut self) -> *mut char {
82        self.storage.as_mut() as *mut [char] as *mut char
83    }
84
85    /// Converts a mutable string slice to a raw pointer.
86    ///
87    /// As string slices are a slice of bytes, the raw pointer points to a
88    /// [`char`]. This pointer will be pointing to the first byte of the string
89    /// slice.
90    #[inline]
91    pub fn from_slice(data: &[char]) -> &Self {
92        unsafe { core::mem::transmute(data) }
93    }
94
95    /// Converts a mutable string slice to a raw pointer.
96    ///
97    /// As string slices are a slice of bytes, the raw pointer points to a
98    /// [`char`]. This pointer will be pointing to the first byte of the string
99    /// slice.
100    #[inline]
101    pub fn from_slice_mut(data: &mut [char]) -> &mut Self {
102        unsafe { core::mem::transmute(data) }
103    }
104
105    /// Returns a subslice of `str`.
106    ///
107    /// This is the non-panicking alternative to indexing the `str`. Returns
108    /// [`None`] whenever equivalent indexing operation would panic.
109    ///
110    /// # Examples
111    ///
112    /// ```
113    /// # use generic_str::{str, String32};
114    /// let v = String32::from("🗻∈🌏");
115    ///
116    /// assert_eq!(v.get(0..2).unwrap().to_owned(), String32::from("🗻∈"));
117    ///
118    /// // out of bounds
119    /// assert!(v.get(..4).is_none());
120    /// ```
121    #[inline]
122    pub fn get<I: SliceIndex<Self>>(&self, i: I) -> Option<&I::Output> {
123        i.get(self.as_ref())
124    }
125
126    /// Returns a mutable subslice of `str`.
127    ///
128    /// This is the non-panicking alternative to indexing the `str`. Returns
129    /// [`None`] whenever equivalent indexing operation would panic.
130    ///
131    /// # Examples
132    ///
133    /// ```
134    /// # use generic_str::{str, String32};
135    /// let mut v = String32::from("hello");
136    /// // correct length
137    /// assert!(v.get_mut(0..5).is_some());
138    /// // out of bounds
139    /// assert!(v.get_mut(..42).is_none());
140    ///
141    /// {
142    ///     let s = v.get_mut(0..2);
143    ///     let s = s.map(|s| {
144    ///         s.make_ascii_uppercase();
145    ///         &*s
146    ///     });
147    /// }
148    /// assert_eq!(v, String32::from("HEllo"));
149    /// ```
150    #[inline]
151    pub fn get_mut<I: SliceIndex<Self>>(&mut self, i: I) -> Option<&mut I::Output> {
152        i.get_mut(self.as_mut())
153    }
154
155    /// Returns an unchecked subslice of `str`.
156    ///
157    /// This is the unchecked alternative to indexing the `str`.
158    ///
159    /// # Safety
160    ///
161    /// Callers of this function are responsible that these preconditions are
162    /// satisfied:
163    ///
164    /// * The starting index must not exceed the ending index;
165    /// * Indexes must be within bounds of the original slice;
166    /// * Indexes must lie on UTF-8 sequence boundaries.
167    ///
168    /// Failing that, the returned string slice may reference invalid memory or
169    /// violate the invariants communicated by the `str` type.
170    ///
171    /// # Examples
172    ///
173    /// ```
174    /// # use generic_str::String32;
175    /// let v = "🗻∈🌏";
176    /// unsafe {
177    ///     assert_eq!(v.get_unchecked(0..4), "🗻");
178    ///     assert_eq!(v.get_unchecked(4..7), "∈");
179    ///     assert_eq!(v.get_unchecked(7..11), "🌏");
180    /// }
181    /// ```
182    #[inline]
183    pub unsafe fn get_unchecked<I: SliceIndex<Self>>(&self, i: I) -> &I::Output {
184        // SAFETY: the caller must uphold the safety contract for `get_unchecked`;
185        // the slice is dereferencable because `self` is a safe reference.
186        // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is.
187        &*i.get_unchecked(self)
188    }
189
190    /// Returns a mutable, unchecked subslice of `str`.
191    ///
192    /// This is the unchecked alternative to indexing the `str`.
193    ///
194    /// # Safety
195    ///
196    /// Callers of this function are responsible that these preconditions are
197    /// satisfied:
198    ///
199    /// * The starting index must not exceed the ending index;
200    /// * Indexes must be within bounds of the original slice;
201    /// * Indexes must lie on UTF-8 sequence boundaries.
202    ///
203    /// Failing that, the returned string slice may reference invalid memory or
204    /// violate the invariants communicated by the `str` type.
205    ///
206    /// # Examples
207    ///
208    /// ```
209    /// # use generic_str::String32;
210    /// let mut v = String32::from("🗻∈🌏");
211    /// unsafe {
212    ///     assert_eq!(*v.get_unchecked_mut(0..2), String32::from("🗻∈"));
213    /// }
214    /// ```
215    #[inline]
216    pub unsafe fn get_unchecked_mut<I: SliceIndex<Self>>(&mut self, i: I) -> &mut I::Output {
217        // SAFETY: the caller must uphold the safety contract for `get_unchecked_mut`;
218        // the slice is dereferencable because `self` is a safe reference.
219        // The returned pointer is safe because impls of `SliceIndex` have to guarantee that it is.
220        &mut *i.get_unchecked_mut(self)
221    }
222
223    /// Divide one string slice into two at an index.
224    ///
225    /// The two slices returned go from the start of the string slice to `mid`,
226    /// and from `mid` to the end of the string slice.
227    ///
228    /// To get mutable string slices instead, see the [`split_at_mut`]
229    /// method.
230    ///
231    /// [`split_at_mut`]: str32::split_at_mut
232    ///
233    /// # Panics
234    ///
235    /// Panics if `mid` is past the end of the last code point of the string slice.
236    ///
237    /// # Examples
238    ///
239    /// Basic usage:
240    ///
241    /// ```
242    /// # use generic_str::String32;
243    /// let s = String32::from("Per Martin-Löf");
244    ///
245    /// let (first, last) = s.split_at(3);
246    ///
247    /// assert_eq!(first.to_owned(), String32::from("Per"));
248    /// assert_eq!(last.to_owned(), String32::from(" Martin-Löf"));
249    /// ```
250    #[inline]
251    pub fn split_at(&self, mid: usize) -> (&Self, &Self) {
252        if mid <= self.len() {
253            unsafe {
254                (
255                    self.get_unchecked(0..mid),
256                    self.get_unchecked(mid..self.len()),
257                )
258            }
259        } else {
260            #[cfg(feature = "alloc")]
261            panic!("char index {} is out of bounds of `{}`", mid, self);
262
263            #[cfg(not(feature = "alloc"))]
264            panic!("char index {} is out of bounds", mid);
265        }
266    }
267
268    /// Divide one mutable string slice into two at an index.
269    ///
270    /// The argument, `mid`, should be a byte offset from the start of the
271    /// string. It must also be on the boundary of a UTF-8 code point.
272    ///
273    /// The two slices returned go from the start of the string slice to `mid`,
274    /// and from `mid` to the end of the string slice.
275    ///
276    /// To get immutable string slices instead, see the [`split_at`] method.
277    ///
278    /// [`split_at`]: str32::split_at
279    ///
280    /// # Panics
281    ///
282    /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
283    /// past the end of the last code point of the string slice.
284    ///
285    /// # Examples
286    ///
287    /// Basic usage:
288    ///
289    /// ```
290    /// # use generic_str::String32;
291    /// let mut s = String32::from("Per Martin-Löf");
292    /// {
293    ///     let (first, last) = s.split_at_mut(3);
294    ///     first.make_ascii_uppercase();
295    ///     assert_eq!(first.to_owned(), String32::from("PER"));
296    ///     assert_eq!(last.to_owned(), String32::from(" Martin-Löf"));
297    /// }
298    /// assert_eq!(s, String32::from("PER Martin-Löf"));
299    /// ```
300    #[inline]
301    pub fn split_at_mut(&mut self, mid: usize) -> (&mut Self, &mut Self) {
302        // is_char_boundary checks that the index is in [0, .len()]
303        if mid < self.len() {
304            let len = self.len();
305            let ptr = self.as_mut_ptr();
306            // SAFETY: just checked that `mid` is on a char boundary.
307            unsafe {
308                (
309                    Self::from_slice_mut(core::slice::from_raw_parts_mut(ptr, mid)),
310                    Self::from_slice_mut(core::slice::from_raw_parts_mut(ptr.add(mid), len - mid)),
311                )
312            }
313        } else {
314            #[cfg(feature = "alloc")]
315            panic!("char index {} is out of bounds of `{}`", mid, self);
316
317            #[cfg(not(feature = "alloc"))]
318            panic!("char index {} is out of bounds", mid);
319        }
320    }
321
322    /// Converts this string to its ASCII upper case equivalent in-place.
323    ///
324    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
325    /// but non-ASCII letters are unchanged.
326    ///
327    /// To return a new uppercased value without modifying the existing one, use
328    /// [`to_ascii_uppercase()`].
329    ///
330    /// [`to_ascii_uppercase()`]: #method.to_ascii_uppercase
331    ///
332    /// # Examples
333    ///
334    /// ```
335    /// # use generic_str::String32;
336    /// let mut s = String32::from("Grüße, Jürgen ❤");
337    ///
338    /// s.make_ascii_uppercase();
339    ///
340    /// assert_eq!(s, String32::from("GRüßE, JüRGEN ❤"));
341    /// ```
342    #[inline]
343    pub fn make_ascii_uppercase(&mut self) {
344        self.storage.iter_mut().for_each(char::make_ascii_uppercase)
345    }
346
347    /// Converts this string to its ASCII lower case equivalent in-place.
348    ///
349    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
350    /// but non-ASCII letters are unchanged.
351    ///
352    /// To return a new lowercased value without modifying the existing one, use
353    /// [`to_ascii_lowercase()`].
354    ///
355    /// [`to_ascii_lowercase()`]: #method.to_ascii_lowercase
356    ///
357    /// # Examples
358    ///
359    /// ```
360    /// # use generic_str::String32;
361    /// let mut s = String32::from("GRÜßE, JÜRGEN ❤");
362    ///
363    /// s.make_ascii_lowercase();
364    ///
365    /// assert_eq!(s, String32::from("grÜße, jÜrgen ❤"));
366    /// ```
367    #[inline]
368    pub fn make_ascii_lowercase(&mut self) {
369        self.storage.iter_mut().for_each(char::make_ascii_lowercase)
370    }
371}