Skip to content

Commit 9317b14

Browse files
SortedLinkedList: add SortedLinkedListView, similar to VecView on top of rust-embedded#486
1 parent 02cc494 commit 9317b14

File tree

1 file changed

+67
-25
lines changed

1 file changed

+67
-25
lines changed

src/sorted_linked_list.rs

Lines changed: 67 additions & 25 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) => {
@@ -183,22 +198,23 @@ impl_index_and_const_new!(LinkedIndexU8, u8, new_u8, { u8::MAX as usize - 1 });
183198
impl_index_and_const_new!(LinkedIndexU16, u16, new_u16, { u16::MAX as usize - 1 });
184199
impl_index_and_const_new!(LinkedIndexUsize, usize, new_usize, { usize::MAX - 1 });
185200

186-
impl<T, Idx, K, const N: usize> SortedLinkedList<T, Idx, K, N>
201+
impl<T, Idx, K, S> SortedLinkedListInner<T, Idx, K, S>
187202
where
188203
Idx: SortedLinkedListIndex,
204+
S: Storage,
189205
{
190206
/// Internal access helper
191207
#[inline(always)]
192208
fn node_at(&self, index: usize) -> &Node<T, Idx> {
193209
// Safety: The entire `self.list` is initialized in `new`, which makes this safe.
194-
unsafe { self.list.get_unchecked(index) }
210+
unsafe { self.list.borrow().get_unchecked(index) }
195211
}
196212

197213
/// Internal access helper
198214
#[inline(always)]
199215
fn node_at_mut(&mut self, index: usize) -> &mut Node<T, Idx> {
200216
// Safety: The entire `self.list` is initialized in `new`, which makes this safe.
201-
unsafe { self.list.get_unchecked_mut(index) }
217+
unsafe { self.list.borrow().get_unchecked_mut(index) }
202218
}
203219

204220
/// Internal access helper
@@ -232,11 +248,12 @@ where
232248
}
233249
}
234250

