1#![allow(rustdoc::redundant_explicit_links)] #![no_std]
71#![cfg_attr(not(feature = "ptr_meta"), feature(ptr_metadata))]
72#![cfg_attr(not(feature = "ptr_meta"), feature(unsize))]
73extern crate alloc;
74
75pub mod iters;
76#[cfg_attr(feature = "ptr_meta", path = "ptr.stable.rs")]
77#[cfg_attr(not(feature = "ptr_meta"), path = "ptr.nightly.rs")]
78mod ptr;
79pub mod types;
80
81use core::alloc::Layout;
82use core::mem::MaybeUninit;
83use core::ptr::NonNull;
84
85#[cfg(feature = "ptr_meta")]
86pub use ::ptr_meta;
87
88use crate::types::ListType;
89use crate::types::ListTypeRev;
90
91pub unsafe trait FromImpl<T> {
102 fn from_impl(value: &T) -> &Self;
103 fn from_impl_mut(value: &mut T) -> &mut Self;
104}
105
106pub struct DynList<T, Typ = types::DoubleLinked>
110where
111 T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
112 Typ: ListType<T>,
113{
114 data: NonNull<MaybeUninit<u8>>,
116 end: usize,
118 capacity: usize,
120 typ: Typ,
121 _pd: core::marker::PhantomData<(T::Metadata, T)>,
122}
123
124impl<T, Typ> DynList<T, Typ>
125where
126 T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
127 Typ: ListType<T>,
128{
129 pub fn new() -> Self {
133 let typ = Typ::default();
134 Self {
135 data: NonNull::without_provenance(typ.starting_align().try_into().unwrap()),
136 end: 0,
137 capacity: 0,
138 typ: Typ::default(),
139 _pd: Default::default(),
140 }
141 }
142
143 pub fn len(&self) -> usize {
145 self.typ.num_items()
146 }
147
148 pub fn is_empty(&self) -> bool {
150 self.end == 0
151 }
152
153 unsafe fn realloc_to(&mut self, new_capacity: usize) {
154 let old_layout =
155 Layout::from_size_align(self.capacity, Layout::new::<T::Metadata>().align()).unwrap();
156 let new_layout =
157 Layout::from_size_align(new_capacity, Layout::new::<T::Metadata>().align())
158 .expect("allocation too large");
159
160 let new_ptr = if new_capacity == 0 {
161 if self.capacity != 0 {
162 unsafe {
163 alloc::alloc::dealloc(self.data.cast().as_ptr(), old_layout);
164 }
165 }
166 core::ptr::without_provenance_mut(self.typ.starting_align())
167 } else if self.capacity == 0 {
168 unsafe { alloc::alloc::alloc(new_layout) }
169 } else {
170 unsafe { alloc::alloc::realloc(self.data.cast().as_ptr(), old_layout, new_capacity) }
171 };
172
173 self.data = NonNull::new(new_ptr as *mut _)
174 .unwrap_or_else(|| alloc::alloc::handle_alloc_error(new_layout));
175 self.capacity = new_capacity;
176 }
177
178 fn ensure_capacity(&mut self, additional: usize) {
179 if self.end + additional > self.capacity {
180 let new_cap = self
181 .end
182 .checked_add(additional)
183 .and_then(|v| v.checked_mul(2))
184 .expect("Allocation too large");
185 unsafe { self.realloc_to(new_cap) };
186 }
187 debug_assert!(self.end + additional <= self.capacity);
188 }
189
190 pub unsafe fn push_ptr(&mut self, value: *mut T) {
199 unsafe {
200 let size = self.typ.entry_size(Layout::for_value(&*value));
201 self.ensure_capacity(size);
202 self.typ.write_entry(self.data.as_ptr(), self.end, value);
203 self.end += size;
204 }
205 }
206
207 pub fn push_boxed(&mut self, value: alloc::boxed::Box<T>) {
212 unsafe {
213 let layout = Layout::for_value(&*value);
214 let ptr = alloc::boxed::Box::into_raw(value);
215 self.push_ptr(ptr);
216 alloc::alloc::dealloc(ptr as *mut _, layout);
217 }
218 }
219
220 pub fn push<U>(&mut self, value: U)
228 where
229 T: FromImpl<U>,
230 {
231 unsafe {
232 let mut value = MaybeUninit::new(value);
233 let ptr = FromImpl::from_impl_mut(value.assume_init_mut()) as *mut T;
234 self.push_ptr(ptr);
235 }
236 }
237
238 pub fn extend_from_other<Typ2>(&mut self, other: DynList<T, Typ2>)
240 where
241 Typ2: ListType<T>,
242 {
243 for p in other.into_ptrs_iter() {
244 unsafe {
245 self.push_ptr(p);
246 }
247 }
248 }
249
250 pub fn clear(&mut self) {
254 if let Some(c) = self.cursor() {
255 c.drop_after();
256 }
257 }
258
259 pub fn shrink_to_fit(&mut self) {
261 unsafe {
262 self.realloc_to(self.end);
263 }
264 }
265
266 pub fn iter<'a>(&'a self) -> iters::Iter<'a, T, Typ> {
268 iters::Iter {
269 offset: 0,
270 index: 0,
271 rev_index: self.typ.num_items(),
272 rev_offset: self.end,
273 list: self,
274 }
275 }
276
277 pub fn iter_mut<'a>(&'a mut self) -> iters::IterMut<'a, T, Typ> {
284 iters::IterMut {
285 offset: 0,
286 index: 0,
287 rev_index: self.typ.num_items(),
288 rev_offset: self.end,
289 list: self,
290 }
291 }
292
293 pub fn into_ptrs_iter(self) -> iters::IntoPtrsIter<T, Typ> {
302 iters::IntoPtrsIter {
303 list: self,
304 offset: 0,
305 index: 0,
306 }
307 }
308
309 pub fn into_box_iter(self) -> iters::IntoBoxedIter<T, Typ> {
311 iters::IntoBoxedIter {
312 inner: self.into_ptrs_iter(),
313 }
314 }
315
316 pub fn cursor<'a>(&'a mut self) -> Option<iters::Cursor<'a, T, Typ>> {
323 if self.is_empty() {
324 return None;
325 }
326 Some(iters::Cursor {
327 offset: 0,
328 index: 0,
329 list: self,
330 })
331 }
332}
333
334impl<T, Typ> DynList<T, Typ>
335where
336 T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
337 Typ: ListTypeRev<T>,
338{
339 pub fn cursor_end<'a>(&'a mut self) -> Option<iters::Cursor<'a, T, Typ>> {
343 if self.is_empty() {
344 return None;
345 }
346 let mut cursor = iters::Cursor {
347 offset: self.end,
348 index: self.typ.num_items(),
349 list: self,
350 };
351 cursor.move_prev();
352 Some(cursor)
353 }
354}
355
356unsafe impl<T, Typ> Send for DynList<T, Typ>
357where
358 T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + Send + ?Sized,
359 Typ: ListType<T> + Send,
360{
361}
362unsafe impl<T, Typ> Sync for DynList<T, Typ>
363where
364 T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + Sync + ?Sized,
365 Typ: ListType<T> + Sync,
366{
367}
368
369impl<T, Typ> core::ops::Drop for DynList<T, Typ>
370where
371 T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
372 Typ: ListType<T>,
373{
374 fn drop(&mut self) {
375 self.clear();
376 unsafe {
377 self.realloc_to(0);
378 }
379 }
380}
381
382impl<T, Typ> Default for DynList<T, Typ>
383where
384 T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + ?Sized,
385 Typ: ListType<T>,
386{
387 fn default() -> Self {
388 Self::new()
389 }
390}
391
392impl<U, T, Typ> Extend<U> for DynList<T, Typ>
393where
394 T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + FromImpl<U> + ?Sized,
395 Typ: ListType<T>,
396{
397 fn extend<I: IntoIterator<Item = U>>(&mut self, iter: I) {
398 let iter = iter.into_iter();
399 let single_size = self.typ.entry_size(Layout::new::<U>());
401 self.ensure_capacity(iter.size_hint().0.saturating_mul(single_size));
402 for v in iter {
404 self.push(v);
405 }
406 }
407}
408
409impl<T, Typ> core::fmt::Debug for DynList<T, Typ>
410where
411 T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + core::fmt::Debug + ?Sized,
412 Typ: ListType<T>,
413{
414 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
415 f.debug_list().entries(self.iter()).finish()
416 }
417}
418
419impl<T, Typ1, U, Typ2> PartialEq<DynList<U, Typ2>> for DynList<T, Typ1>
420where
421 T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + PartialEq<U> + ?Sized,
422 U: ptr::Pointee<Metadata = ptr::DynMetadata<U>> + ?Sized,
423 Typ1: ListType<T>,
424 Typ2: ListType<U>,
425{
426 fn eq(&self, other: &DynList<U, Typ2>) -> bool {
427 let mut i1 = self.iter();
428 let mut i2 = other.iter();
429 while let Some(v1) = i1.next() {
430 let Some(v2) = i2.next() else { return false };
431 if *v1 != *v2 {
432 return false;
433 }
434 }
435 i2.next().is_none()
436 }
437}
438
439impl<T, Typ> Eq for DynList<T, Typ>
440where
441 T: ptr::Pointee<Metadata = ptr::DynMetadata<T>> + Eq + ?Sized,
442 Typ: ListType<T>,
443{
444}