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}