235-
impl<T, Idx, K, const N: usize> SortedLinkedList<T, Idx, K, N>
251+
impl<T, Idx, K, S> SortedLinkedListInner<T, Idx, K, S>
236252
where
237253
T: Ord,
238254
Idx: SortedLinkedListIndex,
239255
K: Kind,
256+
S: Storage,
240257
{
241258
/// Pushes a value onto the list without checking if the list is full.
242259
///
@@ -335,8 +352,8 @@ where
335352
/// assert_eq!(iter.next(), Some(&1));
336353
/// assert_eq!(iter.next(), None);
337354
/// ```
338-
pub fn iter(&self) -> Iter<'_, T, Idx, K, N> {
339-
Iter {
355+
pub fn iter(&self) -> IterInner<'_, T, Idx, K, S> {
356+
IterInner {
340357
list: self,
341358
index: self.head,
342359
}
@@ -364,15 +381,15 @@ where
364381
/// assert_eq!(ll.pop(), Ok(1));
365382
/// assert_eq!(ll.pop(), Err(()));
366383
/// ```
367-
pub fn find_mut<F>(&mut self, mut f: F) -> Option<FindMut<'_, T, Idx, K, N>>
384+
pub fn find_mut<F>(&mut self, mut f: F) -> Option<FindMutInner<'_, T, Idx, K, S>>
368385
where
369386
F: FnMut(&T) -> bool,
370387
{
371388
let head = self.head.option()?;
372389

373390
// Special-case, first element
374391
if f(self.read_data_in_node_at(head)) {
375-
return Some(FindMut {
392+
return Some(FindMutInner {
376393
is_head: true,
377394
prev_index: Idx::none(),
378395
index: self.head,
@@ -385,7 +402,7 @@ where
385402

386403
while let Some(next) = self.node_at(current).next.option() {
387404
if f(self.read_data_in_node_at(next)) {
388-
return Some(FindMut {
405+
return Some(FindMutInner {
389406
is_head: false,
390407
prev_index: unsafe { Idx::new_unchecked(current) },
391408
index: unsafe { Idx::new_unchecked(next) },
@@ -514,22 +531,32 @@ where
514531
}
515532
}
516533

517-
/// Iterator for the linked list.
518-
pub struct Iter<'a, T, Idx, K, const N: usize>
534+
/// Base struct for [`Iter`] and [`IterView`], generic over the [`Storage`].
535+
///
536+
/// In most cases you should use [`Iter`] or [`IterView`] directly. Only use this
537+
/// struct if you want to write code that's generic over both.
538+
pub struct IterInner<'a, T, Idx, K, S>
519539
where
520540
T: Ord,
521541
Idx: SortedLinkedListIndex,
522542
K: Kind,
543+
S: Storage,
523544
{
524-
list: &'a SortedLinkedList<T, Idx, K, N>,
545+
list: &'a SortedLinkedListInner<T, Idx, K, S>,
525546
index: Idx,
526547
}
527548

528-
impl<'a, T, Idx, K, const N: usize> Iterator for Iter<'a, T, Idx, K, N>
549+
/// Iterator for the linked list.
550+
pub type Iter<'a, T, Idx, K, const N: usize> = IterInner<'a, T, Idx, K, OwnedStorage<N>>;
551+
/// Iterator for the linked list.
552+
pub type IterView<'a, T, Idx, K, const N: usize> = IterInner<'a, T, Idx, K, ViewStorage>;
553+
554+
impl<'a, T, Idx, K, S> Iterator for IterInner<'a, T, Idx, K, S>
529555
where
530556
T: Ord,
531557
Idx: SortedLinkedListIndex,
532558
K: Kind,
559+
S: Storage,
533560
{
534561
type Item = &'a T;
535562

@@ -543,25 +570,35 @@ where
543570
}
544571
}
545572

546-
/// Comes from [`SortedLinkedList::find_mut`].
547-
pub struct FindMut<'a, T, Idx, K, const N: usize>
573+
/// Base struct for [`FindMut`] and [`FindMutView`], generic over the [`Storage`].
574+
///
575+
/// In most cases you should use [`FindMut`] or [`FindMutView`] directly. Only use this
576+
/// struct if you want to write code that's generic over both.
577+
pub struct FindMutInner<'a, T, Idx, K, S>
548578
where
549579
T: Ord,
550580
Idx: SortedLinkedListIndex,
551581
K: Kind,
582+
S: Storage,
552583
{
553-
list: &'a mut SortedLinkedList<T, Idx, K, N>,
584+
list: &'a mut SortedLinkedListInner<T, Idx, K, S>,
554585
is_head: bool,
555586
prev_index: Idx,
556587
index: Idx,
557588
maybe_changed: bool,
558589
}
559590

560-
impl<'a, T, Idx, K, const N: usize> FindMut<'a, T, Idx, K, N>
591+
/// Comes from [`SortedLinkedList::find_mut`].
592+
pub type FindMut<'a, T, Idx, K, const N: usize> = FindMutInner<'a, T, Idx, K, OwnedStorage<N>>;
593+
/// Comes from [`SortedLinkedList::find_mut`].
594+
pub type FindMutView<'a, T, Idx, K, const N: usize> = FindMutInner<'a, T, Idx, K, ViewStorage>;
595+
596+
impl<'a, T, Idx, K, S> FindMutInner<'a, T, Idx, K, S>
561597
where
562598
T: Ord,
563599
Idx: SortedLinkedListIndex,
564600
K: Kind,
601+
S: Storage,
565602
{
566603
fn pop_internal(&mut self) -> T {
567604
if self.is_head {
@@ -645,11 +682,12 @@ where
645682
}
646683
}
647684

648-
impl<T, Idx, K, const N: usize> Drop for FindMut<'_, T, Idx, K, N>
685+
impl<T, Idx, K, S> Drop for FindMutInner<'_, T, Idx, K, S>
649686
where
650687
T: Ord,
651688
Idx: SortedLinkedListIndex,
652689
K: Kind,
690+
S: Storage,
653691
{
654692
fn drop(&mut self) {
655693
// Only resort the list if the element has changed
@@ -660,11 +698,12 @@ where
660698
}
661699
}
662700

663-
impl<T, Idx, K, const N: usize> Deref for FindMut<'_, T, Idx, K, N>
701+
impl<T, Idx, K, S> Deref for FindMutInner<'_, T, Idx, K, S>
664702
where
665703
T: Ord,
666704
Idx: SortedLinkedListIndex,
667705
K: Kind,
706+
S: Storage,
668707
{
669708
type Target = T;
670709

@@ -674,11 +713,12 @@ where
674713
}
675714
}
676715

677-
impl<T, Idx, K, const N: usize> DerefMut for FindMut<'_, T, Idx, K, N>
716+
impl<T, Idx, K, S> DerefMut for FindMutInner<'_, T, Idx, K, S>
678717
where
679718
T: Ord,
680719
Idx: SortedLinkedListIndex,
681720
K: Kind,
721+
S: Storage,
682722
{
683723
fn deref_mut(&mut self) -> &mut Self::Target {
684724
self.maybe_changed = true;
@@ -712,20 +752,22 @@ where
712752
// }
713753
// }
714754

715-
impl<T, Idx, K, const N: usize> fmt::Debug for SortedLinkedList<T, Idx, K, N>
755+
impl<T, Idx, K, S> fmt::Debug for SortedLinkedListInner<T, Idx, K, S>
716756
where
717757
T: Ord + core::fmt::Debug,
718758
Idx: SortedLinkedListIndex,
719759
K: Kind,
760+
S: Storage,
720761
{
721762
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
722763
f.debug_list().entries(self.iter()).finish()
723764
}
724765
}
725766

726-
impl<T, Idx, K, const N: usize> Drop for SortedLinkedList<T, Idx, K, N>
767+
impl<T, Idx, K, S> Drop for SortedLinkedListInner<T, Idx, K, S>
727768
where
728769
Idx: SortedLinkedListIndex,
770+
S: Storage,
729771
{
730772
fn drop(&mut self) {
731773
let mut index = self.head;

0 commit comments

Comments
 (0)