1use std::ops::{
6 Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
7};
8
9use byteorder::ByteOrder;
10
11use crate::{WStr, WString};
12
13mod private {
14 use super::*;
15
16 pub trait SealedSliceIndex {}
17
18 impl SealedSliceIndex for RangeFull {}
19 impl SealedSliceIndex for Range<usize> {}
20 impl SealedSliceIndex for RangeFrom<usize> {}
21 impl SealedSliceIndex for RangeTo<usize> {}
22 impl SealedSliceIndex for RangeInclusive<usize> {}
23 impl SealedSliceIndex for RangeToInclusive<usize> {}
24}
25pub trait SliceIndex<T>: private::SealedSliceIndex
30where
31 T: ?Sized,
32{
33 type Output: ?Sized;
35
36 fn get(self, slice: &T) -> Option<&Self::Output>;
38
39 fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>;
41
42 unsafe fn get_unchecked(self, slice: &T) -> &Self::Output;
49
50 unsafe fn get_unchecked_mut(self, slice: &mut T) -> &mut Self::Output;
57
58 fn index(self, slice: &T) -> &Self::Output;
60
61 fn index_mut(self, slice: &mut T) -> &mut Self::Output;
63}
64
65impl<E> SliceIndex<WStr<E>> for RangeFull
69where
70 E: ByteOrder,
71{
72 type Output = WStr<E>;
73
74 #[inline]
75 fn get(self, slice: &WStr<E>) -> Option<&Self::Output> {
76 Some(slice)
77 }
78
79 #[inline]
80 fn get_mut(self, slice: &mut WStr<E>) -> Option<&mut Self::Output> {
81 Some(slice)
82 }
83
84 #[inline]
85 unsafe fn get_unchecked(self, slice: &WStr<E>) -> &Self::Output {
86 slice
87 }
88
89 #[inline]
90 unsafe fn get_unchecked_mut(self, slice: &mut WStr<E>) -> &mut Self::Output {
91 slice
92 }
93
94 #[inline]
95 fn index(self, slice: &WStr<E>) -> &Self::Output {
96 slice
97 }
98
99 #[inline]
100 fn index_mut(self, slice: &mut WStr<E>) -> &mut Self::Output {
101 slice
102 }
103}
104
105impl<E> SliceIndex<WStr<E>> for Range<usize>
107where
108 E: ByteOrder,
109{
110 type Output = WStr<E>;
111
112 #[inline]
113 fn get(self, slice: &WStr<E>) -> Option<&Self::Output> {
114 if self.start <= self.end
115 && slice.is_char_boundary(self.start)
116 && slice.is_char_boundary(self.end)
117 {
118 Some(unsafe { self.get_unchecked(slice) })
119 } else {
120 None
121 }
122 }
123
124 #[inline]
125 fn get_mut(self, slice: &mut WStr<E>) -> Option<&mut Self::Output> {
126 if self.start <= self.end
127 && slice.is_char_boundary(self.start)
128 && slice.is_char_boundary(self.end)
129 {
130 Some(unsafe { self.get_unchecked_mut(slice) })
131 } else {
132 None
133 }
134 }
135
136 #[inline]
137 unsafe fn get_unchecked(self, slice: &WStr<E>) -> &Self::Output {
138 let ptr = slice.as_ptr().add(self.start);
139 let len = self.end - self.start;
140 WStr::from_utf16_unchecked(std::slice::from_raw_parts(ptr, len))
141 }
142
143 #[inline]
144 unsafe fn get_unchecked_mut(self, slice: &mut WStr<E>) -> &mut Self::Output {
145 let ptr = slice.as_mut_ptr().add(self.start);
146 let len = self.end - self.start;
147 WStr::from_utf16_unchecked_mut(std::slice::from_raw_parts_mut(ptr, len))
148 }
149
150 #[inline]
151 fn index(self, slice: &WStr<E>) -> &Self::Output {
152 self.get(slice).expect("slice index out of bounds")
153 }
154
155 #[inline]
156 fn index_mut(self, slice: &mut WStr<E>) -> &mut Self::Output {
157 self.get_mut(slice).expect("slice index out of bounds")
158 }
159}
160
161impl<E> SliceIndex<WStr<E>> for RangeTo<usize>
163where
164 E: ByteOrder,
165{
166 type Output = WStr<E>;
167
168 #[inline]
169 fn get(self, slice: &WStr<E>) -> Option<&Self::Output> {
170 if slice.is_char_boundary(self.end) {
171 Some(unsafe { self.get_unchecked(slice) })
172 } else {
173 None
174 }
175 }
176
177 #[inline]
178 fn get_mut(self, slice: &mut WStr<E>) -> Option<&mut Self::Output> {
179 if slice.is_char_boundary(self.end) {
180 Some(unsafe { self.get_unchecked_mut(slice) })
181 } else {
182 None
183 }
184 }
185
186 #[inline]
187 unsafe fn get_unchecked(self, slice: &WStr<E>) -> &Self::Output {
188 let ptr = slice.as_ptr();
189 WStr::from_utf16_unchecked(std::slice::from_raw_parts(ptr, self.end))
190 }
191
192 #[inline]
193 unsafe fn get_unchecked_mut(self, slice: &mut WStr<E>) -> &mut Self::Output {
194 let ptr = slice.as_mut_ptr();
195 WStr::from_utf16_unchecked_mut(std::slice::from_raw_parts_mut(ptr, self.end))
196 }
197
198 #[inline]
199 fn index(self, slice: &WStr<E>) -> &Self::Output {
200 self.get(slice).expect("slice index out of bounds")
201 }
202
203 #[inline]
204 fn index_mut(self, slice: &mut WStr<E>) -> &mut Self::Output {
205 self.get_mut(slice).expect("slice index out of bounds")
206 }
207}
208
209impl<E> SliceIndex<WStr<E>> for RangeFrom<usize>
211where
212 E: ByteOrder,
213{
214 type Output = WStr<E>;
215
216 #[inline]
217 fn get(self, slice: &WStr<E>) -> Option<&Self::Output> {
218 if slice.is_char_boundary(self.start) {
219 Some(unsafe { self.get_unchecked(slice) })
220 } else {
221 None
222 }
223 }
224
225 #[inline]
226 fn get_mut(self, slice: &mut WStr<E>) -> Option<&mut Self::Output> {
227 if slice.is_char_boundary(self.start) {
228 Some(unsafe { self.get_unchecked_mut(slice) })
229 } else {
230 None
231 }
232 }
233
234 #[inline]
235 unsafe fn get_unchecked(self, slice: &WStr<E>) -> &Self::Output {
236 let ptr = slice.as_ptr().add(self.start);
237 let len = slice.len() - self.start;
238 WStr::from_utf16_unchecked(std::slice::from_raw_parts(ptr, len))
239 }
240
241 #[inline]
242 unsafe fn get_unchecked_mut(self, slice: &mut WStr<E>) -> &mut Self::Output {
243 let ptr = slice.as_mut_ptr().add(self.start);
244 let len = slice.len() - self.start;
245 WStr::from_utf16_unchecked_mut(std::slice::from_raw_parts_mut(ptr, len))
246 }
247
248 #[inline]
249 fn index(self, slice: &WStr<E>) -> &Self::Output {
250 self.get(slice).expect("slice index out of bounds")
251 }
252
253 #[inline]
254 fn index_mut(self, slice: &mut WStr<E>) -> &mut Self::Output {
255 self.get_mut(slice).expect("slice index out of bounds")
256 }
257}
258
259impl<E> SliceIndex<WStr<E>> for RangeInclusive<usize>
261where
262 E: ByteOrder,
263{
264 type Output = WStr<E>;
265
266 #[inline]
267 fn get(self, slice: &WStr<E>) -> Option<&Self::Output> {
268 if *self.end() == usize::MAX {
269 None
270 } else {
271 (*self.start()..self.end() + 1).get(slice)
272 }
273 }
274
275 #[inline]
276 fn get_mut(self, slice: &mut WStr<E>) -> Option<&mut Self::Output> {
277 if *self.end() == usize::MAX {
278 None
279 } else {
280 (*self.start()..self.end() + 1).get_mut(slice)
281 }
282 }
283
284 #[inline]
285 unsafe fn get_unchecked(self, slice: &WStr<E>) -> &Self::Output {
286 (*self.start()..self.end() + 1).get_unchecked(slice)
287 }
288
289 #[inline]
290 unsafe fn get_unchecked_mut(self, slice: &mut WStr<E>) -> &mut Self::Output {
291 (*self.start()..self.end() + 1).get_unchecked_mut(slice)
292 }
293
294 #[inline]
295 fn index(self, slice: &WStr<E>) -> &Self::Output {
296 if *self.end() == usize::MAX {
297 panic!("index overflow");
298 }
299 (*self.start()..self.end() + 1).index(slice)
300 }
301
302 #[inline]
303 fn index_mut(self, slice: &mut WStr<E>) -> &mut Self::Output {
304 if *self.end() == usize::MAX {
305 panic!("index overflow");
306 }
307 (*self.start()..self.end() + 1).index_mut(slice)
308 }
309}
310
311impl<E> SliceIndex<WStr<E>> for RangeToInclusive<usize>
313where
314 E: ByteOrder,
315{
316 type Output = WStr<E>;
317
318 #[inline]
319 fn get(self, slice: &WStr<E>) -> Option<&Self::Output> {
320 if self.end == usize::MAX {
321 None
322 } else {
323 (..self.end + 1).get(slice)
324 }
325 }
326
327 #[inline]
328 fn get_mut(self, slice: &mut WStr<E>) -> Option<&mut Self::Output> {
329 if self.end == usize::MAX {
330 None
331 } else {
332 (..self.end + 1).get_mut(slice)
333 }
334 }
335
336 #[inline]
337 unsafe fn get_unchecked(self, slice: &WStr<E>) -> &Self::Output {
338 (..self.end + 1).get_unchecked(slice)
339 }
340
341 #[inline]
342 unsafe fn get_unchecked_mut(self, slice: &mut WStr<E>) -> &mut Self::Output {
343 (..self.end + 1).get_unchecked_mut(slice)
344 }
345
346 #[inline]
347 fn index(self, slice: &WStr<E>) -> &Self::Output {
348 if self.end == usize::MAX {
349 panic!("index overflow");
350 }
351 (..self.end + 1).index(slice)
352 }
353
354 #[inline]
355 fn index_mut(self, slice: &mut WStr<E>) -> &mut Self::Output {
356 if self.end == usize::MAX {
357 panic!("index overflow");
358 }
359 (..self.end + 1).index_mut(slice)
360 }
361}
362
363impl<I, E> Index<I> for WStr<E>
364where
365 I: SliceIndex<WStr<E>>,
366 E: ByteOrder,
367{
368 type Output = I::Output;
369
370 #[inline]
371 fn index(&self, index: I) -> &I::Output {
372 index.index(self)
373 }
374}
375
376impl<I, E> IndexMut<I> for WStr<E>
377where
378 I: SliceIndex<WStr<E>>,
379 E: ByteOrder,
380{
381 #[inline]
382 fn index_mut(&mut self, index: I) -> &mut I::Output {
383 index.index_mut(self)
384 }
385}
386
387impl<I, E> Index<I> for WString<E>
388where
389 I: SliceIndex<WStr<E>>,
390 E: ByteOrder,
391{
392 type Output = I::Output;
393
394 #[inline]
395 fn index(&self, index: I) -> &I::Output {
396 index.index(self)
397 }
398}
399
400impl<I, E> IndexMut<I> for WString<E>
401where
402 I: SliceIndex<WStr<E>>,
403 E: ByteOrder,
404{
405 #[inline]
406 fn index_mut(&mut self, index: I) -> &mut I::Output {
407 index.index_mut(self)
408 }
409}
410
411#[cfg(test)]
412mod tests {
413 use super::*;
414
415 #[test]
416 fn test_wstr_range() {
417 let b = b"h\x00e\x00l\x00l\x00o\x00";
418 let s = WStr::from_utf16le(b).unwrap();
419 let t = &s[2..8];
420
421 assert_eq!(t.to_utf8(), "ell");
422 }
423
424 #[test]
425 fn test_wstr_range_to() {
426 let b = b"h\x00e\x00l\x00l\x00o\x00";
427 let s = WStr::from_utf16le(b).unwrap();
428 let t = &s[..8];
429
430 assert_eq!(t.to_utf8(), "hell");
431 }
432
433 #[test]
434 fn test_wstr_range_from() {
435 let b = b"h\x00e\x00l\x00l\x00o\x00";
436 let s = WStr::from_utf16le(b).unwrap();
437 let t = &s[2..];
438
439 assert_eq!(t.to_utf8(), "ello");
440 }
441
442 #[test]
443 fn test_wstr_range_full() {
444 let b = b"h\x00e\x00l\x00l\x00o\x00";
445 let s = WStr::from_utf16le(b).unwrap();
446 let t = &s[..];
447
448 assert_eq!(t.to_utf8(), "hello");
449 }
450
451 #[test]
452 fn test_wstr_range_inclusive() {
453 let b = b"h\x00e\x00l\x00l\x00o\x00";
454 let s = WStr::from_utf16le(b).unwrap();
455 let t = &s[2..=7];
456
457 assert_eq!(t.to_utf8(), "ell");
458 }
459
460 #[test]
461 fn test_wstr_range_to_inclusive() {
462 let b = b"h\x00e\x00l\x00l\x00o\x00";
463 let s = WStr::from_utf16le(b).unwrap();
464 let t = &s[..=7];
465
466 assert_eq!(t.to_utf8(), "hell");
467 }
468
469 #[test]
470 fn test_wstring_range() {
471 let b = b"h\x00e\x00l\x00l\x00o\x00";
472 let s = WString::from_utf16le(b.to_vec()).unwrap();
473 let t = &s[2..8];
474
475 assert_eq!(t.to_utf8(), "ell");
476 }
477
478 #[test]
479 fn test_wstring_range_to() {
480 let b = b"h\x00e\x00l\x00l\x00o\x00";
481 let s = WString::from_utf16le(b.to_vec()).unwrap();
482 let t = &s[..8];
483
484 assert_eq!(t.to_utf8(), "hell");
485 }
486
487 #[test]
488 fn test_wstring_range_from() {
489 let b = b"h\x00e\x00l\x00l\x00o\x00";
490 let s = WString::from_utf16le(b.to_vec()).unwrap();
491 let t = &s[2..];
492
493 assert_eq!(t.to_utf8(), "ello");
494 }
495
496 #[test]
497 fn test_wstring_range_full() {
498 let b = b"h\x00e\x00l\x00l\x00o\x00";
499 let s = WString::from_utf16le(b.to_vec()).unwrap();
500 let t = &s[..];
501
502 assert_eq!(t.to_utf8(), "hello");
503 }
504
505 #[test]
506 fn test_wstring_range_inclusive() {
507 let b = b"h\x00e\x00l\x00l\x00o\x00";
508 let s = WString::from_utf16le(b.to_vec()).unwrap();
509 let t = &s[2..=7];
510
511 assert_eq!(t.to_utf8(), "ell");
512 }
513
514 #[test]
515 fn test_wstring_range_to_inclusive() {
516 let b = b"h\x00e\x00l\x00l\x00o\x00";
517 let s = WString::from_utf16le(b.to_vec()).unwrap();
518 let t = &s[..=7];
519
520 assert_eq!(t.to_utf8(), "hell");
521 }
522}