Skip to content

Commit 0a064b7

Browse files
SortedLinkedList: add SortedLinkedListView, similar to VecView on top of #486
1 parent 02cc494 commit 0a064b7

File tree

2 files changed

+82
-24
lines changed

2 files changed

+82
-24
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
3131
- Added `LinearMapView`, the `!Sized` version of `LinearMap`.
3232
- Added `HistoryBufferView`, the `!Sized` version of `HistoryBuffer`.
3333
- Added `DequeView`, the `!Sized` version of `Deque`.
34+
- Added `SortedLinkedListView`, the `!Sized` version of `SortedLinkedList`.
3435

3536
### Changed
3637

src/sorted_linked_list.rs

Lines changed: 81 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,16 @@
2626
//!
2727
//! [`BinaryHeap`]: `crate::binary_heap::BinaryHeap`
2828
29+
use core::borrow::Borrow;
2930
use core::cmp::Ordering;
3031
use core::fmt;
3132
use core::marker::PhantomData;
3233
use core::mem::MaybeUninit;
3334
use core::ops::{Deref, DerefMut};
3435
use core::ptr;
3536

37+
use crate::storage::{OwnedStorage, Storage, ViewStorage};
38+
3639
/// Trait for defining an index for the linked list, never implemented by users.
3740
pub trait SortedLinkedListIndex: Copy {
3841
#[doc(hidden)]
@@ -83,17 +86,29 @@ pub struct Node<T, Idx> {
8386
next: Idx,
8487
}
8588

86-
/// The linked list.
87-
pub struct SortedLinkedList<T, Idx, K, const N: usize>
89+
/// Base struct for [`SortedLinkedList`] and [`SortedLinkedListView`], generic over the [`Storage`].
90+
///
91+
/// In most cases you should use [`SortedLinkedList`] or [`SortedLinkedListView`] directly. Only use this
92+
/// struct if you want to write code that's generic over both.
93+
pub struct SortedLinkedListInner<T, Idx, K, S>
8894
where
8995
Idx: SortedLinkedListIndex,
96+
S: Storage,
9097
{
91-
list: [Node<T, Idx>; N],
9298
head: Idx,
9399
free: Idx,
94100
_kind: PhantomData<K>,
101+
list: S::Buffer<Node<T, Idx>>,
95102
}
96103

104+
/// The linked list.
105+
pub type SortedLinkedList<T, Idx, K: SortedLinkedListIndex, const N: usize> =
106+
SortedLinkedListInner<T, Idx, K, OwnedStorage<N>>;
107+
108+
/// The linked list.
109+
pub type SortedLinkedListView<T, Idx, K: SortedLinkedListIndex> =
110+
SortedLinkedListInner<T, Idx, K, ViewStorage>;
111+
97112
// Internal macro for generating indexes for the linkedlist and const new for the linked list
98113
macro_rules! impl_index_and_const_new {
99114
($name:ident, $ty:ty, $new_name:ident, $max_val:expr) => {
@@ -186,19 +201,35 @@ impl_index_and_const_new!(LinkedIndexUsize, usize, new_usize, { usize::MAX - 1 }
186201
impl<T, Idx, K, const N: usize> SortedLinkedList<T, Idx, K, N>
187202
where
188203
Idx: SortedLinkedListIndex,
204+
{
205+
/// Get a reference to the `SortedLinkedList`, erasing the `N` const-generic.
206+
pub fn as_view(&self) -> &SortedLinkedListView<T, Idx, K> {
207+
self
208+
}
209+
210+
/// Get a mutable reference to the `Vec`, erasing the `N` const-generic.
211+
pub fn as_mut_view(&mut self) -> &mut SortedLinkedListView<T, Idx, K> {
212+
self
213+
}
214+
}
215+
216+
impl<T, Idx, K, S> SortedLinkedListInner<T, Idx, K, S>
217+
where
218+
Idx: SortedLinkedListIndex,
219+
S: Storage,
189220
{
190221
/// Internal access helper
191222
#[inline(always)]
192223
fn node_at(&self, index: usize) -> &Node<T, Idx> {
193224
// Safety: The entire `self.list` is initialized in `new`, which makes this safe.
194-
unsafe { self.list.get_unchecked(index) }
225+
unsafe { self.list.borrow().get_unchecked(index) }
195226
}
196227

197228
/// Internal access helper
198229
#[inline(always)]
199230
fn node_at_mut(&mut self, index: usize) -> &mut Node<T, Idx> {
200231
// Safety: The entire `self.list` is initialized in `new`, which makes this safe.
201-
unsafe { self.list.get_unchecked_mut(index) }
232+
unsafe { self.list.borrow().get_unchecked_mut(index) }
202233
}
203234

204235
/// Internal access helper
@@ -232,11 +263,12 @@ where
232263
}
233264
}
234265

235-
impl<T, Idx, K, const N: usize> SortedLinkedList<T, Idx, K, N>
266+
impl<T, Idx, K, S> SortedLinkedListInner<T, Idx, K, S>
236267
where
237268
T: Ord,
238269
Idx: SortedLinkedListIndex,
239270
K: Kind,
271+
S: Storage,
240272
{
241273
/// Pushes a value onto the list without checking if the list is full.
242274
///
@@ -335,8 +367,8 @@ where
335367
/// assert_eq!(iter.next(), Some(&1));
336368
/// assert_eq!(iter.next(), None);
337369
/// ```
338-
pub fn iter(&self) -> Iter<'_, T, Idx, K, N> {
339-
Iter {
370+
pub fn iter(&self) -> IterInner<'_, T, Idx, K, S> {
371+
IterInner {
340372
list: self,
341373
index: self.head,
342374
}
@@ -364,15 +396,15 @@ where
364396
/// assert_eq!(ll.pop(), Ok(1));
365397
/// assert_eq!(ll.pop(), Err(()));
366398
/// ```
367-
pub fn find_mut<F>(&mut self, mut f: F) -> Option<FindMut<'_, T, Idx, K, N>>
399+
pub fn find_mut<F>(&mut self, mut f: F) -> Option<FindMutInner<'_, T, Idx, K, S>>
368400
where
369401
F: FnMut(&T) -> bool,
370402
{
371403
let head = self.head.option()?;
372404

373405
// Special-case, first element
374406
if f(self.read_data_in_node_at(head)) {
375-
return Some(FindMut {
407+
return Some(FindMutInner {
376408
is_head: true,
377409
prev_index: Idx::none(),
378410
index: self.head,
@@ -385,7 +417,7 @@ where
385417

386418
while let Some(next) = self.node_at(current).next.option() {
387419
if f(self.read_data_in_node_at(next)) {
388-
return Some(FindMut {
420+
return Some(FindMutInner {
389421
is_head: false,
390422
prev_index: unsafe { Idx::new_unchecked(current) },
391423
index: unsafe { Idx::new_unchecked(next) },
@@ -514,22 +546,32 @@ where
514546
}
515547
}
516548

517-
/// Iterator for the linked list.
518-
pub struct Iter<'a, T, Idx, K, const N: usize>
549+
/// Base struct for [`Iter`] and [`IterView`], generic over the [`Storage`].
550+
///
551+
/// In most cases you should use [`Iter`] or [`IterView`] directly. Only use this
552+
/// struct if you want to write code that's generic over both.
553+
pub struct IterInner<'a, T, Idx, K, S>
519554
where
520555
T: Ord,
521556
Idx: SortedLinkedListIndex,
522557
K: Kind,
558+
S: Storage,
523559
{
524-
list: &'a SortedLinkedList<T, Idx, K, N>,
560+
list: &'a SortedLinkedListInner<T, Idx, K, S>,
525561
index: Idx,
526562
}
527563

528-
impl<'a, T, Idx, K, const N: usize> Iterator for Iter<'a, T, Idx, K, N>
564+
/// Iterator for the linked list.
565+
pub type Iter<'a, T, Idx, K, const N: usize> = IterInner<'a, T, Idx, K, OwnedStorage<N>>;
566+
/// Iterator for the linked list.
567+
pub type IterView<'a, T, Idx, K, const N: usize> = IterInner<'a, T, Idx, K, ViewStorage>;
568+
569+
impl<'a, T, Idx, K, S> Iterator for IterInner<'a, T, Idx, K, S>
529570
where
530571
T: Ord,
531572
Idx: SortedLinkedListIndex,
532573
K: Kind,
574+
S: Storage,
533575
{
534576
type Item = &'a T;
535577

@@ -543,25 +585,35 @@ where
543585
}
544586
}
545587

546-
/// Comes from [`SortedLinkedList::find_mut`].
547-
pub struct FindMut<'a, T, Idx, K, const N: usize>
588+
/// Base struct for [`FindMut`] and [`FindMutView`], generic over the [`Storage`].
589+
///
590+
/// In most cases you should use [`FindMut`] or [`FindMutView`] directly. Only use this
591+
/// struct if you want to write code that's generic over both.
592+
pub struct FindMutInner<'a, T, Idx, K, S>
548593
where
549594
T: Ord,
550595
Idx: SortedLinkedListIndex,
551596
K: Kind,
597+
S: Storage,
552598
{
553-
list: &'a mut SortedLinkedList<T, Idx, K, N>,
599+
list: &'a mut SortedLinkedListInner<T, Idx, K, S>,
554600
is_head: bool,
555601
prev_index: Idx,
556602
index: Idx,
557603
maybe_changed: bool,
558604
}
559605

560-
impl<'a, T, Idx, K, const N: usize> FindMut<'a, T, Idx, K, N>
606+
/// Comes from [`SortedLinkedList::find_mut`].
607+
pub type FindMut<'a, T, Idx, K, const N: usize> = FindMutInner<'a, T, Idx, K, OwnedStorage<N>>;
608+
/// Comes from [`SortedLinkedList::find_mut`].
609+
pub type FindMutView<'a, T, Idx, K, const N: usize> = FindMutInner<'a, T, Idx, K, ViewStorage>;
610+
611+
impl<'a, T, Idx, K, S> FindMutInner<'a, T, Idx, K, S>
561612
where
562613
T: Ord,
563614
Idx: SortedLinkedListIndex,
564615
K: Kind,
616+
S: Storage,
565617
{
566618
fn pop_internal(&mut self) -> T {
567619
if self.is_head {
@@ -645,11 +697,12 @@ where
645697
}
646698
}
647699

648-
impl<T, Idx, K, const N: usize> Drop for FindMut<'_, T, Idx, K, N>
700+
impl<T, Idx, K, S> Drop for FindMutInner<'_, T, Idx, K, S>
649701
where
650702
T: Ord,
651703
Idx: SortedLinkedListIndex,
652704
K: Kind,
705+
S: Storage,
653706
{
654707
fn drop(&mut self) {
655708
// Only resort the list if the element has changed
@@ -660,11 +713,12 @@ where
660713
}
661714
}
662715

663-
impl<T, Idx, K, const N: usize> Deref for FindMut<'_, T, Idx, K, N>
716+
impl<T, Idx, K, S> Deref for FindMutInner<'_, T, Idx, K, S>
664717
where
665718
T: Ord,
666719
Idx: SortedLinkedListIndex,
667720
K: Kind,
721+
S: Storage,
668722
{
669723
type Target = T;
670724

@@ -674,11 +728,12 @@ where
674728
}
675729
}
676730

677-
impl<T, Idx, K, const N: usize> DerefMut for FindMut<'_, T, Idx, K, N>
731+
impl<T, Idx, K, S> DerefMut for FindMutInner<'_, T, Idx, K, S>
678732
where
679733
T: Ord,
680734
Idx: SortedLinkedListIndex,
681735
K: Kind,
736+
S: Storage,
682737
{
683738
fn deref_mut(&mut self) -> &mut Self::Target {
684739
self.maybe_changed = true;
@@ -712,20 +767,22 @@ where
712767
// }
713768
// }
714769

715-
impl<T, Idx, K, const N: usize> fmt::Debug for SortedLinkedList<T, Idx, K, N>
770+
impl<T, Idx, K, S> fmt::Debug for SortedLinkedListInner<T, Idx, K, S>
716771
where
717772
T: Ord + core::fmt::Debug,
718773
Idx: SortedLinkedListIndex,
719774
K: Kind,
775+
S: Storage,
720776
{
721777
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
722778
f.debug_list().entries(self.iter()).finish()
723779
}
724780
}
725781

726-
impl<T, Idx, K, const N: usize> Drop for SortedLinkedList<T, Idx, K, N>
782+
impl<T, Idx, K, S> Drop for SortedLinkedListInner<T, Idx, K, S>
727783
where
728784
Idx: SortedLinkedListIndex,
785+
S: Storage,
729786
{
730787
fn drop(&mut self) {
731788
let mut index = self.head;

0 commit comments

Comments
 (0)