1use core::{
61 borrow::Borrow,
62 cmp::Ordering,
63 fmt::{self, Debug, Display},
64 hash::{Hash, Hasher},
65 marker::PhantomData,
66 mem::{self, ManuallyDrop},
67 ops::{Deref, DerefMut},
68 ptr::{slice_from_raw_parts_mut, NonNull},
69 slice,
70 str::{from_utf8_unchecked, from_utf8_unchecked_mut},
71};
72use smallvec::SmallVec;
73use thiserror::Error;
74
75#[derive(Error, Debug)]
84#[error("The length `{len}` was too long")]
85pub struct LenTooLong<T = ()> {
86 pub len: usize,
88 pub too_long: T,
90}
91
92impl<T> LenTooLong<T> {
93 pub fn forget(self) -> LenTooLong {
95 self.map(drop)
96 }
97
98 pub fn map<U>(self, with: impl FnOnce(T) -> U) -> LenTooLong<U> {
100 LenTooLong {
101 len: self.len,
102 too_long: with(self.too_long),
103 }
104 }
105}
106
107#[inline]
109pub fn try_into<A, B: TryFrom<A, Error = LenTooLong<A>>>(x: A) -> Result<B, LenTooLong> {
110 x.try_into().map_err(|e: LenTooLong<A>| e.forget())
111}
112
113macro_rules! ensure_len_fits {
119 ($thing:expr) => {
120 let Ok(_) = u32::try_from($thing.len()) else {
121 return Err(LenTooLong {
122 len: $thing.len(),
123 too_long: $thing,
124 });
125 };
126 };
127}
128
129#[inline]
131fn expect_fit<A, E, B: TryInto<A, Error = LenTooLong<E>>>(x: B) -> A {
132 x.try_into().map_err(|e| e.len).expect("length didn't fit in `u32`")
133}
134
135#[inline]
136fn into_box<T, U: Into<Box<[T]>>>(x: U) -> Box<[T]> {
137 x.into()
138}
139
140struct AssertU32<const N: usize>;
142impl<const N: usize> AssertU32<N> {
143 const OK: () = assert!(N <= u32::MAX as usize);
144}
145
146pub unsafe trait SafelyExchangeable<T> {}
159
160#[repr(Rust, packed)]
164struct SlimRawSlice<T> {
165 ptr: NonNull<T>,
167 len: u32,
169}
170
171impl<T> SlimRawSlice<T> {
172 #[inline]
174 fn dangling() -> Self {
175 let ptr = NonNull::dangling();
176 Self { len: 0, ptr }
177 }
178
179 #[inline]
185 fn cast<U: SafelyExchangeable<T>>(self) -> SlimRawSlice<U> {
186 SlimRawSlice {
187 ptr: self.ptr.cast(),
188 len: self.len,
189 }
190 }
191
192 #[inline]
194 fn split(self) -> (*mut T, usize) {
195 (self.ptr.as_ptr(), self.len as usize)
196 }
197
198 #[allow(clippy::needless_lifetimes)]
218 #[inline]
219 unsafe fn deref<'a>(&'a self) -> &'a [T] {
220 let (ptr, len) = self.split();
221 unsafe { slice::from_raw_parts(ptr, len) }
223 }
224
225 #[allow(clippy::needless_lifetimes)]
246 #[inline]
247 unsafe fn deref_mut<'a>(&'a mut self) -> &'a mut [T] {
248 let (ptr, len) = self.split();
249 unsafe { slice::from_raw_parts_mut(ptr, len) }
251 }
252
253 #[inline]
258 const unsafe fn from_len_ptr(len: usize, ptr: *mut T) -> Self {
259 unsafe {
260 let ptr = NonNull::new_unchecked(ptr);
262 let len = len as u32;
263 Self { ptr, len }
264 }
265 }
266}
267
268impl<T> Copy for SlimRawSlice<T> {}
269impl<T> Clone for SlimRawSlice<T> {
270 #[inline]
271 fn clone(&self) -> Self {
272 *self
273 }
274}
275
276pub use slim_slice_box::*;
281mod slim_slice_box {
282 use super::*;
286
287 #[repr(transparent)]
290 pub struct SlimSliceBox<T> {
291 raw: SlimRawSlice<T>,
295 owned: PhantomData<T>,
297 }
298
299 impl<T> Drop for SlimSliceBox<T> {
300 #[inline]
301 fn drop(&mut self) {
302 let raw = SlimRawSlice::dangling();
306 let owned = PhantomData;
307 let this = mem::replace(self, Self { raw, owned });
308
309 drop(into_box(this));
311 }
312 }
313
314 impl<T> SlimSliceBox<T> {
315 #[allow(clippy::boxed_local)]
321 #[inline]
322 pub unsafe fn from_boxed_unchecked(boxed: Box<[T]>) -> Self {
324 unsafe {
325 let len = boxed.len();
326 let ptr = Box::into_raw(boxed) as *mut T;
327 let raw = SlimRawSlice::from_len_ptr(len, ptr);
330 let owned = PhantomData;
331 Self { raw, owned }
332 }
333 }
334
335 #[allow(clippy::needless_lifetimes)]
337 #[inline]
338 pub fn shared_ref<'a>(&'a self) -> &'a SlimSlice<'a, T> {
339 unsafe { mem::transmute(self) }
342 }
343
344 #[allow(clippy::needless_lifetimes)]
346 #[inline]
347 pub fn exclusive_ref<'a>(&'a mut self) -> &'a mut SlimSliceMut<'a, T> {
348 unsafe { mem::transmute(self) }
352 }
353
354 #[inline]
358 pub fn map_safely_exchangeable<U: SafelyExchangeable<T>>(self) -> SlimSliceBox<U> {
359 SlimSliceBox {
363 raw: self.raw.cast(),
364 owned: PhantomData,
365 }
366 }
367 }
368
369 impl<T> From<SlimSliceBox<T>> for Box<[T]> {
370 #[inline]
371 fn from(slice: SlimSliceBox<T>) -> Self {
372 let slice = ManuallyDrop::new(slice);
373 let (ptr, len) = slice.raw.split();
374 unsafe { Box::from_raw(slice_from_raw_parts_mut(ptr, len)) }
387 }
388 }
389}
390
391unsafe impl<T: Send> Send for SlimSliceBox<T> {}
393
394unsafe impl<T: Sync> Sync for SlimSliceBox<T> {}
396
397impl<T> Deref for SlimSliceBox<T> {
398 type Target = [T];
399
400 #[inline]
401 fn deref(&self) -> &Self::Target {
402 self.shared_ref().deref()
403 }
404}
405
406impl<T> DerefMut for SlimSliceBox<T> {
407 #[inline]
408 fn deref_mut(&mut self) -> &mut Self::Target {
409 self.exclusive_ref().deref_mut()
410 }
411}
412
413impl<T> SlimSliceBox<T> {
414 #[inline]
418 pub fn from_boxed(boxed: Box<[T]>) -> Self {
419 expect_fit(boxed)
420 }
421
422 #[inline]
426 pub fn from_vec(vec: Vec<T>) -> Self {
427 Self::from_boxed(vec.into())
428 }
429
430 #[inline]
434 pub fn map<U>(self, by: impl FnMut(T) -> U) -> SlimSliceBox<U> {
435 let mapped = self.into_iter().map(by).collect::<Box<_>>();
436 unsafe { SlimSliceBox::from_boxed_unchecked(mapped) }
438 }
439
440 #[inline]
444 pub fn map_borrowed<U>(&self, by: impl FnMut(&T) -> U) -> SlimSliceBox<U> {
445 let mapped = self.iter().map(by).collect::<Box<_>>();
446 unsafe { SlimSliceBox::from_boxed_unchecked(mapped) }
448 }
449}
450
451impl<T> TryFrom<Box<[T]>> for SlimSliceBox<T> {
452 type Error = LenTooLong<Box<[T]>>;
453
454 #[inline]
455 fn try_from(boxed: Box<[T]>) -> Result<Self, Self::Error> {
456 ensure_len_fits!(boxed);
457 Ok(unsafe { Self::from_boxed_unchecked(boxed) })
459 }
460}
461
462impl<T> TryFrom<Vec<T>> for SlimSliceBox<T> {
463 type Error = LenTooLong<Vec<T>>;
464
465 #[inline]
466 fn try_from(vec: Vec<T>) -> Result<Self, Self::Error> {
467 ensure_len_fits!(vec);
468 Ok(unsafe { Self::from_boxed_unchecked(vec.into_boxed_slice()) })
470 }
471}
472
473impl<T, const N: usize> From<[T; N]> for SlimSliceBox<T> {
474 #[inline]
475 fn from(arr: [T; N]) -> Self {
476 #[allow(clippy::let_unit_value)]
477 let () = AssertU32::<N>::OK;
478
479 unsafe { Self::from_boxed_unchecked(into_box(arr)) }
481 }
482}
483
484impl<T> From<SlimSliceBox<T>> for Vec<T> {
485 #[inline]
486 fn from(slice: SlimSliceBox<T>) -> Self {
487 into_box(slice).into()
488 }
489}
490
491impl<T: Debug> Debug for SlimSliceBox<T> {
492 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
493 Debug::fmt(self.deref(), f)
494 }
495}
496
497impl<T: Clone> Clone for SlimSliceBox<T> {
498 #[inline]
499 fn clone(&self) -> Self {
500 let mut vec = Vec::with_capacity(self.len());
503 vec.extend_from_slice(self);
504 unsafe { Self::from_boxed_unchecked(into_box(vec)) }
506 }
507}
508
509impl<R: Deref, T> PartialEq<R> for SlimSliceBox<T>
510where
511 [T]: PartialEq<R::Target>,
512{
513 #[inline]
514 fn eq(&self, other: &R) -> bool {
515 **self == **other
516 }
517}
518
519impl<T: Eq> Eq for SlimSliceBox<T> {}
520
521impl<R: Deref, T> PartialOrd<R> for SlimSliceBox<T>
522where
523 [T]: PartialOrd<R::Target>,
524{
525 #[inline]
526 fn partial_cmp(&self, other: &R) -> Option<Ordering> {
527 (**self).partial_cmp(&**other)
528 }
529}
530
531impl<T: Ord> Ord for SlimSliceBox<T> {
532 #[inline]
533 fn cmp(&self, other: &Self) -> Ordering {
534 (**self).cmp(&**other)
535 }
536}
537
538impl<T: Hash> Hash for SlimSliceBox<T> {
539 #[inline]
540 fn hash<H: Hasher>(&self, state: &mut H) {
541 Hash::hash(&**self, state)
542 }
543}
544
545impl<T> IntoIterator for SlimSliceBox<T> {
546 type Item = T;
547 type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
548 #[inline]
549 fn into_iter(self) -> Self::IntoIter {
550 Vec::from(self).into_iter()
551 }
552}
553
554pub struct SlimSliceBoxCollected<T> {
558 pub inner: Result<SlimSliceBox<T>, LenTooLong<Vec<T>>>,
560}
561
562impl<T: Debug> SlimSliceBoxCollected<T> {
563 #[inline]
564 pub fn unwrap(self) -> SlimSliceBox<T> {
565 self.inner.expect("number of elements overflowed `u32::MAX`")
566 }
567}
568
569impl<A> FromIterator<A> for SlimSliceBoxCollected<A> {
570 #[inline]
571 fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
572 let inner = iter.into_iter().collect::<Vec<_>>().try_into();
573 SlimSliceBoxCollected { inner }
574 }
575}
576
577#[derive(Clone)]
582pub struct SlimSmallSliceBox<T, const N: usize>(SlimSmallSliceBoxData<T, N>);
583
584#[derive(Clone)]
588enum SlimSmallSliceBoxData<T, const N: usize> {
589 Inline([T; N]),
591 Heap(SlimSliceBox<T>),
593}
594
595impl<T, const N: usize> From<[T; N]> for SlimSmallSliceBox<T, N> {
596 fn from(value: [T; N]) -> Self {
597 #[allow(clippy::let_unit_value)]
598 let () = AssertU32::<N>::OK;
599
600 Self(SlimSmallSliceBoxData::Inline(value))
601 }
602}
603
604impl<T, const N: usize> From<SlimSliceBox<T>> for SlimSmallSliceBox<T, N> {
605 fn from(value: SlimSliceBox<T>) -> Self {
606 Self(SlimSmallSliceBoxData::Heap(value))
607 }
608}
609
610impl<T, const N: usize> From<SlimSmallSliceBox<T, N>> for SlimSliceBox<T> {
611 fn from(SlimSmallSliceBox(value): SlimSmallSliceBox<T, N>) -> Self {
612 match value {
613 SlimSmallSliceBoxData::Inline(i) => i.into(),
614 SlimSmallSliceBoxData::Heap(h) => h,
615 }
616 }
617}
618
619impl<T, const N: usize> Deref for SlimSmallSliceBox<T, N> {
620 type Target = [T];
621 fn deref(&self) -> &Self::Target {
622 match &self.0 {
623 SlimSmallSliceBoxData::Inline(i) => i,
624 SlimSmallSliceBoxData::Heap(h) => h,
625 }
626 }
627}
628
629impl<T, const N: usize> DerefMut for SlimSmallSliceBox<T, N> {
630 fn deref_mut(&mut self) -> &mut Self::Target {
631 match &mut self.0 {
632 SlimSmallSliceBoxData::Inline(i) => i,
633 SlimSmallSliceBoxData::Heap(h) => h,
634 }
635 }
636}
637
638impl<T: PartialEq, const N: usize> PartialEq for SlimSmallSliceBox<T, N> {
639 fn eq(&self, other: &Self) -> bool {
640 self.deref().eq(other.deref())
641 }
642}
643
644impl<T: Eq, const N: usize> Eq for SlimSmallSliceBox<T, N> {}
645
646impl<T: Debug, const N: usize> fmt::Debug for SlimSmallSliceBox<T, N> {
647 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
648 Debug::fmt(self.deref(), f)
649 }
650}
651
652impl<T, const N: usize> From<SmallVec<[T; N]>> for SlimSmallSliceBox<T, N> {
653 fn from(value: SmallVec<[T; N]>) -> Self {
654 match value.into_inner() {
655 Ok(inline) => inline.into(),
656 Err(heap) => SlimSliceBox::from_boxed(heap.into_boxed_slice()).into(),
657 }
658 }
659}
660
661#[repr(transparent)]
668pub struct SlimStrBox {
669 raw: SlimSliceBox<u8>,
671}
672
673#[cfg(feature = "serde")]
674impl serde::Serialize for SlimStrBox {
675 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
676 s.serialize_str(self.deref())
677 }
678}
679
680impl SlimStrBox {
681 #[inline]
687 pub unsafe fn from_boxed_unchecked(boxed: Box<str>) -> Self {
688 let raw = unsafe { SlimSliceBox::from_boxed_unchecked(into_box(boxed)) };
690 Self { raw }
691 }
692
693 #[inline]
697 pub fn from_boxed(boxed: Box<str>) -> Self {
698 expect_fit(boxed)
699 }
700
701 #[inline]
705 pub fn from_string(str: String) -> Self {
706 Self::from_boxed(str.into())
707 }
708
709 #[allow(clippy::needless_lifetimes)]
711 #[inline]
712 pub fn shared_ref<'a>(&'a self) -> &'a SlimStr<'a> {
713 unsafe { mem::transmute(self.raw.shared_ref()) }
717 }
718
719 #[allow(clippy::needless_lifetimes)]
721 #[inline]
722 pub fn exclusive_ref<'a>(&'a mut self) -> &'a mut SlimStrMut<'a> {
723 unsafe { mem::transmute(self.raw.exclusive_ref()) }
727 }
728}
729
730impl Deref for SlimStrBox {
731 type Target = str;
732
733 #[inline]
734 fn deref(&self) -> &Self::Target {
735 self.shared_ref().deref()
736 }
737}
738
739impl DerefMut for SlimStrBox {
740 #[inline]
741 fn deref_mut(&mut self) -> &mut Self::Target {
742 self.exclusive_ref().deref_mut()
743 }
744}
745
746impl<const N: usize> From<NStr<N>> for SlimStrBox {
747 #[inline]
748 fn from(arr: NStr<N>) -> Self {
749 (&arr).into()
750 }
751}
752
753impl<const N: usize> From<&NStr<N>> for SlimStrBox {
754 #[inline]
755 fn from(arr: &NStr<N>) -> Self {
756 <SlimStr<'_>>::from(arr).into()
757 }
758}
759
760impl TryFrom<Box<str>> for SlimStrBox {
761 type Error = LenTooLong<Box<str>>;
762
763 #[inline]
764 fn try_from(boxed: Box<str>) -> Result<Self, Self::Error> {
765 ensure_len_fits!(boxed);
766 Ok(unsafe { Self::from_boxed_unchecked(boxed) })
768 }
769}
770
771impl TryFrom<String> for SlimStrBox {
772 type Error = LenTooLong<String>;
773
774 #[inline]
775 fn try_from(str: String) -> Result<Self, Self::Error> {
776 ensure_len_fits!(str);
777 Ok(unsafe { Self::from_boxed_unchecked(str.into_boxed_str()) })
779 }
780}
781
782impl<'a> TryFrom<&'a str> for SlimStrBox {
783 type Error = LenTooLong<&'a str>;
784
785 #[inline]
786 fn try_from(str: &'a str) -> Result<Self, Self::Error> {
787 str.try_into().map(|s: SlimStr<'_>| s.into())
788 }
789}
790
791impl From<SlimStrBox> for Box<str> {
792 #[inline]
793 fn from(str: SlimStrBox) -> Self {
794 let raw_box = into_box(str.raw);
795 unsafe { Box::from_raw(Box::into_raw(raw_box) as *mut str) }
797 }
798}
799
800impl From<SlimStrBox> for String {
801 #[inline]
802 fn from(str: SlimStrBox) -> Self {
803 <Box<str>>::from(str).into()
804 }
805}
806
807impl Debug for SlimStrBox {
808 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
809 Debug::fmt(self.deref(), f)
810 }
811}
812
813impl Display for SlimStrBox {
814 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
815 Display::fmt(self.deref(), f)
816 }
817}
818
819impl Clone for SlimStrBox {
820 #[inline]
821 fn clone(&self) -> Self {
822 Self { raw: self.raw.clone() }
823 }
824}
825
826impl<R: Deref> PartialEq<R> for SlimStrBox
827where
828 str: PartialEq<R::Target>,
829{
830 #[inline]
831 fn eq(&self, other: &R) -> bool {
832 self.deref() == other.deref()
833 }
834}
835
836impl Eq for SlimStrBox {}
837
838impl<R: Deref> PartialOrd<R> for SlimStrBox
839where
840 str: PartialOrd<R::Target>,
841{
842 #[inline]
843 fn partial_cmp(&self, other: &R) -> Option<Ordering> {
844 self.deref().partial_cmp(other.deref())
845 }
846}
847
848impl Ord for SlimStrBox {
849 #[inline]
850 fn cmp(&self, other: &Self) -> Ordering {
851 self.deref().cmp(other.deref())
852 }
853}
854
855impl Hash for SlimStrBox {
856 #[inline]
857 fn hash<H: Hasher>(&self, state: &mut H) {
858 Hash::hash(self.deref(), state)
859 }
860}
861
862impl Borrow<str> for SlimStrBox {
863 #[inline]
864 fn borrow(&self) -> &str {
865 self
866 }
867}
868
869#[allow(clippy::module_inception)]
874mod slim_slice {
875 use super::*;
876
877 #[repr(transparent)]
879 #[derive(Clone, Copy)]
880 pub struct SlimSlice<'a, T> {
881 raw: SlimRawSlice<T>,
883 covariant: PhantomData<&'a [T]>,
885 }
886
887 impl<'a, T> SlimSlice<'a, T> {
888 pub(super) const unsafe fn from_slice_unchecked(slice: &'a [T]) -> Self {
892 unsafe {
893 let len = slice.len();
894 let ptr = slice.as_ptr().cast_mut();
895 let raw = SlimRawSlice::from_len_ptr(len, ptr);
897 let covariant = PhantomData;
899 Self { raw, covariant }
900 }
901 }
902 }
903
904 impl<T> Deref for SlimSlice<'_, T> {
905 type Target = [T];
906
907 fn deref(&self) -> &Self::Target {
908 unsafe { self.raw.deref() }
913 }
914 }
915}
916pub use slim_slice::*;
917
918use crate::nstr::NStr;
919
920unsafe impl<T: Send + Sync> Send for SlimSlice<'_, T> {}
922
923unsafe impl<T: Sync> Sync for SlimSlice<'_, T> {}
925
926impl<T> SlimSlice<'_, T> {
927 #[inline]
931 pub fn try_map<U, E>(&self, by: impl FnMut(&T) -> Result<U, E>) -> Result<SlimSliceBox<U>, E> {
932 let mapped = self.iter().map(by).collect::<Result<_, _>>()?;
933 Ok(unsafe { SlimSliceBox::from_boxed_unchecked(mapped) })
935 }
936}
937
938impl<T: Debug> Debug for SlimSlice<'_, T> {
939 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
940 Debug::fmt(self.deref(), f)
941 }
942}
943
944impl<T: Hash> Hash for SlimSlice<'_, T> {
945 #[inline]
946 fn hash<H: Hasher>(&self, state: &mut H) {
947 Hash::hash(self.deref(), state)
948 }
949}
950
951impl<T: Eq> Eq for SlimSlice<'_, T> {}
952impl<T: PartialEq> PartialEq for SlimSlice<'_, T> {
953 #[inline]
954 fn eq(&self, other: &Self) -> bool {
955 self.deref() == other.deref()
956 }
957}
958impl<T: PartialEq> PartialEq<[T]> for SlimSlice<'_, T> {
959 #[inline]
960 fn eq(&self, other: &[T]) -> bool {
961 self.deref() == other
962 }
963}
964
965impl<T: Ord> Ord for SlimSlice<'_, T> {
966 #[inline]
967 fn cmp(&self, other: &Self) -> Ordering {
968 self.deref().cmp(other)
969 }
970}
971impl<T: PartialOrd> PartialOrd for SlimSlice<'_, T> {
972 #[inline]
973 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
974 self.deref().partial_cmp(other.deref())
975 }
976}
977impl<T: PartialOrd> PartialOrd<[T]> for SlimSlice<'_, T> {
978 #[inline]
979 fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
980 self.deref().partial_cmp(other)
981 }
982}
983
984impl<T: Clone> From<&SlimSlice<'_, T>> for SlimSliceBox<T> {
985 #[inline]
986 fn from(slice: &SlimSlice<'_, T>) -> Self {
987 let boxed = into_box(slice.deref());
988 unsafe { Self::from_boxed_unchecked(boxed) }
990 }
991}
992impl<T: Clone> From<&SlimSlice<'_, T>> for Box<[T]> {
993 #[inline]
994 fn from(slice: &SlimSlice<'_, T>) -> Self {
995 slice.deref().into()
996 }
997}
998impl<T: Clone> From<&SlimSlice<'_, T>> for Vec<T> {
999 #[inline]
1000 fn from(slice: &SlimSlice<'_, T>) -> Self {
1001 slice.deref().into()
1002 }
1003}
1004
1005impl<T: Clone> From<SlimSlice<'_, T>> for SlimSliceBox<T> {
1006 #[inline]
1007 fn from(slice: SlimSlice<'_, T>) -> Self {
1008 (&slice).into()
1009 }
1010}
1011impl<T: Clone> From<SlimSlice<'_, T>> for Box<[T]> {
1012 #[inline]
1013 fn from(slice: SlimSlice<'_, T>) -> Self {
1014 slice.deref().into()
1015 }
1016}
1017impl<T: Clone> From<SlimSlice<'_, T>> for Vec<T> {
1018 #[inline]
1019 fn from(slice: SlimSlice<'_, T>) -> Self {
1020 slice.deref().into()
1021 }
1022}
1023
1024impl<'a, T> TryFrom<&'a [T]> for SlimSlice<'a, T> {
1025 type Error = LenTooLong<&'a [T]>;
1026
1027 #[inline]
1028 fn try_from(slice: &'a [T]) -> Result<Self, Self::Error> {
1029 ensure_len_fits!(slice);
1030 Ok(unsafe { Self::from_slice_unchecked(slice) })
1032 }
1033}
1034
1035#[inline]
1039pub fn from_slice<T>(s: &[T]) -> SlimSlice<'_, T> {
1040 expect_fit(s)
1041}
1042
1043#[repr(transparent)]
1049pub struct SlimSliceMut<'a, T> {
1050 raw: SlimRawSlice<T>,
1052 invariant: PhantomData<&'a mut [T]>,
1054}
1055
1056unsafe impl<T: Send> Send for SlimSliceMut<'_, T> {}
1058
1059unsafe impl<T: Sync> Sync for SlimSliceMut<'_, T> {}
1061
1062impl<'a, T> SlimSliceMut<'a, T> {
1063 #[inline]
1065 pub fn shared(&'a self) -> &'a SlimSlice<'a, T> {
1066 unsafe { mem::transmute(self) }
1069 }
1070
1071 #[inline]
1075 unsafe fn from_slice_unchecked(slice: &'a mut [T]) -> Self {
1076 unsafe {
1077 let raw = SlimRawSlice::from_len_ptr(slice.len(), slice.as_mut_ptr());
1079 let invariant = PhantomData;
1082 Self { raw, invariant }
1083 }
1084 }
1085}
1086
1087impl<T> Deref for SlimSliceMut<'_, T> {
1088 type Target = [T];
1089
1090 #[inline]
1091 fn deref(&self) -> &Self::Target {
1092 self.shared().deref()
1093 }
1094}
1095
1096impl<T> DerefMut for SlimSliceMut<'_, T> {
1097 #[inline]
1098 fn deref_mut(&mut self) -> &mut Self::Target {
1099 unsafe { self.raw.deref_mut() }
1105 }
1106}
1107
1108impl<T: Debug> Debug for SlimSliceMut<'_, T> {
1109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1110 Debug::fmt(self.deref(), f)
1111 }
1112}
1113
1114impl<T: Hash> Hash for SlimSliceMut<'_, T> {
1115 #[inline]
1116 fn hash<H: Hasher>(&self, state: &mut H) {
1117 Hash::hash(self.deref(), state)
1118 }
1119}
1120
1121impl<T: Eq> Eq for SlimSliceMut<'_, T> {}
1122impl<T: PartialEq> PartialEq for SlimSliceMut<'_, T> {
1123 #[inline]
1124 fn eq(&self, other: &Self) -> bool {
1125 self.deref() == other.deref()
1126 }
1127}
1128impl<T: PartialEq> PartialEq<[T]> for SlimSliceMut<'_, T> {
1129 #[inline]
1130 fn eq(&self, other: &[T]) -> bool {
1131 self.deref() == other
1132 }
1133}
1134
1135impl<T: Ord> Ord for SlimSliceMut<'_, T> {
1136 #[inline]
1137 fn cmp(&self, other: &Self) -> Ordering {
1138 self.deref().cmp(other)
1139 }
1140}
1141impl<T: PartialOrd> PartialOrd for SlimSliceMut<'_, T> {
1142 #[inline]
1143 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1144 self.deref().partial_cmp(other.deref())
1145 }
1146}
1147impl<T: PartialOrd> PartialOrd<[T]> for SlimSliceMut<'_, T> {
1148 #[inline]
1149 fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
1150 self.deref().partial_cmp(other)
1151 }
1152}
1153
1154impl<T: Clone> From<&SlimSliceMut<'_, T>> for SlimSliceBox<T> {
1155 #[inline]
1156 fn from(slice: &SlimSliceMut<'_, T>) -> Self {
1157 unsafe { Self::from_boxed_unchecked(into_box(slice.deref())) }
1159 }
1160}
1161impl<T: Clone> From<&SlimSliceMut<'_, T>> for Box<[T]> {
1162 #[inline]
1163 fn from(slice: &SlimSliceMut<'_, T>) -> Self {
1164 slice.deref().into()
1165 }
1166}
1167impl<T: Clone> From<&SlimSliceMut<'_, T>> for Vec<T> {
1168 #[inline]
1169 fn from(slice: &SlimSliceMut<'_, T>) -> Self {
1170 slice.deref().into()
1171 }
1172}
1173
1174impl<T: Clone> From<SlimSliceMut<'_, T>> for SlimSliceBox<T> {
1175 #[inline]
1176 fn from(slice: SlimSliceMut<'_, T>) -> Self {
1177 (&slice).into()
1178 }
1179}
1180impl<T: Clone> From<SlimSliceMut<'_, T>> for Box<[T]> {
1181 #[inline]
1182 fn from(slice: SlimSliceMut<'_, T>) -> Self {
1183 slice.deref().into()
1184 }
1185}
1186impl<T: Clone> From<SlimSliceMut<'_, T>> for Vec<T> {
1187 #[inline]
1188 fn from(slice: SlimSliceMut<'_, T>) -> Self {
1189 slice.deref().into()
1190 }
1191}
1192
1193impl<'a, T> TryFrom<&'a mut [T]> for SlimSliceMut<'a, T> {
1194 type Error = LenTooLong<&'a mut [T]>;
1195
1196 #[inline]
1197 fn try_from(slice: &'a mut [T]) -> Result<Self, Self::Error> {
1198 ensure_len_fits!(slice);
1199 Ok(unsafe { Self::from_slice_unchecked(slice) })
1201 }
1202}
1203
1204#[inline]
1208pub fn from_slice_mut<T>(s: &mut [T]) -> SlimSliceMut<'_, T> {
1209 expect_fit(s)
1210}
1211
1212#[repr(transparent)]
1218#[derive(Clone, Copy)]
1219pub struct SlimStr<'a> {
1220 raw: SlimSlice<'a, u8>,
1222}
1223
1224impl<'a> SlimStr<'a> {
1225 #[inline]
1231 const unsafe fn from_str_unchecked(s: &'a str) -> Self {
1232 let raw = unsafe { SlimSlice::from_slice_unchecked(s.as_bytes()) };
1234 Self { raw }
1236 }
1237}
1238
1239impl Deref for SlimStr<'_> {
1240 type Target = str;
1241
1242 #[inline]
1243 fn deref(&self) -> &Self::Target {
1244 unsafe { from_utf8_unchecked(self.raw.deref()) }
1246 }
1247}
1248
1249impl Debug for SlimStr<'_> {
1250 #[inline]
1251 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1252 Debug::fmt(self.deref(), f)
1253 }
1254}
1255
1256impl Display for SlimStr<'_> {
1257 #[inline]
1258 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1259 Display::fmt(self.deref(), f)
1260 }
1261}
1262
1263impl Hash for SlimStr<'_> {
1264 #[inline]
1265 fn hash<H: Hasher>(&self, state: &mut H) {
1266 Hash::hash(self.deref(), state)
1267 }
1268}
1269
1270impl Eq for SlimStr<'_> {}
1271impl PartialEq for SlimStr<'_> {
1272 #[inline]
1273 fn eq(&self, other: &Self) -> bool {
1274 self.deref() == other.deref()
1275 }
1276}
1277impl PartialEq<str> for SlimStr<'_> {
1278 #[inline]
1279 fn eq(&self, other: &str) -> bool {
1280 self.deref() == other
1281 }
1282}
1283
1284impl Ord for SlimStr<'_> {
1285 #[inline]
1286 fn cmp(&self, other: &Self) -> Ordering {
1287 self.deref().cmp(other)
1288 }
1289}
1290impl PartialOrd for SlimStr<'_> {
1291 #[inline]
1292 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1293 Some(self.cmp(other))
1294 }
1295}
1296impl PartialOrd<str> for SlimStr<'_> {
1297 #[inline]
1298 fn partial_cmp(&self, other: &str) -> Option<Ordering> {
1299 self.deref().partial_cmp(other)
1300 }
1301}
1302
1303impl From<&SlimStr<'_>> for SlimStrBox {
1304 #[inline]
1305 fn from(slice: &SlimStr<'_>) -> Self {
1306 (*slice).into()
1307 }
1308}
1309impl From<&SlimStr<'_>> for Box<str> {
1310 #[inline]
1311 fn from(slice: &SlimStr<'_>) -> Self {
1312 slice.deref().into()
1313 }
1314}
1315impl From<&SlimStr<'_>> for String {
1316 #[inline]
1317 fn from(slice: &SlimStr<'_>) -> Self {
1318 slice.deref().into()
1319 }
1320}
1321
1322impl From<SlimStr<'_>> for SlimStrBox {
1323 #[inline]
1324 fn from(slice: SlimStr<'_>) -> Self {
1325 Self { raw: slice.raw.into() }
1327 }
1328}
1329impl From<SlimStr<'_>> for Box<str> {
1330 #[inline]
1331 fn from(slice: SlimStr<'_>) -> Self {
1332 slice.deref().into()
1333 }
1334}
1335impl From<SlimStr<'_>> for String {
1336 #[inline]
1337 fn from(slice: SlimStr<'_>) -> Self {
1338 slice.deref().into()
1339 }
1340}
1341
1342impl<'a, const N: usize> From<&'a NStr<N>> for SlimStr<'a> {
1343 #[inline]
1344 fn from(arr: &'a NStr<N>) -> Self {
1345 #[allow(clippy::let_unit_value)]
1346 let () = AssertU32::<N>::OK;
1347
1348 unsafe { Self::from_str_unchecked(arr) }
1350 }
1351}
1352impl<'a> TryFrom<&'a str> for SlimStr<'a> {
1353 type Error = LenTooLong<&'a str>;
1354
1355 #[inline]
1356 fn try_from(s: &'a str) -> Result<Self, Self::Error> {
1357 ensure_len_fits!(s);
1358 Ok(unsafe { Self::from_str_unchecked(s) })
1360 }
1361}
1362
1363#[inline]
1367pub const fn from_str(s: &str) -> SlimStr<'_> {
1368 if s.len() > u32::MAX as usize {
1369 panic!("length didn't fit in `u32`");
1370 }
1371
1372 unsafe { SlimStr::from_str_unchecked(s) }
1374}
1375
1376#[inline]
1380pub fn from_string(s: &str) -> SlimStrBox {
1381 from_str(s).into()
1382}
1383
1384#[repr(transparent)]
1390pub struct SlimStrMut<'a> {
1391 raw: SlimSliceMut<'a, u8>,
1393}
1394
1395impl<'a> SlimStrMut<'a> {
1396 #[inline]
1402 unsafe fn from_str_unchecked(s: &'a mut str) -> Self {
1403 let raw = unsafe { SlimSliceMut::from_slice_unchecked(s.as_bytes_mut()) };
1405 Self { raw }
1407 }
1408}
1409
1410impl Deref for SlimStrMut<'_> {
1411 type Target = str;
1412
1413 #[inline]
1414 fn deref(&self) -> &Self::Target {
1415 unsafe { from_utf8_unchecked(self.raw.deref()) }
1417 }
1418}
1419
1420impl DerefMut for SlimStrMut<'_> {
1421 #[inline]
1422 fn deref_mut(&mut self) -> &mut Self::Target {
1423 unsafe { from_utf8_unchecked_mut(self.raw.deref_mut()) }
1425 }
1426}
1427
1428impl Debug for SlimStrMut<'_> {
1429 #[inline]
1430 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1431 Debug::fmt(self.deref(), f)
1432 }
1433}
1434
1435impl Display for SlimStrMut<'_> {
1436 #[inline]
1437 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1438 Display::fmt(self.deref(), f)
1439 }
1440}
1441
1442impl Hash for SlimStrMut<'_> {
1443 #[inline]
1444 fn hash<H: Hasher>(&self, state: &mut H) {
1445 Hash::hash(self.deref(), state)
1446 }
1447}
1448
1449impl Eq for SlimStrMut<'_> {}
1450impl PartialEq for SlimStrMut<'_> {
1451 #[inline]
1452 fn eq(&self, other: &Self) -> bool {
1453 self.deref() == other.deref()
1454 }
1455}
1456impl PartialEq<str> for SlimStrMut<'_> {
1457 #[inline]
1458 fn eq(&self, other: &str) -> bool {
1459 self.deref() == other
1460 }
1461}
1462
1463impl Ord for SlimStrMut<'_> {
1464 #[inline]
1465 fn cmp(&self, other: &Self) -> Ordering {
1466 self.deref().cmp(other)
1467 }
1468}
1469impl PartialOrd for SlimStrMut<'_> {
1470 #[inline]
1471 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1472 Some(self.cmp(other))
1473 }
1474}
1475impl PartialOrd<str> for SlimStrMut<'_> {
1476 #[inline]
1477 fn partial_cmp(&self, other: &str) -> Option<Ordering> {
1478 self.deref().partial_cmp(other)
1479 }
1480}
1481
1482impl From<&SlimStrMut<'_>> for SlimStrBox {
1483 #[inline]
1484 fn from(slice: &SlimStrMut<'_>) -> Self {
1485 Self {
1487 raw: (&slice.raw).into(),
1488 }
1489 }
1490}
1491impl From<&SlimStrMut<'_>> for Box<str> {
1492 #[inline]
1493 fn from(slice: &SlimStrMut<'_>) -> Self {
1494 slice.deref().into()
1495 }
1496}
1497impl From<&SlimStrMut<'_>> for String {
1498 #[inline]
1499 fn from(slice: &SlimStrMut<'_>) -> Self {
1500 slice.deref().into()
1501 }
1502}
1503
1504impl From<SlimStrMut<'_>> for SlimStrBox {
1505 #[inline]
1506 fn from(slice: SlimStrMut<'_>) -> Self {
1507 (&slice).into()
1508 }
1509}
1510impl From<SlimStrMut<'_>> for Box<str> {
1511 #[inline]
1512 fn from(slice: SlimStrMut<'_>) -> Self {
1513 slice.deref().into()
1514 }
1515}
1516impl From<SlimStrMut<'_>> for String {
1517 #[inline]
1518 fn from(slice: SlimStrMut<'_>) -> Self {
1519 slice.deref().into()
1520 }
1521}
1522
1523impl<'a, const N: usize> From<&'a mut NStr<N>> for SlimStrMut<'a> {
1524 #[inline]
1525 fn from(arr: &'a mut NStr<N>) -> Self {
1526 #[allow(clippy::let_unit_value)]
1527 let () = AssertU32::<N>::OK;
1528
1529 unsafe { Self::from_str_unchecked(arr) }
1531 }
1532}
1533impl<'a> TryFrom<&'a mut str> for SlimStrMut<'a> {
1534 type Error = LenTooLong<&'a mut str>;
1535
1536 #[inline]
1537 fn try_from(slice: &'a mut str) -> Result<Self, Self::Error> {
1538 ensure_len_fits!(slice);
1539 Ok(unsafe { Self::from_str_unchecked(slice) })
1541 }
1542}
1543
1544#[inline]
1548pub fn from_str_mut(s: &mut str) -> SlimStrMut<'_> {
1549 expect_fit(s)
1550}
1551
1552#[cfg(test)]
1553mod tests {
1554 use std::hash::BuildHasher;
1555
1556 use super::*;
1557 use crate::map::DefaultHashBuilder;
1558 use crate::nstr;
1559
1560 fn hash_of<T: Hash>(x: T) -> u64 {
1561 DefaultHashBuilder::default().hash_one(&x)
1562 }
1563
1564 fn hash_properties<T>(a: &T, b: &T, a_deref: &T::Target, b_deref: &T::Target)
1565 where
1566 T: Hash + Debug + Deref,
1567 <T as Deref>::Target: Hash,
1568 {
1569 assert_eq!(hash_of(a), hash_of(a_deref));
1570 assert_eq!(hash_of(b), hash_of(b_deref));
1571 assert_ne!(hash_of(a), hash_of(b));
1572 }
1573
1574 fn ord_properties<T>(a: &T, b: &T, a_deref: &T::Target, b_deref: &T::Target)
1575 where
1576 T: Ord + Debug + Deref + PartialOrd<<T as Deref>::Target>,
1577 {
1578 assert_eq!(a.partial_cmp(b), Some(Ordering::Less));
1579 assert_eq!(b.partial_cmp(a), Some(Ordering::Greater));
1580 assert_eq!(a.partial_cmp(a), Some(Ordering::Equal));
1581 assert_eq!(b.partial_cmp(b), Some(Ordering::Equal));
1582 assert_eq!(a.partial_cmp(b_deref), Some(Ordering::Less));
1583 assert_eq!(b.partial_cmp(a_deref), Some(Ordering::Greater));
1584 assert_eq!(a.partial_cmp(a_deref), Some(Ordering::Equal));
1585 assert_eq!(b.partial_cmp(b_deref), Some(Ordering::Equal));
1586
1587 assert_eq!(a.cmp(b), Ordering::Less);
1588 assert_eq!(b.cmp(a), Ordering::Greater);
1589 assert_eq!(a.cmp(a), Ordering::Equal);
1590 assert_eq!(b.cmp(b), Ordering::Equal);
1591 }
1592
1593 #[allow(clippy::eq_op)]
1594 fn eq_properties<T>(a: &T, b: &T, a_deref: &T::Target, b_deref: &T::Target)
1595 where
1596 T: Eq + Debug + Deref + PartialEq<<T as Deref>::Target>,
1597 {
1598 assert!(a != b);
1599 assert!(b != a);
1600 assert_eq!(a, a);
1601 assert!(a != b_deref);
1602 assert!(a == a_deref);
1603 assert!(b != a_deref);
1604 assert!(b == b_deref);
1605 }
1606
1607 fn debug_properties<T: Debug, U: ?Sized + Debug>(a: &T, b: &T, a_cmp: &U, b_cmp: &U) {
1608 assert_eq!(format!("{a:?}"), format!("{:?}", a_cmp));
1609 assert_eq!(format!("{b:?}"), format!("{:?}", b_cmp));
1610 }
1611
1612 fn display_properties<T: Debug + Display, U: ?Sized + Display>(a: &T, b: &T, a_cmp: &U, b_cmp: &U) {
1613 assert_eq!(a.to_string(), a_cmp.to_string());
1614 assert_eq!(b.to_string(), b_cmp.to_string());
1615 }
1616
1617 fn general_properties<T, U>(a: &T, b: &T, a_deref: &U, b_deref: &U)
1618 where
1619 T: Deref<Target = U> + Debug + Eq + PartialEq<U> + PartialOrd<U> + Ord + Hash,
1620 U: ?Sized + Debug + Eq + Ord + Hash,
1621 {
1622 eq_properties(a, b, a_deref, b_deref);
1623 ord_properties(a, b, a_deref, b_deref);
1624 hash_properties(a, b, a_deref, b_deref);
1625 debug_properties(a, b, a_deref, b_deref);
1626 }
1627
1628 const TEST_STR: &str = "foo";
1629 const TEST_STR2: &str = "fop";
1630 const TEST_SLICE: &[u8] = TEST_STR.as_bytes();
1631 const TEST_SLICE2: &[u8] = TEST_STR2.as_bytes();
1632
1633 fn test_strings() -> [String; 2] {
1634 [TEST_STR.to_string(), TEST_STR2.to_string()]
1635 }
1636
1637 fn test_slices() -> [Vec<u8>; 2] {
1638 [TEST_SLICE.to_owned(), TEST_SLICE2.to_owned()]
1639 }
1640
1641 fn various_boxed_slices() -> [[SlimSliceBox<u8>; 2]; 5] {
1642 [
1643 test_slices().map(SlimSliceBox::from_vec),
1644 test_slices().map(Box::from).map(SlimSliceBox::from_boxed),
1645 test_slices().map(|s| SlimSliceBox::try_from(s).unwrap()),
1646 test_slices().map(|s| SlimSliceBox::try_from(s.into_boxed_slice()).unwrap()),
1647 test_slices().map(|s| SlimSliceBox::from(<[u8; 3]>::try_from(s).unwrap())),
1648 ]
1649 }
1650
1651 fn various_boxed_strs() -> [[SlimStrBox; 2]; 7] {
1652 [
1653 [nstr!("foo"), nstr!("fop")],
1654 test_strings().map(|s| from_string(&s)),
1655 test_strings().map(SlimStrBox::from_string),
1656 test_strings().map(Box::from).map(SlimStrBox::from_boxed),
1657 test_strings().map(|s| SlimStrBox::try_from(s).unwrap()),
1658 test_strings().map(|s| SlimStrBox::try_from(s.into_boxed_str()).unwrap()),
1659 test_strings().map(|s| SlimStrBox::try_from(s.deref()).unwrap()),
1660 ]
1661 }
1662
1663 fn assert_str_mut_properties(s1: &mut SlimStrMut<'_>, s2: &mut SlimStrMut<'_>) {
1664 let a: &SlimStrMut<'_> = s1;
1665 let b: &SlimStrMut<'_> = s2;
1666
1667 assert_eq!(a.deref(), TEST_STR);
1668 assert_eq!(SlimStrBox::from(a).clone().deref(), TEST_STR);
1669 assert_eq!(b.deref(), TEST_STR2);
1670
1671 assert_eq!(String::from(a), TEST_STR);
1672 assert_eq!(<Box<str>>::from(a).deref(), TEST_STR);
1673 assert_eq!(SlimStrBox::from(a).deref(), TEST_STR);
1674 assert_eq!(<Box<str>>::from(SlimStrBox::from(a)).deref(), TEST_STR);
1675
1676 general_properties(a, b, TEST_STR, TEST_STR2);
1677 display_properties(a, b, TEST_STR, TEST_STR2);
1678
1679 s1.deref_mut().make_ascii_uppercase();
1680 assert_eq!(&**s1, TEST_STR.to_uppercase());
1681 }
1682
1683 #[test]
1684 fn str_mut_call() {
1685 let [mut s1, mut s2] = test_strings();
1686 let s1 = &mut from_str_mut(s1.as_mut_str());
1687 let s2 = &mut from_str_mut(s2.as_mut_str());
1688 assert_str_mut_properties(s1, s2);
1689 }
1690
1691 #[test]
1692 fn str_mut_try_into() {
1693 let [mut s1, mut s2] = test_strings();
1694 let s1: &mut SlimStrMut = &mut s1.as_mut().try_into().unwrap();
1695 let s2: &mut SlimStrMut = &mut s2.as_mut().try_into().unwrap();
1696 assert_str_mut_properties(s1, s2);
1697 }
1698
1699 #[test]
1700 fn str_mut_exclusive_ref_various() {
1701 for [mut a, mut b] in various_boxed_strs() {
1702 assert_str_mut_properties(a.exclusive_ref(), b.exclusive_ref())
1703 }
1704 }
1705
1706 fn assert_str_properties(a: &SlimStr<'_>, b: &SlimStr<'_>) {
1707 assert_eq!(a.deref(), TEST_STR);
1708 assert_eq!(SlimStrBox::from(a).clone().deref(), TEST_STR);
1709 assert_eq!(b.deref(), TEST_STR2);
1710
1711 assert_eq!(String::from(a), TEST_STR);
1712 assert_eq!(<Box<str>>::from(a).deref(), TEST_STR);
1713 assert_eq!(SlimStrBox::from(a).deref(), TEST_STR);
1714 assert_eq!(String::from(SlimStrBox::from(a)).deref(), TEST_STR);
1715 assert_eq!(<Box<str>>::from(SlimStrBox::from(a)).deref(), TEST_STR);
1716
1717 general_properties(a, b, TEST_STR, TEST_STR2);
1718 display_properties(a, b, TEST_STR, TEST_STR2);
1719 }
1720
1721 #[test]
1722 fn str_call() {
1723 let [s1, s2] = test_strings();
1724 assert_str_properties(&from_str(&s1), &from_str(&s2));
1725 }
1726
1727 #[test]
1728 fn str_try_into() {
1729 let [s1, s2] = test_strings();
1730 let s1: &SlimStr = &mut s1.deref().try_into().unwrap();
1731 let s2: &SlimStr = &mut s2.deref().try_into().unwrap();
1732 assert_str_properties(s1, s2);
1733 }
1734
1735 #[test]
1736 fn str_shared_ref_various() {
1737 for [a, b] in various_boxed_strs() {
1738 assert_str_properties(a.shared_ref(), b.shared_ref())
1739 }
1740 }
1741
1742 fn assert_slice_mut_properties(s1: &mut SlimSliceMut<'_, u8>, s2: &mut SlimSliceMut<'_, u8>) {
1743 let a: &SlimSliceMut<'_, u8> = s1;
1744 let b: &SlimSliceMut<'_, u8> = s2;
1745
1746 assert_eq!(a.deref(), TEST_SLICE);
1747 assert_eq!(SlimSliceBox::from(a).clone().deref(), TEST_SLICE);
1748 assert_eq!(b.deref(), TEST_SLICE2);
1749
1750 assert_eq!(<Vec<u8>>::from(a), TEST_SLICE);
1751 assert_eq!(<Box<[u8]>>::from(a).deref(), TEST_SLICE);
1752 assert_eq!(<SlimSliceBox<u8>>::from(a).deref(), TEST_SLICE);
1753 assert_eq!(<Vec<u8>>::from(<SlimSliceBox<u8>>::from(a)).deref(), TEST_SLICE);
1754
1755 general_properties(a, b, TEST_SLICE, TEST_SLICE2);
1756
1757 s1.deref_mut().make_ascii_uppercase();
1758 let mut upper = TEST_SLICE.to_owned();
1759 upper.iter_mut().for_each(|x| x.make_ascii_uppercase());
1760 assert_eq!(&**s1, upper);
1761 }
1762
1763 #[test]
1764 fn slice_mut_call() {
1765 let [mut s1, mut s2] = test_slices();
1766 let s1 = &mut from_slice_mut(s1.as_mut());
1767 let s2 = &mut from_slice_mut(s2.as_mut());
1768 assert_slice_mut_properties(s1, s2);
1769 }
1770
1771 #[test]
1772 fn slice_mut_try_into() {
1773 let [mut s1, mut s2] = test_slices();
1774 let s1: &mut SlimSliceMut<u8> = &mut s1.deref_mut().try_into().unwrap();
1775 let s2: &mut SlimSliceMut<u8> = &mut s2.deref_mut().try_into().unwrap();
1776 assert_slice_mut_properties(s1, s2);
1777 }
1778
1779 #[test]
1780 fn slice_mut_exclusive_ref_various() {
1781 for [mut a, mut b] in various_boxed_slices() {
1782 assert_slice_mut_properties(a.exclusive_ref(), b.exclusive_ref());
1783 }
1784 }
1785
1786 fn assert_slice_properties(a: &SlimSlice<'_, u8>, b: &SlimSlice<'_, u8>) {
1787 assert_eq!(a.deref(), TEST_SLICE);
1788 assert_eq!(SlimSliceBox::from(a).clone().deref(), TEST_SLICE);
1789 assert_eq!(b.deref(), TEST_SLICE2);
1790
1791 assert_eq!(<Vec<u8>>::from(a), TEST_SLICE);
1792 assert_eq!(<Box<[u8]>>::from(a).deref(), TEST_SLICE);
1793 assert_eq!(<SlimSliceBox<u8>>::from(a).deref(), TEST_SLICE);
1794 assert_eq!(<Vec<u8>>::from(<SlimSliceBox<u8>>::from(a)).deref(), TEST_SLICE);
1795
1796 general_properties(a, b, TEST_SLICE, TEST_SLICE2);
1797 }
1798
1799 #[test]
1800 fn slice_call() {
1801 let [s1, s2] = test_slices();
1802 assert_slice_properties(&from_slice(&s1), &from_slice(&s2));
1803 }
1804
1805 #[test]
1806 fn slice_try_into() {
1807 let [s1, s2] = test_slices();
1808 let s1: &SlimSlice<u8> = &s1.deref().try_into().unwrap();
1809 let s2: &SlimSlice<u8> = &s2.deref().try_into().unwrap();
1810 assert_slice_properties(s1, s2);
1811 }
1812
1813 #[test]
1814 fn slice_shared_ref_various() {
1815 for [a, b] in various_boxed_slices() {
1816 assert_slice_properties(a.shared_ref(), b.shared_ref())
1817 }
1818 }
1819}