1use alloc::{borrow::Cow, boxed::Box, string::String, vec::Vec};
2use core::{mem, ptr, ptr::NonNull};
3
4use crate::error::TryReserveError;
5
6pub trait Buffer<T>: Send + 'static {
7 fn as_slice(&self) -> &[T];
8
9 #[doc(hidden)]
10 #[inline(always)]
11 fn is_array(&self) -> bool {
12 false
13 }
14
15 #[doc(hidden)]
16 #[inline(always)]
17 fn try_into_static(self) -> Result<&'static [T], Self>
18 where
19 Self: Sized,
20 {
21 Err(self)
22 }
23
24 #[doc(hidden)]
25 #[inline(always)]
26 fn try_into_vec(self) -> Result<Vec<T>, Self>
27 where
28 Self: Sized,
29 {
30 Err(self)
31 }
32}
33
34impl<T: Send + Sync + 'static> Buffer<T> for &'static [T] {
35 fn as_slice(&self) -> &[T] {
36 self
37 }
38
39 #[inline(always)]
40 fn try_into_static(self) -> Result<&'static [T], Self>
41 where
42 Self: Sized,
43 {
44 Ok(self)
45 }
46}
47
48impl<T: Send + Sync + 'static, const N: usize> Buffer<T> for [T; N] {
49 #[inline]
50 fn as_slice(&self) -> &[T] {
51 self
52 }
53
54 #[inline]
55 fn is_array(&self) -> bool {
56 true
57 }
58}
59
60impl<T: Send + Sync + 'static, const N: usize> Buffer<T> for &'static [T; N] {
61 #[inline]
62 fn as_slice(&self) -> &[T] {
63 *self
64 }
65
66 #[inline(always)]
67 fn try_into_static(self) -> Result<&'static [T], Self>
68 where
69 Self: Sized,
70 {
71 Ok(self)
72 }
73}
74
75impl<T: Send + Sync + 'static> Buffer<T> for Box<[T]> {
76 #[inline]
77 fn as_slice(&self) -> &[T] {
78 self
79 }
80
81 #[inline(always)]
82 fn try_into_vec(self) -> Result<Vec<T>, Self>
83 where
84 Self: Sized,
85 {
86 Ok(self.into_vec())
87 }
88}
89
90impl<T: Send + Sync + 'static> Buffer<T> for Vec<T> {
91 #[inline]
92 fn as_slice(&self) -> &[T] {
93 self
94 }
95
96 #[inline(always)]
97 fn try_into_vec(self) -> Result<Vec<T>, Self>
98 where
99 Self: Sized,
100 {
101 Ok(self)
102 }
103}
104
105impl<T: Clone + Send + Sync + 'static> Buffer<T> for Cow<'static, [T]> {
106 #[inline]
107 fn as_slice(&self) -> &[T] {
108 self
109 }
110
111 #[inline(always)]
112 fn try_into_static(self) -> Result<&'static [T], Self>
113 where
114 Self: Sized,
115 {
116 match self {
117 Cow::Borrowed(s) => Ok(s),
118 cow => Err(cow),
119 }
120 }
121
122 #[inline(always)]
123 fn try_into_vec(self) -> Result<Vec<T>, Self>
124 where
125 Self: Sized,
126 {
127 match self {
128 Cow::Owned(vec) => Ok(vec),
129 cow => Err(cow),
130 }
131 }
132}
133
134#[cfg(not(feature = "portable-atomic"))]
135impl<T: Send + Sync + 'static> Buffer<T> for alloc::sync::Arc<[T]> {
136 #[inline]
137 fn as_slice(&self) -> &[T] {
138 self
139 }
140}
141
142#[allow(clippy::len_without_is_empty)]
152pub unsafe trait BufferMut<T>: Buffer<T> {
153 fn as_mut_ptr(&mut self) -> NonNull<T>;
154
155 fn len(&self) -> usize;
156
157 fn capacity(&self) -> usize;
158
159 unsafe fn set_len(&mut self, len: usize) -> bool;
164
165 fn reserve(&mut self, _additional: usize) -> bool;
166}
167
168unsafe impl<T: Send + Sync + 'static> BufferMut<T> for Vec<T> {
169 #[inline]
170 fn as_mut_ptr(&mut self) -> NonNull<T> {
171 NonNull::new(self.as_mut_ptr()).unwrap()
172 }
173
174 #[inline]
175 fn len(&self) -> usize {
176 self.len()
177 }
178
179 #[inline]
180 fn capacity(&self) -> usize {
181 self.capacity()
182 }
183
184 #[inline]
185 unsafe fn set_len(&mut self, len: usize) -> bool {
186 unsafe { self.set_len(len) };
188 true
189 }
190
191 #[inline]
192 fn reserve(&mut self, additional: usize) -> bool {
193 self.reserve(additional);
194 true
195 }
196}
197
198unsafe impl<T: Send + Sync + 'static, const N: usize> BufferMut<T> for [T; N] {
199 #[inline]
200 fn as_mut_ptr(&mut self) -> NonNull<T> {
201 NonNull::new(self.as_mut_slice().as_mut_ptr()).unwrap()
202 }
203
204 #[inline]
205 fn len(&self) -> usize {
206 self.as_slice().len()
207 }
208
209 #[inline]
210 fn capacity(&self) -> usize {
211 self.as_slice().len()
212 }
213
214 #[inline]
215 unsafe fn set_len(&mut self, _len: usize) -> bool {
216 false
217 }
218
219 #[inline]
220 fn reserve(&mut self, _additional: usize) -> bool {
221 false
222 }
223}
224
225pub(crate) trait BufferMutExt<T>: BufferMut<T> + Sized {
226 unsafe fn shift_left(&mut self, offset: usize, length: usize) -> bool {
227 let prev_len = self.len();
228 if !unsafe { self.set_len(length) } {
229 return false;
230 }
231 let buffer_ptr = self.as_mut_ptr().as_ptr();
232 if mem::needs_drop::<T>() {
233 unsafe {
234 ptr::drop_in_place(ptr::slice_from_raw_parts_mut(buffer_ptr, offset));
235 if prev_len > offset + length {
236 ptr::drop_in_place(ptr::slice_from_raw_parts_mut(
237 buffer_ptr.add(offset + length),
238 prev_len - offset - length,
239 ));
240 }
241 }
242 }
243 if offset >= length {
244 unsafe { ptr::copy_nonoverlapping(buffer_ptr.add(offset), buffer_ptr, length) };
245 } else {
246 unsafe { ptr::copy(buffer_ptr.add(offset), buffer_ptr, length) };
247 }
248 true
249 }
250
251 unsafe fn try_reclaim(&mut self, offset: usize, length: usize, additional: usize) -> bool {
252 self.capacity() - length >= additional
253 && offset >= length
254 && unsafe { self.shift_left(offset, length) }
255 }
256
257 unsafe fn try_reclaim_or_reserve(
258 &mut self,
259 offset: usize,
260 length: usize,
261 additional: usize,
262 allocate: bool,
263 ) -> Result<usize, TryReserveError> {
264 let capacity = self.capacity();
265 if capacity - offset - length >= additional {
266 return Ok(offset);
267 }
268 if self.capacity() - length >= additional
270 && offset >= length
271 && unsafe { self.shift_left(offset, length) }
272 {
273 return Ok(0);
274 }
275 if allocate && unsafe { self.shift_left(0, offset + length) } && self.reserve(additional) {
276 Ok(offset)
277 } else {
278 Err(TryReserveError::Unsupported)
279 }
280 }
281}
282
283impl<T, B: BufferMut<T>> BufferMutExt<T> for B {}
284
285pub trait StringBuffer: Send + 'static {
286 fn as_str(&self) -> &str;
287
288 #[doc(hidden)]
289 #[inline(always)]
290 fn try_into_static(self) -> Result<&'static str, Self>
291 where
292 Self: Sized,
293 {
294 Err(self)
295 }
296
297 #[doc(hidden)]
298 #[inline(always)]
299 fn try_into_string(self) -> Result<String, Self>
300 where
301 Self: Sized,
302 {
303 Err(self)
304 }
305}
306
307impl StringBuffer for &'static str {
308 #[inline]
309 fn as_str(&self) -> &str {
310 self
311 }
312
313 #[inline(always)]
314 fn try_into_static(self) -> Result<&'static str, Self>
315 where
316 Self: Sized,
317 {
318 Ok(self)
319 }
320}
321
322impl StringBuffer for Box<str> {
323 #[inline]
324 fn as_str(&self) -> &str {
325 self
326 }
327
328 #[inline(always)]
329 fn try_into_string(self) -> Result<String, Self>
330 where
331 Self: Sized,
332 {
333 Ok(self.into_string())
334 }
335}
336
337impl StringBuffer for String {
338 #[inline]
339 fn as_str(&self) -> &str {
340 self
341 }
342
343 #[inline(always)]
344 fn try_into_string(self) -> Result<String, Self>
345 where
346 Self: Sized,
347 {
348 Ok(self)
349 }
350}
351
352impl StringBuffer for Cow<'static, str> {
353 #[inline]
354 fn as_str(&self) -> &str {
355 self
356 }
357
358 #[inline(always)]
359 fn try_into_static(self) -> Result<&'static str, Self>
360 where
361 Self: Sized,
362 {
363 match self {
364 Cow::Borrowed(s) => Ok(s),
365 cow => Err(cow),
366 }
367 }
368
369 #[inline(always)]
370 fn try_into_string(self) -> Result<String, Self>
371 where
372 Self: Sized,
373 {
374 match self {
375 Cow::Owned(s) => Ok(s),
376 cow => Err(cow),
377 }
378 }
379}
380
381pub trait BorrowMetadata {
382 type Metadata: ?Sized + Sync + 'static;
383
384 fn borrow_metadata(&self) -> &Self::Metadata;
385}