1use core::borrow::{Borrow, BorrowMut};
2use core::ops::{Deref, DerefMut};
3use core::hash::{Hash, Hasher};
4use core::marker::PhantomData;
5use core::cmp::Ordering;
6use core::{slice, fmt};
7use core::ptr::NonNull;
8
9pub struct HeapSlice<T>(NonNull<u8>, PhantomData<T>);
11
12unsafe impl<T: Send> Send for HeapSlice<T> {}
13unsafe impl<T: Sync> Sync for HeapSlice<T> {}
14
15impl<T: Clone> From<&[T]> for HeapSlice<T> {
16 fn from(value: &[T]) -> Self {
17 if value.is_empty() {
18 return Self::default();
19 }
20
21 let align = align_of::<usize>().max(align_of::<T>());
22 let size = align + size_of_val(value);
23 unsafe {
24 let ptr = alloc::alloc::alloc(alloc::alloc::Layout::from_size_align(size, align).unwrap_unchecked());
25 (ptr as *mut usize).write(value.len());
26 let mut p = ptr.add(align) as *mut T;
27 for v in value {
28 p.write(v.clone());
29 p = p.add(1);
30 }
31 Self(NonNull::new_unchecked(ptr), PhantomData)
32 }
33 }
34}
35
36impl<T> Default for HeapSlice<T> {
37 fn default() -> Self {
38 Self(unsafe { NonNull::new_unchecked(sptr::invalid_mut(1)) }, PhantomData)
39 }
40}
41
42impl<T> Deref for HeapSlice<T> {
43 type Target = [T];
44 fn deref(&self) -> &Self::Target {
45 if self.0.as_ptr() as usize != 1 {
46 let align = align_of::<usize>().max(align_of::<T>());
47 unsafe { slice::from_raw_parts(self.0.as_ptr().add(align) as *const T, (self.0.as_ptr() as *const usize).read()) }
48 } else {
49 &[]
50 }
51 }
52}
53
54impl<T> DerefMut for HeapSlice<T> {
55 fn deref_mut(&mut self) -> &mut Self::Target {
56 if self.0.as_ptr() as usize != 1 {
57 let align = align_of::<usize>().max(align_of::<T>());
58 unsafe { slice::from_raw_parts_mut(self.0.as_ptr().add(align) as *mut T, (self.0.as_ptr() as *const usize).read()) }
59 } else {
60 &mut []
61 }
62 }
63}
64
65impl<T> Drop for HeapSlice<T> {
66 fn drop(&mut self) {
67 if self.0.as_ptr() as usize != 1 {
68 let values = &mut **self;
69 let align = align_of::<usize>().max(align_of::<T>());
70 let size = align + size_of_val(values);
71
72 unsafe {
73 for value in values.iter_mut() {
74 (value as *mut T).drop_in_place();
75 }
76 alloc::alloc::dealloc(self.0.as_ptr(), alloc::alloc::Layout::from_size_align(size, align).unwrap_unchecked());
77 }
78 }
79 }
80}
81
82impl<T> AsRef<[T]> for HeapSlice<T> {
83 fn as_ref(&self) -> &[T] {
84 self
85 }
86}
87
88impl<T> AsMut<[T]> for HeapSlice<T> {
89 fn as_mut(&mut self) -> &mut [T] {
90 self
91 }
92}
93
94impl<T> Borrow<[T]> for HeapSlice<T> {
95 fn borrow(&self) -> &[T] {
96 self
97 }
98}
99
100impl<T> BorrowMut<[T]> for HeapSlice<T> {
101 fn borrow_mut(&mut self) -> &mut [T] {
102 self
103 }
104}
105
106impl<T: Hash> Hash for HeapSlice<T> {
107 fn hash<H: Hasher>(&self, state: &mut H) {
108 (**self).hash(state)
109 }
110}
111
112impl<T: fmt::Debug> fmt::Debug for HeapSlice<T> {
113 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
114 write!(f, "{:?}", &**self)
115 }
116}
117
118impl<T: Clone> Clone for HeapSlice<T> {
119 fn clone(&self) -> Self {
120 Self::from(&**self)
121 }
122}
123
124impl<T: PartialEq, U: AsRef<[T]>> PartialEq<U> for HeapSlice<T> {
125 fn eq(&self, other: &U) -> bool {
126 (**self).eq(other.as_ref())
127 }
128}
129
130impl<T: Eq> Eq for HeapSlice<T> {}
131
132impl<T: PartialOrd, U: AsRef<[T]>> PartialOrd<U> for HeapSlice<T> {
133 fn partial_cmp(&self, other: &U) -> Option<Ordering> {
134 (**self).partial_cmp(other.as_ref())
135 }
136}
137
138impl<T: Ord> Ord for HeapSlice<T> {
139 fn cmp(&self, other: &Self) -> Ordering {
140 (**self).cmp(&**other)
141 }
142}
143
144#[test]
145fn test_basic() {
146 extern crate std;
147 use alloc::string::String;
148
149 assert_eq!(size_of::<HeapSlice<u8>>(), size_of::<usize>());
150 assert_eq!(size_of::<Option<HeapSlice<u8>>>(), size_of::<usize>());
151
152 macro_rules! assert_implements {
153 ($t:ty : $($tt:tt)*) => {{
154 fn f<T: $($tt)*>() {}
155 f::<$t>();
156 }};
157 }
158
159 assert_implements!(HeapSlice<u8>: Send + Sync + fmt::Debug + Clone + PartialEq + Eq + PartialOrd + Ord + Deref<Target = [u8]> + DerefMut + AsRef<[u8]> + AsMut<[u8]> + Borrow<[u8]> + BorrowMut<[u8]> + Hash + Default);
160
161 for content in [b"".as_slice(), b"h", b"he", b"hel", b"help", b"help me obi-wan kenobi, you're my only hope"] {
162 let mut v = HeapSlice::from(content);
163 assert_eq!(v, content);
164 assert_eq!(v.deref(), content);
165 assert_eq!(v.deref_mut(), content);
166 assert_eq!(v.as_ref(), content);
167 assert_eq!(v.as_mut(), content);
168 assert_eq!(<HeapSlice<u8> as Borrow<[u8]>>::borrow(&v), content);
169 assert_eq!(<HeapSlice<u8> as BorrowMut<[u8]>>::borrow_mut(&mut v), content);
170 if v.is_empty() {
171 assert_eq!(v.0.as_ptr() as usize, 1);
172 } else {
173 assert_ne!(v.0.as_ptr() as usize, 1);
174 assert_eq!((v.0.as_ptr() as usize) % align_of::<usize>(), 0);
175 }
176 std::thread::spawn(move || {
177 assert_eq!(v, content);
178 assert_eq!(v.deref(), content);
179 assert_eq!(v.deref_mut(), content);
180 assert_eq!(v.as_ref(), content);
181 assert_eq!(v.as_mut(), content);
182 assert_eq!(<HeapSlice<u8> as Borrow<[u8]>>::borrow(&v), content);
183 assert_eq!(<HeapSlice<u8> as BorrowMut<[u8]>>::borrow_mut(&mut v), content);
184 if v.is_empty() {
185 assert_eq!(v.0.as_ptr() as usize, 1);
186 } else {
187 assert_ne!(v.0.as_ptr() as usize, 1);
188 assert_eq!((v.0.as_ptr() as usize) % align_of::<usize>(), 0);
189 }
190 }).join().unwrap();
191 }
192
193 let vv = HeapSlice::<u8>::default();
194 assert_eq!(vv, &[]);
195 assert_eq!(vv.0.as_ptr() as usize, 1);
196
197 let x = HeapSlice::<String>::from([String::from("hello"), String::from("world")].as_slice());
198 assert_eq!(x.len(), 2);
199 assert_eq!(x[0], "hello");
200 assert_eq!(x[1], "world");
201
202 let xx = HeapSlice::<String>::default();
203 assert_eq!(xx, &[]);
204
205 let zz = HeapSlice::<u128>::from([1, 6, 3].as_slice());
206 assert_eq!(zz.len(), 3);
207 assert_eq!(zz[0], 1);
208 assert_eq!(zz[1], 6);
209 assert_eq!(zz[2], 3);
210}