1pub(crate) use internal::Beef;
2pub(crate) use internal::Capacity;
3
4pub(crate) mod internal {
5 use alloc::borrow::ToOwned;
6 use alloc::string::String;
7 use alloc::vec::Vec;
8 use core::mem::ManuallyDrop;
9 use core::ptr::{slice_from_raw_parts, NonNull};
10
11 pub trait Capacity {
12 type Field: Copy;
13 type NonZero: Copy;
14
15 fn len(fat: usize) -> usize;
16
17 fn empty(len: usize) -> (usize, Self::Field);
18
19 fn store(len: usize, capacity: usize) -> (usize, Self::Field);
20
21 fn unpack(fat: usize, capacity: Self::NonZero) -> (usize, usize);
22
23 fn maybe(fat: usize, capacity: Self::Field) -> Option<Self::NonZero>;
24 }
25
26 pub unsafe trait Beef: ToOwned {
35 type PointerT;
36
37 fn ref_into_parts<U>(&self) -> (NonNull<Self::PointerT>, usize, U::Field)
38 where
39 U: Capacity;
40
41 unsafe fn ref_from_parts<U>(ptr: NonNull<Self::PointerT>, len: usize) -> *const Self
42 where
43 U: Capacity;
44
45 fn owned_into_parts<U>(owned: Self::Owned) -> (NonNull<Self::PointerT>, usize, U::Field)
48 where
49 U: Capacity;
50
51 unsafe fn owned_from_parts<U>(
54 ptr: NonNull<Self::PointerT>,
55 fat: usize,
56 capacity: U::NonZero,
57 ) -> Self::Owned
58 where
59 U: Capacity;
60 }
61
62 unsafe impl Beef for str {
63 type PointerT = u8;
64
65 #[inline]
66 fn ref_into_parts<U>(&self) -> (NonNull<u8>, usize, U::Field)
67 where
68 U: Capacity,
69 {
70 let (fat, cap) = U::empty(self.len());
71
72 (
77 unsafe { NonNull::new_unchecked(self.as_ptr() as *mut u8) },
78 fat,
79 cap,
80 )
81 }
82
83 #[inline]
84 unsafe fn ref_from_parts<U>(ptr: NonNull<u8>, fat: usize) -> *const str
85 where
86 U: Capacity,
87 {
88 slice_from_raw_parts(ptr.as_ptr(), U::len(fat)) as *const str
89 }
90
91 #[inline]
92 fn owned_into_parts<U>(owned: String) -> (NonNull<u8>, usize, U::Field)
93 where
94 U: Capacity,
95 {
96 let mut owned = ManuallyDrop::new(owned.into_bytes());
100 let (fat, cap) = U::store(owned.len(), owned.capacity());
101
102 (
103 unsafe { NonNull::new_unchecked(owned.as_mut_ptr()) },
104 fat,
105 cap,
106 )
107 }
108
109 #[inline]
110 unsafe fn owned_from_parts<U>(ptr: NonNull<u8>, fat: usize, capacity: U::NonZero) -> String
111 where
112 U: Capacity,
113 {
114 let (len, cap) = U::unpack(fat, capacity);
115
116 String::from_utf8_unchecked(Vec::from_raw_parts(ptr.as_ptr(), len, cap))
117 }
118 }
119
120 unsafe impl<T: Clone> Beef for [T] {
121 type PointerT = T;
122
123 #[inline]
124 fn ref_into_parts<U>(&self) -> (NonNull<T>, usize, U::Field)
125 where
126 U: Capacity,
127 {
128 let (fat, cap) = U::empty(self.len());
129
130 (
135 unsafe { NonNull::new_unchecked(self.as_ptr() as *mut T) },
136 fat,
137 cap,
138 )
139 }
140
141 #[inline]
142 unsafe fn ref_from_parts<U>(ptr: NonNull<T>, fat: usize) -> *const [T]
143 where
144 U: Capacity,
145 {
146 slice_from_raw_parts(ptr.as_ptr(), U::len(fat))
147 }
148
149 #[inline]
150 fn owned_into_parts<U>(owned: Vec<T>) -> (NonNull<T>, usize, U::Field)
151 where
152 U: Capacity,
153 {
154 let mut owned = ManuallyDrop::new(owned);
156 let (fat, cap) = U::store(owned.len(), owned.capacity());
157
158 (
159 unsafe { NonNull::new_unchecked(owned.as_mut_ptr()) },
160 fat,
161 cap,
162 )
163 }
164
165 #[inline]
166 unsafe fn owned_from_parts<U>(ptr: NonNull<T>, fat: usize, capacity: U::NonZero) -> Vec<T>
167 where
168 U: Capacity,
169 {
170 let (len, cap) = U::unpack(fat, capacity);
171
172 Vec::from_raw_parts(ptr.as_ptr(), len, cap)
173 }
174 }
175}