1use alloc::{string::String, vec::Vec};
6use core::{
7 borrow::Borrow,
8 cmp, fmt,
9 hash::{Hash, Hasher},
10 marker::PhantomData,
11 mem::{size_of, ManuallyDrop, MaybeUninit},
12 ops::{Deref, RangeBounds},
13 ptr::addr_of,
14 slice,
15};
16
17use either::Either;
18pub(crate) use private::InlinedLayout;
19
20#[cfg(feature = "oom-handling")]
21use crate::layout::AnyBufferLayout;
22#[cfg(not(feature = "oom-handling"))]
23use crate::layout::CloneNoAllocLayout;
24use crate::{
25 buffer::{Emptyable, Slice, SliceExt, Subsliceable},
26 error::AllocError,
27 layout::{ArcLayout, BoxedSliceLayout, DefaultLayout, Layout, StaticLayout, VecLayout},
28 msrv::ptr,
29 utils::{debug_slice, lower_hex, panic_out_of_range, range_offset_len, upper_hex},
30 ArcSlice,
31};
32
33const INLINED_FLAG: u8 = 0x80;
34
35mod private {
36 #[allow(clippy::missing_safety_doc)]
37 pub unsafe trait InlinedLayout {
38 const LEN: usize;
39 type Data: Copy;
40 const UNINIT: Self::Data;
41 }
42}
43
44const _3_WORDS_LEN: usize = 3 * size_of::<usize>() - 2;
45const _4_WORDS_LEN: usize = 4 * size_of::<usize>() - 2;
46
47unsafe impl<const ANY_BUFFER: bool, const STATIC: bool> InlinedLayout
48 for ArcLayout<ANY_BUFFER, STATIC>
49{
50 const LEN: usize = _3_WORDS_LEN;
51 type Data = [MaybeUninit<u8>; _3_WORDS_LEN];
52 const UNINIT: Self::Data = [MaybeUninit::uninit(); _3_WORDS_LEN];
53}
54
55unsafe impl InlinedLayout for BoxedSliceLayout {
56 const LEN: usize = _3_WORDS_LEN;
57 type Data = [MaybeUninit<u8>; _3_WORDS_LEN];
58 const UNINIT: Self::Data = [MaybeUninit::uninit(); _3_WORDS_LEN];
59}
60
61unsafe impl InlinedLayout for VecLayout {
62 const LEN: usize = _4_WORDS_LEN;
63 type Data = [MaybeUninit<u8>; _4_WORDS_LEN];
64 const UNINIT: Self::Data = [MaybeUninit::uninit(); _4_WORDS_LEN];
65}
66
67#[cfg(feature = "raw-buffer")]
68unsafe impl InlinedLayout for crate::layout::RawLayout {
69 const LEN: usize = _4_WORDS_LEN;
70 type Data = [MaybeUninit<u8>; _4_WORDS_LEN];
71 const UNINIT: Self::Data = [MaybeUninit::uninit(); _4_WORDS_LEN];
72}
73
74#[repr(C)]
84pub struct SmallSlice<S: Slice<Item = u8> + ?Sized, L: Layout = DefaultLayout> {
85 #[cfg(target_endian = "big")]
86 tagged_length: u8,
87 data: <L as InlinedLayout>::Data,
88 offset: u8,
89 #[cfg(target_endian = "little")]
90 tagged_length: u8,
91 _phantom: PhantomData<S>,
92}
93
94impl<S: Slice<Item = u8> + ?Sized, L: Layout> SmallSlice<S, L> {
95 const MAX_LEN: usize = L::LEN;
96
97 pub const EMPTY: Self = Self {
99 data: L::UNINIT,
100 offset: 0,
101 tagged_length: INLINED_FLAG,
102 _phantom: PhantomData,
103 };
104
105 pub fn new(slice: &S) -> Option<Self> {
116 if slice.len() > Self::MAX_LEN {
117 return None;
118 }
119 let mut this = Self {
120 data: L::UNINIT,
121 offset: 0,
122 tagged_length: slice.len() as u8 | INLINED_FLAG,
123 _phantom: PhantomData,
124 };
125 let data = ptr::from_mut(&mut this.data).cast::<u8>();
126 unsafe { ptr::copy_nonoverlapping(slice.as_ptr().as_ptr(), data, slice.len()) }
127 Some(this)
128 }
129
130 #[inline(always)]
131 const fn is_inlined(this: *const Self) -> bool {
132 unsafe { (*addr_of!((*this).tagged_length)) & INLINED_FLAG != 0 }
133 }
134
135 pub const fn len(&self) -> usize {
146 (self.tagged_length & !INLINED_FLAG) as usize
147 }
148
149 pub const fn is_empty(&self) -> bool {
163 self.len() == 0
164 }
165
166 pub const fn as_ptr(&self) -> *const u8 {
170 let data = ptr::from_ref(&self.data).cast::<u8>();
171 unsafe { data.add(self.offset as usize) }
172 }
173
174 pub fn advance(&mut self, offset: usize)
190 where
191 S: Subsliceable,
192 {
193 if offset > self.len() {
194 panic_out_of_range()
195 }
196 unsafe { self.check_advance(offset) };
197 self.offset += offset as u8;
198 self.tagged_length -= offset as u8;
199 }
200
201 pub fn truncate(&mut self, len: usize)
213 where
214 S: Subsliceable,
215 {
216 if len < self.len() {
217 unsafe { self.check_truncate(len) };
218 self.tagged_length = len as u8 | INLINED_FLAG;
219 }
220 }
221
222 pub fn subslice(&self, range: impl RangeBounds<usize>) -> Self
234 where
235 S: Subsliceable,
236 {
237 let (offset, len) = range_offset_len(self.deref(), range);
238 Self {
239 offset: self.offset + offset as u8,
240 tagged_length: len as u8 | INLINED_FLAG,
241 ..*self
242 }
243 }
244}
245
246impl<S: Slice<Item = u8> + ?Sized, L: Layout> Clone for SmallSlice<S, L> {
247 fn clone(&self) -> Self {
248 *self
249 }
250}
251
252impl<S: Slice<Item = u8> + ?Sized, L: Layout> Copy for SmallSlice<S, L> {}
253
254impl<S: Slice<Item = u8> + ?Sized, L: Layout> Deref for SmallSlice<S, L> {
255 type Target = S;
256
257 fn deref(&self) -> &Self::Target {
258 unsafe { S::from_slice_unchecked(slice::from_raw_parts(self.as_ptr(), self.len())) }
259 }
260}
261
262impl<S: Slice<Item = u8> + ?Sized, L: Layout> AsRef<S> for SmallSlice<S, L> {
263 fn as_ref(&self) -> &S {
264 self
265 }
266}
267
268impl<S: Hash + Slice<Item = u8> + ?Sized, L: Layout> Hash for SmallSlice<S, L> {
269 fn hash<H>(&self, state: &mut H)
270 where
271 H: Hasher,
272 {
273 self.deref().hash(state);
274 }
275}
276
277impl<S: Slice<Item = u8> + ?Sized, L: Layout> Borrow<S> for SmallSlice<S, L> {
278 fn borrow(&self) -> &S {
279 self
280 }
281}
282
283impl<S: Emptyable<Item = u8> + ?Sized, L: Layout> Default for SmallSlice<S, L> {
284 fn default() -> Self {
285 Self::EMPTY
286 }
287}
288
289impl<S: fmt::Debug + Slice<Item = u8> + ?Sized, L: Layout> fmt::Debug for SmallSlice<S, L> {
290 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291 debug_slice(self.deref(), f)
292 }
293}
294
295impl<S: fmt::Display + Slice<Item = u8> + ?Sized, L: Layout> fmt::Display for SmallSlice<S, L> {
296 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
297 self.deref().fmt(f)
298 }
299}
300
301impl<S: Slice<Item = u8> + ?Sized, L: Layout> fmt::LowerHex for SmallSlice<S, L> {
302 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303 lower_hex(self.to_slice(), f)
304 }
305}
306
307impl<S: Slice<Item = u8> + ?Sized, L: Layout> fmt::UpperHex for SmallSlice<S, L> {
308 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
309 upper_hex(self.to_slice(), f)
310 }
311}
312
313impl<S: PartialEq + Slice<Item = u8> + ?Sized, L: Layout> PartialEq for SmallSlice<S, L> {
314 fn eq(&self, other: &SmallSlice<S, L>) -> bool {
315 **self == **other
316 }
317}
318
319impl<S: PartialEq + Slice<Item = u8> + ?Sized, L: Layout> Eq for SmallSlice<S, L> {}
320
321impl<S: PartialOrd + Slice<Item = u8> + ?Sized, L: Layout> PartialOrd for SmallSlice<S, L> {
322 fn partial_cmp(&self, other: &SmallSlice<S, L>) -> Option<cmp::Ordering> {
323 self.deref().partial_cmp(other.deref())
324 }
325}
326
327impl<S: Ord + Slice<Item = u8> + ?Sized, L: Layout> Ord for SmallSlice<S, L> {
328 fn cmp(&self, other: &SmallSlice<S, L>) -> cmp::Ordering {
329 self.deref().cmp(other.deref())
330 }
331}
332
333impl<S: PartialEq + Slice<Item = u8> + ?Sized, L: Layout> PartialEq<S> for SmallSlice<S, L> {
334 fn eq(&self, other: &S) -> bool {
335 self.deref() == other
336 }
337}
338
339impl<'a, S: PartialEq + Slice<Item = u8> + ?Sized, L: Layout> PartialEq<&'a S>
340 for SmallSlice<S, L>
341{
342 fn eq(&self, other: &&'a S) -> bool {
343 self.deref() == *other
344 }
345}
346
347impl<L: Layout, const N: usize> PartialEq<[u8; N]> for SmallSlice<[u8], L> {
348 fn eq(&self, other: &[u8; N]) -> bool {
349 *other == **self
350 }
351}
352
353impl<'a, L: Layout, const N: usize> PartialEq<&'a [u8; N]> for SmallSlice<[u8], L> {
354 fn eq(&self, other: &&'a [u8; N]) -> bool {
355 **other == **self
356 }
357}
358
359impl<L: Layout, const N: usize> PartialEq<SmallSlice<[u8], L>> for [u8; N] {
360 fn eq(&self, other: &SmallSlice<[u8], L>) -> bool {
361 **other == *self
362 }
363}
364
365impl<L: Layout> PartialEq<SmallSlice<[u8], L>> for [u8] {
366 fn eq(&self, other: &SmallSlice<[u8], L>) -> bool {
367 **other == *self
368 }
369}
370
371impl<L: Layout> PartialEq<SmallSlice<str, L>> for str {
372 fn eq(&self, other: &SmallSlice<str, L>) -> bool {
373 **other == *self
374 }
375}
376
377impl<L: Layout> PartialEq<Vec<u8>> for SmallSlice<[u8], L> {
378 fn eq(&self, other: &Vec<u8>) -> bool {
379 **self == **other
380 }
381}
382
383impl<L: Layout> PartialEq<String> for SmallSlice<str, L> {
384 fn eq(&self, other: &String) -> bool {
385 **self == **other
386 }
387}
388
389impl<L: Layout> PartialEq<SmallSlice<[u8], L>> for Vec<u8> {
390 fn eq(&self, other: &SmallSlice<[u8], L>) -> bool {
391 **self == **other
392 }
393}
394
395impl<L: Layout> PartialEq<SmallSlice<str, L>> for String {
396 fn eq(&self, other: &SmallSlice<str, L>) -> bool {
397 **self == **other
398 }
399}
400
401pub struct SmallArcSlice<S: Slice<Item = u8> + ?Sized, L: Layout = DefaultLayout>(Inner<S, L>);
409
410#[repr(C)]
411union Inner<S: Slice<Item = u8> + ?Sized, L: Layout> {
412 small: SmallSlice<S, L>,
413 arc: ManuallyDrop<ArcSlice<S, L>>,
414}
415
416impl<S: Slice<Item = u8> + ?Sized, L: Layout> SmallArcSlice<S, L> {
417 pub const fn new() -> Self {
428 Self(Inner {
429 small: SmallSlice::EMPTY,
430 })
431 }
432
433 #[cfg(feature = "oom-handling")]
450 pub fn from_slice(slice: &S) -> Self {
451 SmallSlice::new(slice).map_or_else(|| ArcSlice::from_slice(slice).into(), Into::into)
452 }
453
454 pub fn try_from_slice(slice: &S) -> Result<Self, AllocError> {
471 SmallSlice::new(slice).map_or_else(
472 || Ok(ArcSlice::try_from_slice(slice)?.into()),
473 |s| Ok(s.into()),
474 )
475 }
476
477 #[inline(always)]
493 pub fn as_either(&self) -> Either<&SmallSlice<S, L>, &ArcSlice<S, L>> {
494 if unsafe { SmallSlice::is_inlined(addr_of!(self.0.small)) } {
495 Either::Left(unsafe { &self.0.small })
496 } else {
497 Either::Right(unsafe { &*ptr::from_ref(&self.0.arc).cast() })
498 }
499 }
500
501 #[inline(always)]
517 pub fn as_either_mut(&mut self) -> Either<&mut SmallSlice<S, L>, &mut ArcSlice<S, L>> {
518 if unsafe { SmallSlice::is_inlined(addr_of!(self.0.small)) } {
519 Either::Left(unsafe { &mut self.0.small })
520 } else {
521 Either::Right(unsafe { &mut self.0.arc })
522 }
523 }
524
525 #[inline(always)]
527 pub fn into_either(self) -> Either<SmallSlice<S, L>, ArcSlice<S, L>> {
528 let mut this = ManuallyDrop::new(self);
529 if unsafe { SmallSlice::is_inlined(addr_of!(this.0.small)) } {
530 Either::Left(unsafe { this.0.small })
531 } else {
532 Either::Right(unsafe { ManuallyDrop::take(&mut this.0.arc) })
533 }
534 }
535
536 pub fn len(&self) -> usize {
547 match self.as_either() {
548 Either::Left(bytes) => bytes.len(),
549 Either::Right(bytes) => bytes.len(),
550 }
551 }
552
553 pub fn is_empty(&self) -> bool {
567 self.len() == 0
568 }
569
570 pub fn as_ptr(&self) -> *const u8 {
574 match self.as_either() {
575 Either::Left(bytes) => bytes.as_ptr(),
576 Either::Right(bytes) => bytes.start.as_ptr(),
577 }
578 }
579
580 pub fn try_clone(&self) -> Result<Self, AllocError> {
598 Ok(match self.as_either() {
599 Either::Left(bytes) => Self(Inner { small: *bytes }),
600 Either::Right(bytes) => Self(Inner {
601 arc: ManuallyDrop::new(bytes.try_clone()?),
602 }),
603 })
604 }
605
606 pub fn try_subslice(&self, range: impl RangeBounds<usize>) -> Result<Self, AllocError>
625 where
626 S: Subsliceable,
627 {
628 match self.as_either() {
629 Either::Left(bytes) => Ok(bytes.subslice(range).into()),
630 Either::Right(bytes) => Ok(bytes.try_subslice(range)?.into()),
631 }
632 }
633
634 #[doc(hidden)]
635 pub fn _advance(&mut self, cnt: usize)
636 where
637 S: Subsliceable,
638 {
639 match self.as_either_mut() {
640 Either::Left(s) => s.advance(cnt),
641 Either::Right(s) => s.advance(cnt),
642 }
643 }
644}
645
646impl<L: Layout> SmallArcSlice<[u8], L> {
647 #[cfg(feature = "oom-handling")]
662 pub fn from_array<const N: usize>(array: [u8; N]) -> Self {
663 SmallSlice::new(array.as_slice())
664 .map_or_else(|| ArcSlice::from_array(array).into(), Into::into)
665 }
666
667 pub fn try_from_array<const N: usize>(array: [u8; N]) -> Result<Self, [u8; N]> {
679 SmallSlice::new(array.as_slice()).map_or_else(
680 || Ok(ArcSlice::try_from_array(array)?.into()),
681 |a| Ok(a.into()),
682 )
683 }
684}
685
686impl<
687 S: Slice<Item = u8> + ?Sized,
688 #[cfg(feature = "oom-handling")] L: Layout,
689 #[cfg(not(feature = "oom-handling"))] L: CloneNoAllocLayout,
690 > SmallArcSlice<S, L>
691{
692 pub fn subslice(&self, range: impl RangeBounds<usize>) -> Self
704 where
705 S: Subsliceable,
706 {
707 match self.as_either() {
708 Either::Left(bytes) => bytes.subslice(range).into(),
709 Either::Right(bytes) => bytes.subslice(range).into(),
710 }
711 }
712}
713
714impl<L: StaticLayout> SmallArcSlice<[u8], L> {
715 pub const fn from_static(slice: &'static [u8]) -> SmallArcSlice<[u8], L> {
728 Self(Inner {
729 arc: ManuallyDrop::new(ArcSlice::<[u8], L>::from_static(slice)),
730 })
731 }
732}
733
734impl<L: StaticLayout> SmallArcSlice<str, L> {
735 pub const fn from_static(slice: &'static str) -> SmallArcSlice<str, L> {
748 Self(Inner {
749 arc: ManuallyDrop::new(ArcSlice::<str, L>::from_static(slice)),
750 })
751 }
752}
753
754impl<S: Slice<Item = u8> + ?Sized, L: Layout> Drop for SmallArcSlice<S, L> {
755 fn drop(&mut self) {
756 if let Either::Right(bytes) = self.as_either_mut() {
757 unsafe { ptr::drop_in_place(bytes) }
758 }
759 }
760}
761
762impl<
763 S: Slice<Item = u8> + ?Sized,
764 #[cfg(feature = "oom-handling")] L: Layout,
765 #[cfg(not(feature = "oom-handling"))] L: CloneNoAllocLayout,
766 > Clone for SmallArcSlice<S, L>
767{
768 fn clone(&self) -> Self {
769 match self.as_either() {
770 Either::Left(bytes) => Self(Inner { small: *bytes }),
771 Either::Right(bytes) => Self(Inner {
772 arc: ManuallyDrop::new(bytes.clone()),
773 }),
774 }
775 }
776}
777
778impl<S: Slice<Item = u8> + ?Sized, L: Layout> Deref for SmallArcSlice<S, L> {
779 type Target = S;
780
781 fn deref(&self) -> &Self::Target {
782 match self.as_either() {
783 Either::Left(bytes) => bytes,
784 Either::Right(bytes) => bytes,
785 }
786 }
787}
788
789impl<S: Slice<Item = u8> + ?Sized, L: Layout> AsRef<S> for SmallArcSlice<S, L> {
790 fn as_ref(&self) -> &S {
791 self
792 }
793}
794
795impl<S: Hash + Slice<Item = u8> + ?Sized, L: Layout> Hash for SmallArcSlice<S, L> {
796 fn hash<H>(&self, state: &mut H)
797 where
798 H: Hasher,
799 {
800 self.deref().hash(state);
801 }
802}
803
804impl<S: Slice<Item = u8> + ?Sized, L: Layout> Borrow<S> for SmallArcSlice<S, L> {
805 fn borrow(&self) -> &S {
806 self
807 }
808}
809
810impl<S: Emptyable<Item = u8> + ?Sized, L: Layout> Default for SmallArcSlice<S, L> {
811 fn default() -> Self {
812 Self::from(SmallSlice::default())
813 }
814}
815
816impl<S: fmt::Debug + Slice<Item = u8> + ?Sized, L: Layout> fmt::Debug for SmallArcSlice<S, L> {
817 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
818 debug_slice(self.deref(), f)
819 }
820}
821
822impl<S: fmt::Display + Slice<Item = u8> + ?Sized, L: Layout> fmt::Display for SmallArcSlice<S, L> {
823 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
824 self.deref().fmt(f)
825 }
826}
827
828impl<S: Slice<Item = u8> + ?Sized, L: Layout> fmt::LowerHex for SmallArcSlice<S, L> {
829 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
830 lower_hex(self.to_slice(), f)
831 }
832}
833
834impl<S: Slice<Item = u8> + ?Sized, L: Layout> fmt::UpperHex for SmallArcSlice<S, L> {
835 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
836 upper_hex(self.to_slice(), f)
837 }
838}
839
840impl<S: PartialEq + Slice<Item = u8> + ?Sized, L: Layout> PartialEq for SmallArcSlice<S, L> {
841 fn eq(&self, other: &SmallArcSlice<S, L>) -> bool {
842 **self == **other
843 }
844}
845
846impl<S: PartialEq + Slice<Item = u8> + ?Sized, L: Layout> Eq for SmallArcSlice<S, L> {}
847
848impl<S: PartialOrd + Slice<Item = u8> + ?Sized, L: Layout> PartialOrd for SmallArcSlice<S, L> {
849 fn partial_cmp(&self, other: &SmallArcSlice<S, L>) -> Option<cmp::Ordering> {
850 self.deref().partial_cmp(other.deref())
851 }
852}
853
854impl<S: Ord + Slice<Item = u8> + ?Sized, L: Layout> Ord for SmallArcSlice<S, L> {
855 fn cmp(&self, other: &SmallArcSlice<S, L>) -> cmp::Ordering {
856 self.deref().cmp(other.deref())
857 }
858}
859
860impl<S: PartialEq + Slice<Item = u8> + ?Sized, L: Layout> PartialEq<S> for SmallArcSlice<S, L> {
861 fn eq(&self, other: &S) -> bool {
862 self.deref() == other
863 }
864}
865
866impl<'a, S: PartialEq + Slice<Item = u8> + ?Sized, L: Layout> PartialEq<&'a S>
867 for SmallArcSlice<S, L>
868{
869 fn eq(&self, other: &&'a S) -> bool {
870 self.deref() == *other
871 }
872}
873
874impl<L: Layout, const N: usize> PartialEq<[u8; N]> for SmallArcSlice<[u8], L> {
875 fn eq(&self, other: &[u8; N]) -> bool {
876 *other == **self
877 }
878}
879
880impl<'a, L: Layout, const N: usize> PartialEq<&'a [u8; N]> for SmallArcSlice<[u8], L> {
881 fn eq(&self, other: &&'a [u8; N]) -> bool {
882 **other == **self
883 }
884}
885
886impl<L: Layout, const N: usize> PartialEq<SmallArcSlice<[u8], L>> for [u8; N] {
887 fn eq(&self, other: &SmallArcSlice<[u8], L>) -> bool {
888 **other == *self
889 }
890}
891
892impl<L: Layout> PartialEq<SmallArcSlice<[u8], L>> for [u8] {
893 fn eq(&self, other: &SmallArcSlice<[u8], L>) -> bool {
894 **other == *self
895 }
896}
897
898impl<L: Layout> PartialEq<SmallArcSlice<str, L>> for str {
899 fn eq(&self, other: &SmallArcSlice<str, L>) -> bool {
900 **other == *self
901 }
902}
903
904impl<L: Layout> PartialEq<Vec<u8>> for SmallArcSlice<[u8], L> {
905 fn eq(&self, other: &Vec<u8>) -> bool {
906 **self == **other
907 }
908}
909
910impl<L: Layout> PartialEq<String> for SmallArcSlice<str, L> {
911 fn eq(&self, other: &String) -> bool {
912 **self == **other
913 }
914}
915
916impl<L: Layout> PartialEq<SmallArcSlice<[u8], L>> for Vec<u8> {
917 fn eq(&self, other: &SmallArcSlice<[u8], L>) -> bool {
918 **self == **other
919 }
920}
921
922impl<L: Layout> PartialEq<SmallArcSlice<str, L>> for String {
923 fn eq(&self, other: &SmallArcSlice<str, L>) -> bool {
924 **self == **other
925 }
926}
927
928#[cfg(feature = "oom-handling")]
929impl<S: Slice<Item = u8> + ?Sized, L: AnyBufferLayout> From<&S> for SmallArcSlice<S, L> {
930 fn from(value: &S) -> Self {
931 Self::from_slice(value)
932 }
933}
934
935#[cfg(feature = "oom-handling")]
936impl<L: AnyBufferLayout, const N: usize> From<&[u8; N]> for SmallArcSlice<[u8], L> {
937 fn from(value: &[u8; N]) -> Self {
938 Self::from_slice(value)
939 }
940}
941
942#[cfg(feature = "oom-handling")]
943impl<L: AnyBufferLayout, const N: usize> From<[u8; N]> for SmallArcSlice<[u8], L> {
944 fn from(value: [u8; N]) -> Self {
945 Self::from_array(value)
946 }
947}
948
949#[cfg(feature = "oom-handling")]
950impl<S: Slice<Item = u8> + ?Sized, L: AnyBufferLayout> From<alloc::boxed::Box<S>>
951 for SmallArcSlice<S, L>
952{
953 fn from(value: alloc::boxed::Box<S>) -> Self {
954 ArcSlice::from(value).into()
955 }
956}
957
958#[cfg(feature = "oom-handling")]
959impl<L: AnyBufferLayout> From<Vec<u8>> for SmallArcSlice<[u8], L> {
960 fn from(value: Vec<u8>) -> Self {
961 ArcSlice::from(value).into()
962 }
963}
964
965#[cfg(feature = "oom-handling")]
966impl<L: AnyBufferLayout> From<String> for SmallArcSlice<str, L> {
967 fn from(value: String) -> Self {
968 ArcSlice::from(value).into()
969 }
970}
971
972impl<S: Slice<Item = u8> + ?Sized, L: Layout> From<SmallSlice<S, L>> for SmallArcSlice<S, L> {
973 fn from(value: SmallSlice<S, L>) -> Self {
974 Self(Inner { small: value })
975 }
976}
977
978impl<S: Slice<Item = u8> + ?Sized, L: Layout> From<ArcSlice<S, L>> for SmallArcSlice<S, L> {
979 fn from(value: ArcSlice<S, L>) -> Self {
980 Self(Inner {
981 arc: ManuallyDrop::new(value),
982 })
983 }
984}
985
986#[cfg(feature = "oom-handling")]
987impl<L: Layout> core::str::FromStr for SmallArcSlice<str, L> {
988 type Err = core::convert::Infallible;
989
990 fn from_str(s: &str) -> Result<Self, Self::Err> {
991 Ok(Self::from_slice(s))
992 }
993}
994
995pub type SmallArcBytes<L = DefaultLayout> = SmallArcSlice<[u8], L>;
997pub type SmallArcStr<L = DefaultLayout> = SmallArcSlice<str, L>;