Skip to content

Commit a9ed238

Browse files
authored
Merge pull request #497 from Nitrokey/sorted-linked-list-view
SortedLinkedList: add SortedLinkedListView, similar to VecView on top of #486
2 parents 2880a89 + f9bf0a3 commit a9ed238

File tree

2 files changed

+81
-24
lines changed

2 files changed

+81
-24
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
3232
- Added `HistoryBufferView`, the `!Sized` version of `HistoryBuffer`.
3333
- Added `DequeView`, the `!Sized` version of `Deque`.
3434
- Added `QueueView`, the `!Sized` version of `Queue`.
35+
- Added `SortedLinkedListView`, the `!Sized` version of `SortedLinkedList`.
3536

3637
### Changed
3738

src/sorted_linked_list.rs

+80-24
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, BorrowMut};
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,28 @@ 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, const N: usize> =
106+
SortedLinkedListInner<T, Idx, K, OwnedStorage<N>>;
107+
108+
/// The linked list.
109+
pub type SortedLinkedListView<T, Idx, K> = SortedLinkedListInner<T, Idx, K, ViewStorage>;
110+
97111
// Internal macro for generating indexes for the linkedlist and const new for the linked list
98112
macro_rules! impl_index_and_const_new {
99113
($name:ident, $ty:ty, $new_name:ident, $max_val:expr) => {
@@ -186,19 +200,35 @@ impl_index_and_const_new!(LinkedIndexUsize, usize, new_usize, { usize::MAX - 1 }
186200
impl<T, Idx, K, const N: usize> SortedLinkedList<T, Idx, K, N>
187201
where
188202
Idx: SortedLinkedListIndex,
203+
{
204+
/// Get a reference to the `SortedLinkedList`, erasing the `N` const-generic.
205+
pub fn as_view(&self) -> &SortedLinkedListView<T, Idx, K> {
206+
self
207+
}
208+
209+
/// Get a mutable reference to the `Vec`, erasing the `N` const-generic.
210+
pub fn as_mut_view(&mut self) -> &mut SortedLinkedListView<T, Idx, K> {
211+
self
212+
}
213+
}
214+
215+
impl<T, Idx, K, S> SortedLinkedListInner<T, Idx, K, S>
216+
where
217+
Idx: SortedLinkedListIndex,
218+
S: Storage,
189219
{
190220
/// Internal access helper
191221
#[inline(always)]
192222
fn node_at(&self, index: usize) -> &Node<T, Idx> {
193223
// Safety: The entire `self.list` is initialized in `new`, which makes this safe.
194-
unsafe { self.list.get_unchecked(index) }
224+
unsafe { self.list.borrow().get_unchecked(index) }
195225
}
196226

197227
/// Internal access helper
198228
#[inline(always)]
199229
fn node_at_mut(&mut self, index: usize) -> &mut Node<T, Idx> {
200230
// Safety: The entire `self.list` is initialized in `new`, which makes this safe.
201-
unsafe { self.list.get_unchecked_mut(index) }
231+
unsafe { self.list.borrow_mut().get_unchecked_mut(index) }
202232
}
203233

204234
/// Internal access helper
@@ -232,11 +262,12 @@ where
232262
}
233263
}
234264

235-
impl<T, Idx, K, const N: usize> SortedLinkedList<T, Idx, K, N>
265+
impl<T, Idx, K, S> SortedLinkedListInner<T, Idx, K, S>
236266
where
237267
T: Ord,
238268
Idx: SortedLinkedListIndex,
239269
K: Kind,
270+
S: Storage,
240271
{
241272
/// Pushes a value onto the list without checking if the list is full.
242273
///
@@ -335,8 +366,8 @@ where
335366
/// assert_eq!(iter.next(), Some(&1));
336367
/// assert_eq!(iter.next(), None);
337368
/// ```
338-
pub fn iter(&self) -> Iter<'_, T, Idx, K, N> {
339-
Iter {
369+
pub fn iter(&self) -> IterInner<'_, T, Idx, K, S> {
370+
IterInner {
340371
list: self,
341372
index: self.head,
342373
}
@@ -364,15 +395,15 @@ where
364395
/// assert_eq!(ll.pop(), Ok(1));
365396
/// assert_eq!(ll.pop(), Err(()));
366397
/// ```
367-
pub fn find_mut<F>(&mut self, mut f: F) -> Option<FindMut<'_, T, Idx, K, N>>
398+
pub fn find_mut<F>(&mut self, mut f: F) -> Option<FindMutInner<'_, T, Idx, K, S>>
368399
where
369400
F: FnMut(&T) -> bool,
370401
{
371402
let head = self.head.option()?;
372403

373404
// Special-case, first element
374405
if f(self.read_data_in_node_at(head)) {
375-
return Some(FindMut {
406+
return Some(FindMutInner {
376407
is_head: true,
377408
prev_index: Idx::none(),
378409
index: self.head,
@@ -385,7 +416,7 @@ where
385416

386417
while let Some(next) = self.node_at(current).next.option() {
387418
if f(self.read_data_in_node_at(next)) {
388-
return Some(FindMut {
419+
return Some(FindMutInner {
389420
is_head: false,
390421
prev_index: unsafe { Idx::new_unchecked(current) },
391422
index: unsafe { Idx::new_unchecked(next) },
@@ -514,22 +545,32 @@ where
514545
}
515546
}
516547

517-
/// Iterator for the linked list.
518-
pub struct Iter<'a, T, Idx, K, const N: usize>
548+
/// Base struct for [`Iter`] and [`IterView`], generic over the [`Storage`].
549+
///
550+
/// In most cases you should use [`Iter`] or [`IterView`] directly. Only use this
551+
/// struct if you want to write code that's generic over both.
552+
pub struct IterInner<'a, T, Idx, K, S>
519553
where
520554
T: Ord,
521555
Idx: SortedLinkedListIndex,
522556
K: Kind,
557+
S: Storage,
523558
{
524-
list: &'a SortedLinkedList<T, Idx, K, N>,
559+
list: &'a SortedLinkedListInner<T, Idx, K, S>,
525560
index: Idx,
526561
}
527562

528-
impl<'a, T, Idx, K, const N: usize> Iterator for Iter<'a, T, Idx, K, N>
563+
/// Iterator for the linked list.
564+
pub type Iter<'a, T, Idx, K, const N: usize> = IterInner<'a, T, Idx, K, OwnedStorage<N>>;
565+
/// Iterator for the linked list.
566+
pub type IterView<'a, T, Idx, K, const N: usize> = IterInner<'a, T, Idx, K, ViewStorage>;
567+
568+
impl<'a, T, Idx, K, S> Iterator for IterInner<'a, T, Idx, K, S>
529569
where
530570
T: Ord,
531571
Idx: SortedLinkedListIndex,
532572
K: Kind,
573+
S: Storage,
533574
{
534575
type Item = &'a T;
535576

@@ -543,25 +584,35 @@ where
543584
}
544585
}
545586

546-
/// Comes from [`SortedLinkedList::find_mut`].
547-
pub struct FindMut<'a, T, Idx, K, const N: usize>
587+
/// Base struct for [`FindMut`] and [`FindMutView`], generic over the [`Storage`].
588+
///
589+
/// In most cases you should use [`FindMut`] or [`FindMutView`] directly. Only use this
590+
/// struct if you want to write code that's generic over both.
591+
pub struct FindMutInner<'a, T, Idx, K, S>
548592
where
549593
T: Ord,
550594
Idx: SortedLinkedListIndex,
551595
K: Kind,
596+
S: Storage,
552597
{
553-
list: &'a mut SortedLinkedList<T, Idx, K, N>,
598+
list: &'a mut SortedLinkedListInner<T, Idx, K, S>,
554599
is_head: bool,
555600
prev_index: Idx,
556601
index: Idx,
557602
maybe_changed: bool,
558603
}
559604

560-
impl<'a, T, Idx, K, const N: usize> FindMut<'a, T, Idx, K, N>
605+
/// Comes from [`SortedLinkedList::find_mut`].
606+
pub type FindMut<'a, T, Idx, K, const N: usize> = FindMutInner<'a, T, Idx, K, OwnedStorage<N>>;
607+
/// Comes from [`SortedLinkedList::find_mut`].
608+
pub type FindMutView<'a, T, Idx, K, const N: usize> = FindMutInner<'a, T, Idx, K, ViewStorage>;
609+
610+
impl<'a, T, Idx, K, S> FindMutInner<'a, T, Idx, K, S>
561611
where
562612
T: Ord,
563613
Idx: SortedLinkedListIndex,
564614
K: Kind,
615+
S: Storage,
565616
{
566617
fn pop_internal(&mut self) -> T {
567618
if self.is_head {
@@ -645,11 +696,12 @@ where
645696
}
646697
}
647698

648-
impl<T, Idx, K, const N: usize> Drop for FindMut<'_, T, Idx, K, N>
699+
impl<T, Idx, K, S> Drop for FindMutInner<'_, T, Idx, K, S>
649700
where
650701
T: Ord,
651702
Idx: SortedLinkedListIndex,
652703
K: Kind,
704+
S: Storage,
653705
{
654706
fn drop(&mut self) {
655707
// Only resort the list if the element has changed
@@ -660,11 +712,12 @@ where
660712
}
661713
}
662714

663-
impl<T, Idx, K, const N: usize> Deref for FindMut<'_, T, Idx, K, N>
715+
impl<T, Idx, K, S> Deref for FindMutInner<'_, T, Idx, K, S>
664716
where
665717
T: Ord,
666718
Idx: SortedLinkedListIndex,
667719
K: Kind,
720+
S: Storage,
668721
{
669722
type Target = T;
670723

@@ -674,11 +727,12 @@ where
674727
}
675728
}
676729

677-
impl<T, Idx, K, const N: usize> DerefMut for FindMut<'_, T, Idx, K, N>
730+
impl<T, Idx, K, S> DerefMut for FindMutInner<'_, T, Idx, K, S>
678731
where
679732
T: Ord,
680733
Idx: SortedLinkedListIndex,
681734
K: Kind,
735+
S: Storage,
682736
{
683737
fn deref_mut(&mut self) -> &mut Self::Target {
684738
self.maybe_changed = true;
@@ -712,20 +766,22 @@ where
712766
// }
713767
// }
714768

715-
impl<T, Idx, K, const N: usize> fmt::Debug for SortedLinkedList<T, Idx, K, N>
769+
impl<T, Idx, K, S> fmt::Debug for SortedLinkedListInner<T, Idx, K, S>
716770
where
717771
T: Ord + core::fmt::Debug,
718772
Idx: SortedLinkedListIndex,
719773
K: Kind,
774+
S: Storage,
720775
{
721776
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
722777
f.debug_list().entries(self.iter()).finish()
723778
}
724779
}
725780

726-
impl<T, Idx, K, const N: usize> Drop for SortedLinkedList<T, Idx, K, N>
781+
impl<T, Idx, K, S> Drop for SortedLinkedListInner<T, Idx, K, S>
727782
where
728783
Idx: SortedLinkedListIndex,
784+
S: Storage,
729785
{
730786
fn drop(&mut self) {
731787
let mut index = self.head;

0 commit comments

Comments
 (0)