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 let ptr = NonNull::new_unchecked(ptr);
261 let len = len as u32;
262 Self { ptr, len }
263 }
264}
265
266impl<T> Copy for SlimRawSlice<T> {}
267impl<T> Clone for SlimRawSlice<T> {
268 #[inline]
269 fn clone(&self) -> Self {
270 *self
271 }
272}
273
274pub use slim_slice_box::*;
279mod slim_slice_box {
280 use super::*;
284
285 #[repr(transparent)]
288 pub struct SlimSliceBox<T> {
289 raw: SlimRawSlice<T>,
293 owned: PhantomData<T>,
295 }
296
297 impl<T> Drop for SlimSliceBox<T> {
298 #[inline]
299 fn drop(&mut self) {
300 let raw = SlimRawSlice::dangling();
304 let owned = PhantomData;
305 let this = mem::replace(self, Self { raw, owned });
306
307 drop(into_box(this));
309 }
310 }
311
312 impl<T> SlimSliceBox<T> {
313 #[allow(clippy::boxed_local)]
319 #[inline]
320 pub unsafe fn from_boxed_unchecked(boxed: Box<[T]>) -> Self {
322 let len = boxed.len();
323 let ptr = Box::into_raw(boxed) as *mut T;
324 let raw = SlimRawSlice::from_len_ptr(len, ptr);
327 let owned = PhantomData;
328 Self { raw, owned }
329 }
330
331 #[allow(clippy::needless_lifetimes)]
333 #[inline]
334 pub fn shared_ref<'a>(&'a self) -> &'a SlimSlice<'a, T> {
335 unsafe { mem::transmute(self) }
338 }
339
340 #[allow(clippy::needless_lifetimes)]
342 #[inline]
343 pub fn exclusive_ref<'a>(&'a mut self) -> &'a mut SlimSliceMut<'a, T> {
344 unsafe { mem::transmute(self) }
348 }
349
350 #[inline]
354 pub fn map_safely_exchangeable<U: SafelyExchangeable<T>>(self) -> SlimSliceBox<U> {
355 SlimSliceBox {
359 raw: self.raw.cast(),
360 owned: PhantomData,
361 }
362 }
363 }
364
365 impl<T> From<SlimSliceBox<T>> for Box<[T]> {
366 #[inline]
367 fn from(slice: SlimSliceBox<T>) -> Self {
368 let slice = ManuallyDrop::new(slice);
369 let (ptr, len) = slice.raw.split();
370 unsafe { Box::from_raw(slice_from_raw_parts_mut(ptr, len)) }
383 }
384 }
385}
386
387unsafe impl<T: Send> Send for SlimSliceBox<T> {}
389
390unsafe impl<T: Sync> Sync for SlimSliceBox<T> {}
392
393impl<T> Deref for SlimSliceBox<T> {
394 type Target = [T];
395
396 #[inline]
397 fn deref(&self) -> &Self::Target {
398 self.shared_ref().deref()
399 }
400}
401
402impl<T> DerefMut for SlimSliceBox<T> {
403 #[inline]
404 fn deref_mut(&mut self) -> &mut Self::Target {
405 self.exclusive_ref().deref_mut()
406 }
407}
408
409impl<T> SlimSliceBox<T> {
410 #[inline]
414 pub fn from_boxed(boxed: Box<[T]>) -> Self {
415 expect_fit(boxed)
416 }
417
418 #[inline]
422 pub fn from_vec(vec: Vec<T>) -> Self {
423 Self::from_boxed(vec.into())
424 }
425
426 #[inline]
430 pub fn map<U>(self, by: impl FnMut(T) -> U) -> SlimSliceBox<U> {
431 let mapped = self.into_iter().map(by).collect::<Box<_>>();
432 unsafe { SlimSliceBox::from_boxed_unchecked(mapped) }
434 }
435
436 #[inline]
440 pub fn map_borrowed<U>(&self, by: impl FnMut(&T) -> U) -> SlimSliceBox<U> {
441 let mapped = self.iter().map(by).collect::<Box<_>>();
442 unsafe { SlimSliceBox::from_boxed_unchecked(mapped) }
444 }
445}
446
447impl<T> TryFrom<Box<[T]>> for SlimSliceBox<T> {
448 type Error = LenTooLong<Box<[T]>>;
449
450 #[inline]
451 fn try_from(boxed: Box<[T]>) -> Result<Self, Self::Error> {
452 ensure_len_fits!(boxed);
453 Ok(unsafe { Self::from_boxed_unchecked(boxed) })
455 }
456}
457
458impl<T> TryFrom<Vec<T>> for SlimSliceBox<T> {
459 type Error = LenTooLong<Vec<T>>;
460
461 #[inline]
462 fn try_from(vec: Vec<T>) -> Result<Self, Self::Error> {
463 ensure_len_fits!(vec);
464 Ok(unsafe { Self::from_boxed_unchecked(vec.into_boxed_slice()) })
466 }
467}
468
469impl<T, const N: usize> From<[T; N]> for SlimSliceBox<T> {
470 #[inline]
471 fn from(arr: [T; N]) -> Self {
472 #[allow(clippy::let_unit_value)]
473 let () = AssertU32::<N>::OK;
474
475 unsafe { Self::from_boxed_unchecked(into_box(arr)) }
477 }
478}
479
480impl<T> From<SlimSliceBox<T>> for Vec<T> {
481 #[inline]
482 fn from(slice: SlimSliceBox<T>) -> Self {
483 into_box(slice).into()
484 }
485}
486
487impl<T: Debug> Debug for SlimSliceBox<T> {
488 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
489 Debug::fmt(self.deref(), f)
490 }
491}
492
493impl<T: Clone> Clone for SlimSliceBox<T> {
494 #[inline]
495 fn clone(&self) -> Self {
496 let mut vec = Vec::with_capacity(self.len());
499 vec.extend_from_slice(self);
500 unsafe { Self::from_boxed_unchecked(into_box(vec)) }
502 }
503}
504
505impl<R: Deref, T> PartialEq<R> for SlimSliceBox<T>
506where
507 [T]: PartialEq<R::Target>,
508{
509 #[inline]
510 fn eq(&self, other: &R) -> bool {
511 **self == **other
512 }
513}
514
515impl<T: Eq> Eq for SlimSliceBox<T> {}
516
517impl<R: Deref, T> PartialOrd<R> for SlimSliceBox<T>
518where
519 [T]: PartialOrd<R::Target>,
520{
521 #[inline]
522 fn partial_cmp(&self, other: &R) -> Option<Ordering> {
523 (**self).partial_cmp(&**other)
524 }
525}
526
527impl<T: Ord> Ord for SlimSliceBox<T> {
528 #[inline]
529 fn cmp(&self, other: &Self) -> Ordering {
530 (**self).cmp(&**other)
531 }
532}
533
534impl<T: Hash> Hash for SlimSliceBox<T> {
535 #[inline]
536 fn hash<H: Hasher>(&self, state: &mut H) {
537 Hash::hash(&**self, state)
538 }
539}
540
541impl<T> IntoIterator for SlimSliceBox<T> {
542 type Item = T;
543 type IntoIter = <Vec<T> as IntoIterator>::IntoIter;
544 #[inline]
545 fn into_iter(self) -> Self::IntoIter {
546 Vec::from(self).into_iter()
547 }
548}
549
550pub struct SlimSliceBoxCollected<T> {
554 pub inner: Result<SlimSliceBox<T>, LenTooLong<Vec<T>>>,
556}
557
558impl<T: Debug> SlimSliceBoxCollected<T> {
559 #[inline]
560 pub fn unwrap(self) -> SlimSliceBox<T> {
561 self.inner.expect("number of elements overflowed `u32::MAX`")
562 }
563}
564
565impl<A> FromIterator<A> for SlimSliceBoxCollected<A> {
566 #[inline]
567 fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self {
568 let inner = iter.into_iter().collect::<Vec<_>>().try_into();
569 SlimSliceBoxCollected { inner }
570 }
571}
572
573#[derive(Clone)]
578pub struct SlimSmallSliceBox<T, const N: usize>(SlimSmallSliceBoxData<T, N>);
579
580#[derive(Clone)]
584enum SlimSmallSliceBoxData<T, const N: usize> {
585 Inline([T; N]),
587 Heap(SlimSliceBox<T>),
589}
590
591impl<T, const N: usize> From<[T; N]> for SlimSmallSliceBox<T, N> {
592 fn from(value: [T; N]) -> Self {
593 #[allow(clippy::let_unit_value)]
594 let () = AssertU32::<N>::OK;
595
596 Self(SlimSmallSliceBoxData::Inline(value))
597 }
598}
599
600impl<T, const N: usize> From<SlimSliceBox<T>> for SlimSmallSliceBox<T, N> {
601 fn from(value: SlimSliceBox<T>) -> Self {
602 Self(SlimSmallSliceBoxData::Heap(value))
603 }
604}
605
606impl<T, const N: usize> From<SlimSmallSliceBox<T, N>> for SlimSliceBox<T> {
607 fn from(SlimSmallSliceBox(value): SlimSmallSliceBox<T, N>) -> Self {
608 match value {
609 SlimSmallSliceBoxData::Inline(i) => i.into(),
610 SlimSmallSliceBoxData::Heap(h) => h,
611 }
612 }
613}
614
615impl<T, const N: usize> Deref for SlimSmallSliceBox<T, N> {
616 type Target = [T];
617 fn deref(&self) -> &Self::Target {
618 match &self.0 {
619 SlimSmallSliceBoxData::Inline(i) => i,
620 SlimSmallSliceBoxData::Heap(h) => h,
621 }
622 }
623}
624
625impl<T, const N: usize> DerefMut for SlimSmallSliceBox<T, N> {
626 fn deref_mut(&mut self) -> &mut Self::Target {
627 match &mut self.0 {
628 SlimSmallSliceBoxData::Inline(i) => i,
629 SlimSmallSliceBoxData::Heap(h) => h,
630 }
631 }
632}
633
634impl<T: PartialEq, const N: usize> PartialEq for SlimSmallSliceBox<T, N> {
635 fn eq(&self, other: &Self) -> bool {
636 self.deref().eq(other.deref())
637 }
638}
639
640impl<T: Eq, const N: usize> Eq for SlimSmallSliceBox<T, N> {}
641
642impl<T: Debug, const N: usize> fmt::Debug for SlimSmallSliceBox<T, N> {
643 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
644 Debug::fmt(self.deref(), f)
645 }
646}
647
648impl<T, const N: usize> From<SmallVec<[T; N]>> for SlimSmallSliceBox<T, N> {
649 fn from(value: SmallVec<[T; N]>) -> Self {
650 match value.into_inner() {
651 Ok(inline) => inline.into(),
652 Err(heap) => SlimSliceBox::from_boxed(heap.into_boxed_slice()).into(),
653 }
654 }
655}
656
657#[repr(transparent)]
664pub struct SlimStrBox {
665 raw: SlimSliceBox<u8>,
667}
668
669#[cfg(feature = "serde")]
670impl serde::Serialize for SlimStrBox {
671 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
672 s.serialize_str(self.deref())
673 }
674}
675
676impl SlimStrBox {
677 #[inline]
683 pub unsafe fn from_boxed_unchecked(boxed: Box<str>) -> Self {
684 let raw = unsafe { SlimSliceBox::from_boxed_unchecked(into_box(boxed)) };
686 Self { raw }
687 }
688
689 #[inline]
693 pub fn from_boxed(boxed: Box<str>) -> Self {
694 expect_fit(boxed)
695 }
696
697 #[inline]
701 pub fn from_string(str: String) -> Self {
702 Self::from_boxed(str.into())
703 }
704
705 #[allow(clippy::needless_lifetimes)]
707 #[inline]
708 pub fn shared_ref<'a>(&'a self) -> &'a SlimStr<'a> {
709 unsafe { mem::transmute(self.raw.shared_ref()) }
713 }
714
715 #[allow(clippy::needless_lifetimes)]
717 #[inline]
718 pub fn exclusive_ref<'a>(&'a mut self) -> &'a mut SlimStrMut<'a> {
719 unsafe { mem::transmute(self.raw.exclusive_ref()) }
723 }
724}
725
726impl Deref for SlimStrBox {
727 type Target = str;
728
729 #[inline]
730 fn deref(&self) -> &Self::Target {
731 self.shared_ref().deref()
732 }
733}
734
735impl DerefMut for SlimStrBox {
736 #[inline]
737 fn deref_mut(&mut self) -> &mut Self::Target {
738 self.exclusive_ref().deref_mut()
739 }
740}
741
742impl<const N: usize> From<NStr<N>> for SlimStrBox {
743 #[inline]
744 fn from(arr: NStr<N>) -> Self {
745 (&arr).into()
746 }
747}
748
749impl<const N: usize> From<&NStr<N>> for SlimStrBox {
750 #[inline]
751 fn from(arr: &NStr<N>) -> Self {
752 <SlimStr<'_>>::from(arr).into()
753 }
754}
755
756impl TryFrom<Box<str>> for SlimStrBox {
757 type Error = LenTooLong<Box<str>>;
758
759 #[inline]
760 fn try_from(boxed: Box<str>) -> Result<Self, Self::Error> {
761 ensure_len_fits!(boxed);
762 Ok(unsafe { Self::from_boxed_unchecked(boxed) })
764 }
765}
766
767impl TryFrom<String> for SlimStrBox {
768 type Error = LenTooLong<String>;
769
770 #[inline]
771 fn try_from(str: String) -> Result<Self, Self::Error> {
772 ensure_len_fits!(str);
773 Ok(unsafe { Self::from_boxed_unchecked(str.into_boxed_str()) })
775 }
776}
777
778impl<'a> TryFrom<&'a str> for SlimStrBox {
779 type Error = LenTooLong<&'a str>;
780
781 #[inline]
782 fn try_from(str: &'a str) -> Result<Self, Self::Error> {
783 str.try_into().map(|s: SlimStr<'_>| s.into())
784 }
785}
786
787impl From<SlimStrBox> for Box<str> {
788 #[inline]
789 fn from(str: SlimStrBox) -> Self {
790 let raw_box = into_box(str.raw);
791 unsafe { Box::from_raw(Box::into_raw(raw_box) as *mut str) }
793 }
794}
795
796impl From<SlimStrBox> for String {
797 #[inline]
798 fn from(str: SlimStrBox) -> Self {
799 <Box<str>>::from(str).into()
800 }
801}
802
803impl Debug for SlimStrBox {
804 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
805 Debug::fmt(self.deref(), f)
806 }
807}
808
809impl Display for SlimStrBox {
810 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
811 Display::fmt(self.deref(), f)
812 }
813}
814
815impl Clone for SlimStrBox {
816 #[inline]
817 fn clone(&self) -> Self {
818 Self { raw: self.raw.clone() }
819 }
820}
821
822impl<R: Deref> PartialEq<R> for SlimStrBox
823where
824 str: PartialEq<R::Target>,
825{
826 #[inline]
827 fn eq(&self, other: &R) -> bool {
828 self.deref() == other.deref()
829 }
830}
831
832impl Eq for SlimStrBox {}
833
834impl<R: Deref> PartialOrd<R> for SlimStrBox
835where
836 str: PartialOrd<R::Target>,
837{
838 #[inline]
839 fn partial_cmp(&self, other: &R) -> Option<Ordering> {
840 self.deref().partial_cmp(other.deref())
841 }
842}
843
844impl Ord for SlimStrBox {
845 #[inline]
846 fn cmp(&self, other: &Self) -> Ordering {
847 self.deref().cmp(other.deref())
848 }
849}
850
851impl Hash for SlimStrBox {
852 #[inline]
853 fn hash<H: Hasher>(&self, state: &mut H) {
854 Hash::hash(self.deref(), state)
855 }
856}
857
858impl Borrow<str> for SlimStrBox {
859 #[inline]
860 fn borrow(&self) -> &str {
861 self
862 }
863}
864
865#[allow(clippy::module_inception)]
870mod slim_slice {
871 use super::*;
872
873 #[repr(transparent)]
875 #[derive(Clone, Copy)]
876 pub struct SlimSlice<'a, T> {
877 raw: SlimRawSlice<T>,
879 covariant: PhantomData<&'a [T]>,
881 }
882
883 impl<'a, T> SlimSlice<'a, T> {
884 pub(super) const unsafe fn from_slice_unchecked(slice: &'a [T]) -> Self {
888 let len = slice.len();
889 let ptr = slice.as_ptr().cast_mut();
890 let raw = SlimRawSlice::from_len_ptr(len, ptr);
892 let covariant = PhantomData;
894 Self { raw, covariant }
895 }
896 }
897
898 impl<T> Deref for SlimSlice<'_, T> {
899 type Target = [T];
900
901 fn deref(&self) -> &Self::Target {
902 unsafe { self.raw.deref() }
907 }
908 }
909}
910pub use slim_slice::*;
911
912use crate::nstr::NStr;
913
914unsafe impl<T: Send + Sync> Send for SlimSlice<'_, T> {}
916
917unsafe impl<T: Sync> Sync for SlimSlice<'_, T> {}
919
920impl<T> SlimSlice<'_, T> {
921 #[inline]
925 pub fn try_map<U, E>(&self, by: impl FnMut(&T) -> Result<U, E>) -> Result<SlimSliceBox<U>, E> {
926 let mapped = self.iter().map(by).collect::<Result<_, _>>()?;
927 Ok(unsafe { SlimSliceBox::from_boxed_unchecked(mapped) })
929 }
930}
931
932impl<T: Debug> Debug for SlimSlice<'_, T> {
933 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
934 Debug::fmt(self.deref(), f)
935 }
936}
937
938impl<T: Hash> Hash for SlimSlice<'_, T> {
939 #[inline]
940 fn hash<H: Hasher>(&self, state: &mut H) {
941 Hash::hash(self.deref(), state)
942 }
943}
944
945impl<T: Eq> Eq for SlimSlice<'_, T> {}
946impl<T: PartialEq> PartialEq for SlimSlice<'_, T> {
947 #[inline]
948 fn eq(&self, other: &Self) -> bool {
949 self.deref() == other.deref()
950 }
951}
952impl<T: PartialEq> PartialEq<[T]> for SlimSlice<'_, T> {
953 #[inline]
954 fn eq(&self, other: &[T]) -> bool {
955 self.deref() == other
956 }
957}
958
959impl<T: Ord> Ord for SlimSlice<'_, T> {
960 #[inline]
961 fn cmp(&self, other: &Self) -> Ordering {
962 self.deref().cmp(other)
963 }
964}
965impl<T: PartialOrd> PartialOrd for SlimSlice<'_, T> {
966 #[inline]
967 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
968 self.deref().partial_cmp(other.deref())
969 }
970}
971impl<T: PartialOrd> PartialOrd<[T]> for SlimSlice<'_, T> {
972 #[inline]
973 fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
974 self.deref().partial_cmp(other)
975 }
976}
977
978impl<T: Clone> From<&SlimSlice<'_, T>> for SlimSliceBox<T> {
979 #[inline]
980 fn from(slice: &SlimSlice<'_, T>) -> Self {
981 let boxed = into_box(slice.deref());
982 unsafe { Self::from_boxed_unchecked(boxed) }
984 }
985}
986impl<T: Clone> From<&SlimSlice<'_, T>> for Box<[T]> {
987 #[inline]
988 fn from(slice: &SlimSlice<'_, T>) -> Self {
989 slice.deref().into()
990 }
991}
992impl<T: Clone> From<&SlimSlice<'_, T>> for Vec<T> {
993 #[inline]
994 fn from(slice: &SlimSlice<'_, T>) -> Self {
995 slice.deref().into()
996 }
997}
998
999impl<T: Clone> From<SlimSlice<'_, T>> for SlimSliceBox<T> {
1000 #[inline]
1001 fn from(slice: SlimSlice<'_, T>) -> Self {
1002 (&slice).into()
1003 }
1004}
1005impl<T: Clone> From<SlimSlice<'_, T>> for Box<[T]> {
1006 #[inline]
1007 fn from(slice: SlimSlice<'_, T>) -> Self {
1008 slice.deref().into()
1009 }
1010}
1011impl<T: Clone> From<SlimSlice<'_, T>> for Vec<T> {
1012 #[inline]
1013 fn from(slice: SlimSlice<'_, T>) -> Self {
1014 slice.deref().into()
1015 }
1016}
1017
1018impl<'a, T> TryFrom<&'a [T]> for SlimSlice<'a, T> {
1019 type Error = LenTooLong<&'a [T]>;
1020
1021 #[inline]
1022 fn try_from(slice: &'a [T]) -> Result<Self, Self::Error> {
1023 ensure_len_fits!(slice);
1024 Ok(unsafe { Self::from_slice_unchecked(slice) })
1026 }
1027}
1028
1029#[inline]
1033pub fn from_slice<T>(s: &[T]) -> SlimSlice<'_, T> {
1034 expect_fit(s)
1035}
1036
1037#[repr(transparent)]
1043pub struct SlimSliceMut<'a, T> {
1044 raw: SlimRawSlice<T>,
1046 invariant: PhantomData<&'a mut [T]>,
1048}
1049
1050unsafe impl<T: Send> Send for SlimSliceMut<'_, T> {}
1052
1053unsafe impl<T: Sync> Sync for SlimSliceMut<'_, T> {}
1055
1056impl<'a, T> SlimSliceMut<'a, T> {
1057 #[inline]
1059 pub fn shared(&'a self) -> &'a SlimSlice<'a, T> {
1060 unsafe { mem::transmute(self) }
1063 }
1064
1065 #[inline]
1069 unsafe fn from_slice_unchecked(slice: &'a mut [T]) -> Self {
1070 let raw = SlimRawSlice::from_len_ptr(slice.len(), slice.as_mut_ptr());
1072 let invariant = PhantomData;
1075 Self { raw, invariant }
1076 }
1077}
1078
1079impl<T> Deref for SlimSliceMut<'_, T> {
1080 type Target = [T];
1081
1082 #[inline]
1083 fn deref(&self) -> &Self::Target {
1084 self.shared().deref()
1085 }
1086}
1087
1088impl<T> DerefMut for SlimSliceMut<'_, T> {
1089 #[inline]
1090 fn deref_mut(&mut self) -> &mut Self::Target {
1091 unsafe { self.raw.deref_mut() }
1097 }
1098}
1099
1100impl<T: Debug> Debug for SlimSliceMut<'_, T> {
1101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1102 Debug::fmt(self.deref(), f)
1103 }
1104}
1105
1106impl<T: Hash> Hash for SlimSliceMut<'_, T> {
1107 #[inline]
1108 fn hash<H: Hasher>(&self, state: &mut H) {
1109 Hash::hash(self.deref(), state)
1110 }
1111}
1112
1113impl<T: Eq> Eq for SlimSliceMut<'_, T> {}
1114impl<T: PartialEq> PartialEq for SlimSliceMut<'_, T> {
1115 #[inline]
1116 fn eq(&self, other: &Self) -> bool {
1117 self.deref() == other.deref()
1118 }
1119}
1120impl<T: PartialEq> PartialEq<[T]> for SlimSliceMut<'_, T> {
1121 #[inline]
1122 fn eq(&self, other: &[T]) -> bool {
1123 self.deref() == other
1124 }
1125}
1126
1127impl<T: Ord> Ord for SlimSliceMut<'_, T> {
1128 #[inline]
1129 fn cmp(&self, other: &Self) -> Ordering {
1130 self.deref().cmp(other)
1131 }
1132}
1133impl<T: PartialOrd> PartialOrd for SlimSliceMut<'_, T> {
1134 #[inline]
1135 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1136 self.deref().partial_cmp(other.deref())
1137 }
1138}
1139impl<T: PartialOrd> PartialOrd<[T]> for SlimSliceMut<'_, T> {
1140 #[inline]
1141 fn partial_cmp(&self, other: &[T]) -> Option<Ordering> {
1142 self.deref().partial_cmp(other)
1143 }
1144}
1145
1146impl<T: Clone> From<&SlimSliceMut<'_, T>> for SlimSliceBox<T> {
1147 #[inline]
1148 fn from(slice: &SlimSliceMut<'_, T>) -> Self {
1149 unsafe { Self::from_boxed_unchecked(into_box(slice.deref())) }
1151 }
1152}
1153impl<T: Clone> From<&SlimSliceMut<'_, T>> for Box<[T]> {
1154 #[inline]
1155 fn from(slice: &SlimSliceMut<'_, T>) -> Self {
1156 slice.deref().into()
1157 }
1158}
1159impl<T: Clone> From<&SlimSliceMut<'_, T>> for Vec<T> {
1160 #[inline]
1161 fn from(slice: &SlimSliceMut<'_, T>) -> Self {
1162 slice.deref().into()
1163 }
1164}
1165
1166impl<T: Clone> From<SlimSliceMut<'_, T>> for SlimSliceBox<T> {
1167 #[inline]
1168 fn from(slice: SlimSliceMut<'_, T>) -> Self {
1169 (&slice).into()
1170 }
1171}
1172impl<T: Clone> From<SlimSliceMut<'_, T>> for Box<[T]> {
1173 #[inline]
1174 fn from(slice: SlimSliceMut<'_, T>) -> Self {
1175 slice.deref().into()
1176 }
1177}
1178impl<T: Clone> From<SlimSliceMut<'_, T>> for Vec<T> {
1179 #[inline]
1180 fn from(slice: SlimSliceMut<'_, T>) -> Self {
1181 slice.deref().into()
1182 }
1183}
1184
1185impl<'a, T> TryFrom<&'a mut [T]> for SlimSliceMut<'a, T> {
1186 type Error = LenTooLong<&'a mut [T]>;
1187
1188 #[inline]
1189 fn try_from(slice: &'a mut [T]) -> Result<Self, Self::Error> {
1190 ensure_len_fits!(slice);
1191 Ok(unsafe { Self::from_slice_unchecked(slice) })
1193 }
1194}
1195
1196#[inline]
1200pub fn from_slice_mut<T>(s: &mut [T]) -> SlimSliceMut<'_, T> {
1201 expect_fit(s)
1202}
1203
1204#[repr(transparent)]
1210#[derive(Clone, Copy)]
1211pub struct SlimStr<'a> {
1212 raw: SlimSlice<'a, u8>,
1214}
1215
1216impl<'a> SlimStr<'a> {
1217 #[inline]
1223 const unsafe fn from_str_unchecked(s: &'a str) -> Self {
1224 let raw = unsafe { SlimSlice::from_slice_unchecked(s.as_bytes()) };
1226 Self { raw }
1228 }
1229}
1230
1231impl Deref for SlimStr<'_> {
1232 type Target = str;
1233
1234 #[inline]
1235 fn deref(&self) -> &Self::Target {
1236 unsafe { from_utf8_unchecked(self.raw.deref()) }
1238 }
1239}
1240
1241impl Debug for SlimStr<'_> {
1242 #[inline]
1243 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1244 Debug::fmt(self.deref(), f)
1245 }
1246}
1247
1248impl Display for SlimStr<'_> {
1249 #[inline]
1250 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1251 Display::fmt(self.deref(), f)
1252 }
1253}
1254
1255impl Hash for SlimStr<'_> {
1256 #[inline]
1257 fn hash<H: Hasher>(&self, state: &mut H) {
1258 Hash::hash(self.deref(), state)
1259 }
1260}
1261
1262impl Eq for SlimStr<'_> {}
1263impl PartialEq for SlimStr<'_> {
1264 #[inline]
1265 fn eq(&self, other: &Self) -> bool {
1266 self.deref() == other.deref()
1267 }
1268}
1269impl PartialEq<str> for SlimStr<'_> {
1270 #[inline]
1271 fn eq(&self, other: &str) -> bool {
1272 self.deref() == other
1273 }
1274}
1275
1276impl Ord for SlimStr<'_> {
1277 #[inline]
1278 fn cmp(&self, other: &Self) -> Ordering {
1279 self.deref().cmp(other)
1280 }
1281}
1282impl PartialOrd for SlimStr<'_> {
1283 #[inline]
1284 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1285 Some(self.cmp(other))
1286 }
1287}
1288impl PartialOrd<str> for SlimStr<'_> {
1289 #[inline]
1290 fn partial_cmp(&self, other: &str) -> Option<Ordering> {
1291 self.deref().partial_cmp(other)
1292 }
1293}
1294
1295impl From<&SlimStr<'_>> for SlimStrBox {
1296 #[inline]
1297 fn from(slice: &SlimStr<'_>) -> Self {
1298 (*slice).into()
1299 }
1300}
1301impl From<&SlimStr<'_>> for Box<str> {
1302 #[inline]
1303 fn from(slice: &SlimStr<'_>) -> Self {
1304 slice.deref().into()
1305 }
1306}
1307impl From<&SlimStr<'_>> for String {
1308 #[inline]
1309 fn from(slice: &SlimStr<'_>) -> Self {
1310 slice.deref().into()
1311 }
1312}
1313
1314impl From<SlimStr<'_>> for SlimStrBox {
1315 #[inline]
1316 fn from(slice: SlimStr<'_>) -> Self {
1317 Self { raw: slice.raw.into() }
1319 }
1320}
1321impl From<SlimStr<'_>> for Box<str> {
1322 #[inline]
1323 fn from(slice: SlimStr<'_>) -> Self {
1324 slice.deref().into()
1325 }
1326}
1327impl From<SlimStr<'_>> for String {
1328 #[inline]
1329 fn from(slice: SlimStr<'_>) -> Self {
1330 slice.deref().into()
1331 }
1332}
1333
1334impl<'a, const N: usize> From<&'a NStr<N>> for SlimStr<'a> {
1335 #[inline]
1336 fn from(arr: &'a NStr<N>) -> Self {
1337 #[allow(clippy::let_unit_value)]
1338 let () = AssertU32::<N>::OK;
1339
1340 unsafe { Self::from_str_unchecked(arr) }
1342 }
1343}
1344impl<'a> TryFrom<&'a str> for SlimStr<'a> {
1345 type Error = LenTooLong<&'a str>;
1346
1347 #[inline]
1348 fn try_from(s: &'a str) -> Result<Self, Self::Error> {
1349 ensure_len_fits!(s);
1350 Ok(unsafe { Self::from_str_unchecked(s) })
1352 }
1353}
1354
1355#[inline]
1359pub const fn from_str(s: &str) -> SlimStr<'_> {
1360 if s.len() > u32::MAX as usize {
1361 panic!("length didn't fit in `u32`");
1362 }
1363
1364 unsafe { SlimStr::from_str_unchecked(s) }
1366}
1367
1368#[inline]
1372pub fn from_string(s: &str) -> SlimStrBox {
1373 from_str(s).into()
1374}
1375
1376#[repr(transparent)]
1382pub struct SlimStrMut<'a> {
1383 raw: SlimSliceMut<'a, u8>,
1385}
1386
1387impl<'a> SlimStrMut<'a> {
1388 #[inline]
1394 unsafe fn from_str_unchecked(s: &'a mut str) -> Self {
1395 let raw = unsafe { SlimSliceMut::from_slice_unchecked(s.as_bytes_mut()) };
1397 Self { raw }
1399 }
1400}
1401
1402impl Deref for SlimStrMut<'_> {
1403 type Target = str;
1404
1405 #[inline]
1406 fn deref(&self) -> &Self::Target {
1407 unsafe { from_utf8_unchecked(self.raw.deref()) }
1409 }
1410}
1411
1412impl DerefMut for SlimStrMut<'_> {
1413 #[inline]
1414 fn deref_mut(&mut self) -> &mut Self::Target {
1415 unsafe { from_utf8_unchecked_mut(self.raw.deref_mut()) }
1417 }
1418}
1419
1420impl Debug for SlimStrMut<'_> {
1421 #[inline]
1422 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1423 Debug::fmt(self.deref(), f)
1424 }
1425}
1426
1427impl Display for SlimStrMut<'_> {
1428 #[inline]
1429 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1430 Display::fmt(self.deref(), f)
1431 }
1432}
1433
1434impl Hash for SlimStrMut<'_> {
1435 #[inline]
1436 fn hash<H: Hasher>(&self, state: &mut H) {
1437 Hash::hash(self.deref(), state)
1438 }
1439}
1440
1441impl Eq for SlimStrMut<'_> {}
1442impl PartialEq for SlimStrMut<'_> {
1443 #[inline]
1444 fn eq(&self, other: &Self) -> bool {
1445 self.deref() == other.deref()
1446 }
1447}
1448impl PartialEq<str> for SlimStrMut<'_> {
1449 #[inline]
1450 fn eq(&self, other: &str) -> bool {
1451 self.deref() == other
1452 }
1453}
1454
1455impl Ord for SlimStrMut<'_> {
1456 #[inline]
1457 fn cmp(&self, other: &Self) -> Ordering {
1458 self.deref().cmp(other)
1459 }
1460}
1461impl PartialOrd for SlimStrMut<'_> {
1462 #[inline]
1463 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1464 Some(self.cmp(other))
1465 }
1466}
1467impl PartialOrd<str> for SlimStrMut<'_> {
1468 #[inline]
1469 fn partial_cmp(&self, other: &str) -> Option<Ordering> {
1470 self.deref().partial_cmp(other)
1471 }
1472}
1473
1474impl From<&SlimStrMut<'_>> for SlimStrBox {
1475 #[inline]
1476 fn from(slice: &SlimStrMut<'_>) -> Self {
1477 Self {
1479 raw: (&slice.raw).into(),
1480 }
1481 }
1482}
1483impl From<&SlimStrMut<'_>> for Box<str> {
1484 #[inline]
1485 fn from(slice: &SlimStrMut<'_>) -> Self {
1486 slice.deref().into()
1487 }
1488}
1489impl From<&SlimStrMut<'_>> for String {
1490 #[inline]
1491 fn from(slice: &SlimStrMut<'_>) -> Self {
1492 slice.deref().into()
1493 }
1494}
1495
1496impl From<SlimStrMut<'_>> for SlimStrBox {
1497 #[inline]
1498 fn from(slice: SlimStrMut<'_>) -> Self {
1499 (&slice).into()
1500 }
1501}
1502impl From<SlimStrMut<'_>> for Box<str> {
1503 #[inline]
1504 fn from(slice: SlimStrMut<'_>) -> Self {
1505 slice.deref().into()
1506 }
1507}
1508impl From<SlimStrMut<'_>> for String {
1509 #[inline]
1510 fn from(slice: SlimStrMut<'_>) -> Self {
1511 slice.deref().into()
1512 }
1513}
1514
1515impl<'a, const N: usize> From<&'a mut NStr<N>> for SlimStrMut<'a> {
1516 #[inline]
1517 fn from(arr: &'a mut NStr<N>) -> Self {
1518 #[allow(clippy::let_unit_value)]
1519 let () = AssertU32::<N>::OK;
1520
1521 unsafe { Self::from_str_unchecked(arr) }
1523 }
1524}
1525impl<'a> TryFrom<&'a mut str> for SlimStrMut<'a> {
1526 type Error = LenTooLong<&'a mut str>;
1527
1528 #[inline]
1529 fn try_from(slice: &'a mut str) -> Result<Self, Self::Error> {
1530 ensure_len_fits!(slice);
1531 Ok(unsafe { Self::from_str_unchecked(slice) })
1533 }
1534}
1535
1536#[inline]
1540pub fn from_str_mut(s: &mut str) -> SlimStrMut<'_> {
1541 expect_fit(s)
1542}
1543
1544#[cfg(test)]
1545mod tests {
1546 use std::hash::BuildHasher;
1547
1548 use super::*;
1549 use crate::map::DefaultHashBuilder;
1550 use crate::nstr;
1551
1552 fn hash_of<T: Hash>(x: T) -> u64 {
1553 DefaultHashBuilder::default().hash_one(&x)
1554 }
1555
1556 fn hash_properties<T>(a: &T, b: &T, a_deref: &T::Target, b_deref: &T::Target)
1557 where
1558 T: Hash + Debug + Deref,
1559 <T as Deref>::Target: Hash,
1560 {
1561 assert_eq!(hash_of(a), hash_of(a_deref));
1562 assert_eq!(hash_of(b), hash_of(b_deref));
1563 assert_ne!(hash_of(a), hash_of(b));
1564 }
1565
1566 fn ord_properties<T>(a: &T, b: &T, a_deref: &T::Target, b_deref: &T::Target)
1567 where
1568 T: Ord + Debug + Deref + PartialOrd<<T as Deref>::Target>,
1569 {
1570 assert_eq!(a.partial_cmp(b), Some(Ordering::Less));
1571 assert_eq!(b.partial_cmp(a), Some(Ordering::Greater));
1572 assert_eq!(a.partial_cmp(a), Some(Ordering::Equal));
1573 assert_eq!(b.partial_cmp(b), Some(Ordering::Equal));
1574 assert_eq!(a.partial_cmp(b_deref), Some(Ordering::Less));
1575 assert_eq!(b.partial_cmp(a_deref), Some(Ordering::Greater));
1576 assert_eq!(a.partial_cmp(a_deref), Some(Ordering::Equal));
1577 assert_eq!(b.partial_cmp(b_deref), Some(Ordering::Equal));
1578
1579 assert_eq!(a.cmp(b), Ordering::Less);
1580 assert_eq!(b.cmp(a), Ordering::Greater);
1581 assert_eq!(a.cmp(a), Ordering::Equal);
1582 assert_eq!(b.cmp(b), Ordering::Equal);
1583 }
1584
1585 #[allow(clippy::eq_op)]
1586 fn eq_properties<T>(a: &T, b: &T, a_deref: &T::Target, b_deref: &T::Target)
1587 where
1588 T: Eq + Debug + Deref + PartialEq<<T as Deref>::Target>,
1589 {
1590 assert!(a != b);
1591 assert!(b != a);
1592 assert_eq!(a, a);
1593 assert!(a != b_deref);
1594 assert!(a == a_deref);
1595 assert!(b != a_deref);
1596 assert!(b == b_deref);
1597 }
1598
1599 fn debug_properties<T: Debug, U: ?Sized + Debug>(a: &T, b: &T, a_cmp: &U, b_cmp: &U) {
1600 assert_eq!(format!("{a:?}"), format!("{:?}", a_cmp));
1601 assert_eq!(format!("{b:?}"), format!("{:?}", b_cmp));
1602 }
1603
1604 fn display_properties<T: Debug + Display, U: ?Sized + Display>(a: &T, b: &T, a_cmp: &U, b_cmp: &U) {
1605 assert_eq!(a.to_string(), a_cmp.to_string());
1606 assert_eq!(b.to_string(), b_cmp.to_string());
1607 }
1608
1609 fn general_properties<T, U>(a: &T, b: &T, a_deref: &U, b_deref: &U)
1610 where
1611 T: Deref<Target = U> + Debug + Eq + PartialEq<U> + PartialOrd<U> + Ord + Hash,
1612 U: ?Sized + Debug + Eq + Ord + Hash,
1613 {
1614 eq_properties(a, b, a_deref, b_deref);
1615 ord_properties(a, b, a_deref, b_deref);
1616 hash_properties(a, b, a_deref, b_deref);
1617 debug_properties(a, b, a_deref, b_deref);
1618 }
1619
1620 const TEST_STR: &str = "foo";
1621 const TEST_STR2: &str = "fop";
1622 const TEST_SLICE: &[u8] = TEST_STR.as_bytes();
1623 const TEST_SLICE2: &[u8] = TEST_STR2.as_bytes();
1624
1625 fn test_strings() -> [String; 2] {
1626 [TEST_STR.to_string(), TEST_STR2.to_string()]
1627 }
1628
1629 fn test_slices() -> [Vec<u8>; 2] {
1630 [TEST_SLICE.to_owned(), TEST_SLICE2.to_owned()]
1631 }
1632
1633 fn various_boxed_slices() -> [[SlimSliceBox<u8>; 2]; 5] {
1634 [
1635 test_slices().map(SlimSliceBox::from_vec),
1636 test_slices().map(Box::from).map(SlimSliceBox::from_boxed),
1637 test_slices().map(|s| SlimSliceBox::try_from(s).unwrap()),
1638 test_slices().map(|s| SlimSliceBox::try_from(s.into_boxed_slice()).unwrap()),
1639 test_slices().map(|s| SlimSliceBox::from(<[u8; 3]>::try_from(s).unwrap())),
1640 ]
1641 }
1642
1643 fn various_boxed_strs() -> [[SlimStrBox; 2]; 7] {
1644 [
1645 [nstr!("foo"), nstr!("fop")],
1646 test_strings().map(|s| from_string(&s)),
1647 test_strings().map(SlimStrBox::from_string),
1648 test_strings().map(Box::from).map(SlimStrBox::from_boxed),
1649 test_strings().map(|s| SlimStrBox::try_from(s).unwrap()),
1650 test_strings().map(|s| SlimStrBox::try_from(s.into_boxed_str()).unwrap()),
1651 test_strings().map(|s| SlimStrBox::try_from(s.deref()).unwrap()),
1652 ]
1653 }
1654
1655 fn assert_str_mut_properties(s1: &mut SlimStrMut<'_>, s2: &mut SlimStrMut<'_>) {
1656 let a: &SlimStrMut<'_> = s1;
1657 let b: &SlimStrMut<'_> = s2;
1658
1659 assert_eq!(a.deref(), TEST_STR);
1660 assert_eq!(SlimStrBox::from(a).clone().deref(), TEST_STR);
1661 assert_eq!(b.deref(), TEST_STR2);
1662
1663 assert_eq!(String::from(a), TEST_STR);
1664 assert_eq!(<Box<str>>::from(a).deref(), TEST_STR);
1665 assert_eq!(SlimStrBox::from(a).deref(), TEST_STR);
1666 assert_eq!(<Box<str>>::from(SlimStrBox::from(a)).deref(), TEST_STR);
1667
1668 general_properties(a, b, TEST_STR, TEST_STR2);
1669 display_properties(a, b, TEST_STR, TEST_STR2);
1670
1671 s1.deref_mut().make_ascii_uppercase();
1672 assert_eq!(&**s1, TEST_STR.to_uppercase());
1673 }
1674
1675 #[test]
1676 fn str_mut_call() {
1677 let [mut s1, mut s2] = test_strings();
1678 let s1 = &mut from_str_mut(s1.as_mut_str());
1679 let s2 = &mut from_str_mut(s2.as_mut_str());
1680 assert_str_mut_properties(s1, s2);
1681 }
1682
1683 #[test]
1684 fn str_mut_try_into() {
1685 let [mut s1, mut s2] = test_strings();
1686 let s1: &mut SlimStrMut = &mut s1.as_mut().try_into().unwrap();
1687 let s2: &mut SlimStrMut = &mut s2.as_mut().try_into().unwrap();
1688 assert_str_mut_properties(s1, s2);
1689 }
1690
1691 #[test]
1692 fn str_mut_exclusive_ref_various() {
1693 for [mut a, mut b] in various_boxed_strs() {
1694 assert_str_mut_properties(a.exclusive_ref(), b.exclusive_ref())
1695 }
1696 }
1697
1698 fn assert_str_properties(a: &SlimStr<'_>, b: &SlimStr<'_>) {
1699 assert_eq!(a.deref(), TEST_STR);
1700 assert_eq!(SlimStrBox::from(a).clone().deref(), TEST_STR);
1701 assert_eq!(b.deref(), TEST_STR2);
1702
1703 assert_eq!(String::from(a), TEST_STR);
1704 assert_eq!(<Box<str>>::from(a).deref(), TEST_STR);
1705 assert_eq!(SlimStrBox::from(a).deref(), TEST_STR);
1706 assert_eq!(String::from(SlimStrBox::from(a)).deref(), TEST_STR);
1707 assert_eq!(<Box<str>>::from(SlimStrBox::from(a)).deref(), TEST_STR);
1708
1709 general_properties(a, b, TEST_STR, TEST_STR2);
1710 display_properties(a, b, TEST_STR, TEST_STR2);
1711 }
1712
1713 #[test]
1714 fn str_call() {
1715 let [s1, s2] = test_strings();
1716 assert_str_properties(&from_str(&s1), &from_str(&s2));
1717 }
1718
1719 #[test]
1720 fn str_try_into() {
1721 let [s1, s2] = test_strings();
1722 let s1: &SlimStr = &mut s1.deref().try_into().unwrap();
1723 let s2: &SlimStr = &mut s2.deref().try_into().unwrap();
1724 assert_str_properties(s1, s2);
1725 }
1726
1727 #[test]
1728 fn str_shared_ref_various() {
1729 for [a, b] in various_boxed_strs() {
1730 assert_str_properties(a.shared_ref(), b.shared_ref())
1731 }
1732 }
1733
1734 fn assert_slice_mut_properties(s1: &mut SlimSliceMut<'_, u8>, s2: &mut SlimSliceMut<'_, u8>) {
1735 let a: &SlimSliceMut<'_, u8> = s1;
1736 let b: &SlimSliceMut<'_, u8> = s2;
1737
1738 assert_eq!(a.deref(), TEST_SLICE);
1739 assert_eq!(SlimSliceBox::from(a).clone().deref(), TEST_SLICE);
1740 assert_eq!(b.deref(), TEST_SLICE2);
1741
1742 assert_eq!(<Vec<u8>>::from(a), TEST_SLICE);
1743 assert_eq!(<Box<[u8]>>::from(a).deref(), TEST_SLICE);
1744 assert_eq!(<SlimSliceBox<u8>>::from(a).deref(), TEST_SLICE);
1745 assert_eq!(<Vec<u8>>::from(<SlimSliceBox<u8>>::from(a)).deref(), TEST_SLICE);
1746
1747 general_properties(a, b, TEST_SLICE, TEST_SLICE2);
1748
1749 s1.deref_mut().make_ascii_uppercase();
1750 let mut upper = TEST_SLICE.to_owned();
1751 upper.iter_mut().for_each(|x| x.make_ascii_uppercase());
1752 assert_eq!(&**s1, upper);
1753 }
1754
1755 #[test]
1756 fn slice_mut_call() {
1757 let [mut s1, mut s2] = test_slices();
1758 let s1 = &mut from_slice_mut(s1.as_mut());
1759 let s2 = &mut from_slice_mut(s2.as_mut());
1760 assert_slice_mut_properties(s1, s2);
1761 }
1762
1763 #[test]
1764 fn slice_mut_try_into() {
1765 let [mut s1, mut s2] = test_slices();
1766 let s1: &mut SlimSliceMut<u8> = &mut s1.deref_mut().try_into().unwrap();
1767 let s2: &mut SlimSliceMut<u8> = &mut s2.deref_mut().try_into().unwrap();
1768 assert_slice_mut_properties(s1, s2);
1769 }
1770
1771 #[test]
1772 fn slice_mut_exclusive_ref_various() {
1773 for [mut a, mut b] in various_boxed_slices() {
1774 assert_slice_mut_properties(a.exclusive_ref(), b.exclusive_ref());
1775 }
1776 }
1777
1778 fn assert_slice_properties(a: &SlimSlice<'_, u8>, b: &SlimSlice<'_, u8>) {
1779 assert_eq!(a.deref(), TEST_SLICE);
1780 assert_eq!(SlimSliceBox::from(a).clone().deref(), TEST_SLICE);
1781 assert_eq!(b.deref(), TEST_SLICE2);
1782
1783 assert_eq!(<Vec<u8>>::from(a), TEST_SLICE);
1784 assert_eq!(<Box<[u8]>>::from(a).deref(), TEST_SLICE);
1785 assert_eq!(<SlimSliceBox<u8>>::from(a).deref(), TEST_SLICE);
1786 assert_eq!(<Vec<u8>>::from(<SlimSliceBox<u8>>::from(a)).deref(), TEST_SLICE);
1787
1788 general_properties(a, b, TEST_SLICE, TEST_SLICE2);
1789 }
1790
1791 #[test]
1792 fn slice_call() {
1793 let [s1, s2] = test_slices();
1794 assert_slice_properties(&from_slice(&s1), &from_slice(&s2));
1795 }
1796
1797 #[test]
1798 fn slice_try_into() {
1799 let [s1, s2] = test_slices();
1800 let s1: &SlimSlice<u8> = &s1.deref().try_into().unwrap();
1801 let s2: &SlimSlice<u8> = &s2.deref().try_into().unwrap();
1802 assert_slice_properties(s1, s2);
1803 }
1804
1805 #[test]
1806 fn slice_shared_ref_various() {
1807 for [a, b] in various_boxed_slices() {
1808 assert_slice_properties(a.shared_ref(), b.shared_ref())
1809 }
1810 }
1811}