1use core::{
2 mem::transmute,
3 ops::{Bound, Deref, Index, IndexMut, RangeBounds},
4 ptr::{self, DynMetadata, Pointee},
5 slice,
6};
7
8use crate::{DynSlice, Iter, IterMut};
9
10#[repr(transparent)]
24pub struct DynSliceMut<'a, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>>>(
25 pub(crate) DynSlice<'a, Dyn>,
26);
27
28impl<'a, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>>> AsRef<DynSlice<'a, Dyn>>
29 for DynSliceMut<'a, Dyn>
30{
31 #[inline]
32 fn as_ref(&self) -> &DynSlice<'a, Dyn> {
33 &self.0
34 }
35}
36
37impl<'a, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>>> Deref for DynSliceMut<'a, Dyn> {
38 type Target = DynSlice<'a, Dyn>;
39
40 #[inline]
41 fn deref(&self) -> &Self::Target {
42 &self.0
43 }
44}
45
46impl<'a, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>>> DynSliceMut<'a, Dyn> {
47 #[inline]
48 #[must_use]
49 pub unsafe fn with_vtable_ptr<DynSliceFromType>(
54 value: &'a mut [DynSliceFromType],
55 vtable_ptr: *const (),
56 ) -> Self {
57 Self::from_parts(vtable_ptr, value.len(), value.as_mut_ptr().cast())
58 }
59
60 #[inline]
61 #[must_use]
62 pub unsafe fn with_metadata<DynSliceFromType>(
67 value: &'a mut [DynSliceFromType],
68 metadata: DynMetadata<Dyn>,
69 ) -> Self {
70 Self::with_vtable_ptr(value, transmute(metadata))
71 }
72
73 #[inline]
74 #[must_use]
75 pub const unsafe fn from_parts(vtable_ptr: *const (), len: usize, data: *mut ()) -> Self {
84 Self(DynSlice::from_parts(vtable_ptr, len, data))
85 }
86
87 #[inline]
88 #[must_use]
89 pub const unsafe fn from_parts_with_metadata(
98 metadata: DynMetadata<Dyn>,
99 len: usize,
100 data: *mut (),
101 ) -> Self {
102 Self::from_parts(transmute(metadata), len, data)
103 }
104
105 #[inline]
106 #[must_use]
107 pub fn as_mut_ptr(&mut self) -> *mut () {
109 self.0.data.cast_mut()
110 }
111
112 #[inline]
113 #[must_use]
114 pub unsafe fn first_unchecked_mut(&mut self) -> &mut Dyn {
120 debug_assert!(!self.is_empty(), "[dyn-slice] slice is empty!");
121 debug_assert!(
122 !self.vtable_ptr.is_null(),
123 "[dyn-slice] vtable pointer is null on access!"
124 );
125
126 &mut *ptr::from_raw_parts_mut::<Dyn>(self.as_mut_ptr(), transmute(self.vtable_ptr()))
127 }
128
129 #[must_use]
130 pub fn first_mut(&mut self) -> Option<&mut Dyn> {
143 (!self.0.is_empty()).then(|| {
144 debug_assert!(
145 !self.vtable_ptr.is_null(),
146 "[dyn-slice] vtable pointer is null on access!"
147 );
148
149 unsafe { self.first_unchecked_mut() }
153 })
154 }
155
156 #[must_use]
157 pub fn last_mut(&mut self) -> Option<&mut Dyn> {
170 (!self.0.is_empty()).then(|| {
171 unsafe { self.get_unchecked_mut(self.0.len - 1) }
175 })
176 }
177
178 #[must_use]
179 pub fn get_mut(&mut self, index: usize) -> Option<&mut Dyn> {
192 (index < self.0.len).then(|| {
193 unsafe { self.get_unchecked_mut(index) }
198 })
199 }
200
201 #[inline]
202 #[must_use]
203 pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut Dyn {
209 debug_assert!(
210 index < self.len,
211 "[dyn-slice] index is greater than length!"
212 );
213 debug_assert!(
214 !self.vtable_ptr.is_null(),
215 "[dyn-slice] vtable pointer is null on access!"
216 );
217
218 let metadata = transmute::<_, DynMetadata<Dyn>>(self.0.vtable_ptr());
219 &mut *ptr::from_raw_parts_mut::<Dyn>(
220 self.as_mut_ptr().byte_add(metadata.size_of() * index),
221 metadata,
222 )
223 }
224
225 #[inline]
226 #[must_use]
227 pub unsafe fn slice_unchecked_mut(&mut self, start: usize, len: usize) -> DynSliceMut<Dyn> {
234 debug_assert!(
236 start + len <= self.len,
237 "[dyn-slice] sub-slice is out of bounds!"
238 );
239
240 let metadata = transmute::<_, DynMetadata<Dyn>>(self.0.vtable_ptr());
241 Self::from_parts_with_metadata(
242 metadata,
243 len,
244 self.as_mut_ptr().byte_add(metadata.size_of() * start),
245 )
246 }
247
248 #[must_use]
249 pub fn slice_mut<R: RangeBounds<usize>>(&mut self, range: R) -> Option<DynSliceMut<Dyn>> {
265 let start_inclusive = match range.start_bound() {
268 Bound::Included(i) => *i,
269 Bound::Excluded(i) => i.checked_add(1)?,
270 Bound::Unbounded => 0,
271 };
272
273 let end_exclusive = match range.end_bound() {
274 Bound::Included(i) => i.checked_add(1)?,
275 Bound::Excluded(i) => *i,
276 Bound::Unbounded => self.0.len,
277 };
278
279 if end_exclusive > self.0.len {
280 return None;
281 }
282
283 let len = end_exclusive.checked_sub(start_inclusive)?;
284
285 Some(unsafe { self.slice_unchecked_mut(start_inclusive, len) })
290 }
291
292 #[inline]
293 #[must_use]
294 pub unsafe fn downcast_unchecked_mut<T>(&mut self) -> &mut [T] {
299 slice::from_raw_parts_mut(self.as_ptr().cast_mut().cast(), self.len)
300 }
301
302 #[inline]
303 #[must_use]
304 pub fn iter_mut(&mut self) -> IterMut<'_, Dyn> {
317 IterMut {
318 slice: unsafe { self.slice_unchecked_mut(0, self.len) },
322 }
323 }
324}
325
326impl<'a, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>>> Index<usize> for DynSliceMut<'a, Dyn> {
327 type Output = Dyn;
328
329 #[inline]
330 fn index(&self, index: usize) -> &Self::Output {
331 self.0.index(index)
332 }
333}
334
335impl<'a, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>>> IndexMut<usize>
336 for DynSliceMut<'a, Dyn>
337{
338 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
339 assert!(index < self.0.len, "index out of bounds");
340 debug_assert!(
341 !self.vtable_ptr.is_null(),
342 "[dyn-slice] vtable pointer is null on access!"
343 );
344
345 unsafe { self.get_unchecked_mut(index) }
350 }
351}
352
353impl<'a, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>>> IntoIterator for DynSliceMut<'a, Dyn> {
354 type IntoIter = IterMut<'a, Dyn>;
355 type Item = &'a mut Dyn;
356
357 fn into_iter(self) -> Self::IntoIter {
358 IterMut { slice: self }
359 }
360}
361
362impl<'a, 'b, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>>> IntoIterator
363 for &'b mut DynSliceMut<'a, Dyn>
364{
365 type IntoIter = IterMut<'b, Dyn>;
366 type Item = &'b mut Dyn;
367
368 fn into_iter(self) -> Self::IntoIter {
369 self.iter_mut()
370 }
371}
372
373impl<'a, 'b, Dyn: ?Sized + Pointee<Metadata = DynMetadata<Dyn>>> IntoIterator
374 for &'b DynSliceMut<'a, Dyn>
375{
376 type IntoIter = Iter<'b, Dyn>;
377 type Item = &'b Dyn;
378
379 fn into_iter(self) -> Self::IntoIter {
380 self.iter()
381 }
382}
383
384#[cfg(test)]
385mod test {
386 use core::{fmt::Display, ptr::addr_of};
387
388 use crate::{declare_new_fns, standard::partial_eq, DynSliceMut};
389
390 declare_new_fns!(
391 #[crate = crate]
392 display_dyn_slice Display
393 );
394 pub use display_dyn_slice::new_mut as new_display_dyn_slice;
395
396 #[test]
397 fn create_dyn_slice() {
398 let array: [u8; 5] = [1, 2, 3, 4, 5];
399 let mut array2 = array;
400
401 let dyn_slice = new_display_dyn_slice(&mut array2);
402
403 assert_eq!(dyn_slice.len(), array.len());
404 assert!(!dyn_slice.is_empty());
405
406 for (i, x) in array.iter().enumerate() {
407 assert_eq!(
408 format!(
409 "{}",
410 dyn_slice
411 .get(i)
412 .expect("failed to get an element of dyn_slice")
413 ),
414 format!("{x}"),
415 );
416 }
417 }
418
419 #[test]
420 fn empty() {
421 let mut array: [u8; 0] = [];
422
423 let dyn_slice = new_display_dyn_slice(&mut array);
424
425 assert_eq!(dyn_slice.len(), 0);
426 assert!(dyn_slice.is_empty());
427 }
428
429 #[test]
430 fn test_slice() {
431 type GetSliceFn = for<'a> fn(
432 &'a mut DynSliceMut<dyn PartialEq<i32>>,
433 ) -> DynSliceMut<'a, dyn PartialEq<i32>>;
434 type GetOptSliceFn = for<'a> fn(
435 &'a mut DynSliceMut<dyn PartialEq<i32>>,
436 ) -> Option<DynSliceMut<'a, dyn PartialEq<i32>>>;
437
438 let mut array = [1, 2, 3, 4, 5, 6, 7, 8, 9];
439 let len = array.len();
440 let mut slice = partial_eq::new_mut(&mut array);
441 let metadata = slice.metadata().unwrap();
442 assert_eq!(slice.len(), len);
443
444 let full_slices: [GetSliceFn; 6] = [
446 |slice| slice.slice_mut(..).unwrap(),
447 |slice| slice.slice_mut(0..).unwrap(),
448 |slice| slice.slice_mut(..(slice.len())).unwrap(),
449 #[allow(clippy::range_minus_one)]
450 |slice| slice.slice_mut(..=(slice.len() - 1)).unwrap(),
451 |slice| slice.slice_mut(0..slice.len()).unwrap(),
452 #[allow(clippy::range_minus_one)]
453 |slice| slice.slice_mut(0..=(slice.len() - 1)).unwrap(),
454 ];
455
456 for get_sub_slice in full_slices {
457 let sub_slice = get_sub_slice(&mut slice);
458
459 assert_eq!(sub_slice.metadata(), Some(metadata));
460 assert_eq!(sub_slice.len(), len);
461 assert_eq!(sub_slice.as_ptr(), slice.as_ptr());
462 }
463
464 let sub_slice = slice.slice_mut(2..).unwrap();
466 assert_eq!(sub_slice.metadata(), Some(metadata));
467 assert_eq!(sub_slice.len(), len - 2);
468 assert_eq!(sub_slice.as_ptr(), addr_of!(slice[2]).cast());
469
470 let sub_slice = slice.slice_mut(..7).unwrap();
471 assert_eq!(sub_slice.metadata(), Some(metadata));
472 assert_eq!(sub_slice.len(), 7);
473 assert_eq!(sub_slice.as_ptr(), slice.as_ptr());
474
475 let sub_slices: [GetSliceFn; 2] = [
477 |slice| slice.slice_mut(2..slice.len()).unwrap(),
478 #[allow(clippy::range_minus_one)]
479 |slice| slice.slice_mut(2..=(slice.len() - 1)).unwrap(),
480 ];
481
482 for get_sub_slice in sub_slices {
483 let sub_slice = get_sub_slice(&mut slice);
484
485 assert_eq!(sub_slice.metadata(), Some(metadata));
486 assert_eq!(sub_slice.len(), len - 2);
487 assert_eq!(sub_slice.as_ptr(), addr_of!(slice[2]).cast());
488 }
489
490 let zero_length_slices: [GetSliceFn; 4] = [
492 |slice| slice.slice_mut(0..0).unwrap(),
493 |slice| slice.slice_mut(2..2).unwrap(),
494 #[allow(clippy::reversed_empty_ranges)]
495 |slice| slice.slice_mut(2..=1).unwrap(),
496 |slice| slice.slice_mut((slice.len())..).unwrap(),
497 ];
498
499 for get_sub_slice in zero_length_slices {
500 let sub_slice = get_sub_slice(&mut slice);
501
502 assert_eq!(sub_slice.metadata(), Some(metadata));
503 assert_eq!(sub_slice.len(), 0);
504 }
505
506 let invalid_slices: [GetOptSliceFn; 2] = [
508 #[allow(clippy::range_plus_one)]
509 |slice| slice.slice_mut(..(slice.len() + 1)),
510 |slice| slice.slice_mut(..=(slice.len())),
511 ];
512
513 for get_sub_slice in invalid_slices {
514 let sub_slice = get_sub_slice(&mut slice);
515
516 assert!(sub_slice.is_none());
517 }
518 }
519
520 #[test]
521 #[should_panic(expected = "index out of bounds")]
522 fn index_empty() {
523 let slice = partial_eq::new_mut::<u8, u8>(&mut []);
524 _ = &slice[0];
525 }
526
527 #[test]
528 fn index() {
529 let mut array = [1, 2, 3, 4];
530 let slice = partial_eq::new_mut::<u8, u8>(&mut array);
531 assert!(slice[0] == 1);
532 assert!(slice[1] == 2);
533 assert!(slice[2] == 3);
534 assert!(slice[3] == 4);
535 }
536
537 #[test]
538 #[should_panic(expected = "index out of bounds")]
539 fn index_on_bound() {
540 let mut array = [1, 2, 3, 4];
541 let slice = partial_eq::new_mut::<u8, u8>(&mut array);
542 _ = &slice[4];
543 }
544
545 #[test]
546 #[should_panic(expected = "index out of bounds")]
547 fn index_out_of_bounds() {
548 let mut array = [1, 2, 3, 4];
549 let slice = partial_eq::new_mut::<u8, u8>(&mut array);
550 _ = &slice[6];
551 }
552}