Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cordyceps): add List::len method #204

Merged
merged 1 commit into from
Jun 6, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions cordyceps/src/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ use core::{
pub struct List<T: ?Sized> {
head: Link<T>,
tail: Link<T>,
len: usize,
}

/// Links to other nodes in a [`List`].
Expand Down Expand Up @@ -250,21 +251,37 @@ impl<T: ?Sized> List<T> {
List {
head: None,
tail: None,
len: 0,
}
}

/// Returns `true` if this list is empty.
#[inline]
pub fn is_empty(&self) -> bool {
if self.head.is_none() {
debug_assert!(
self.tail.is_none(),
"inconsistent state: a list had a tail but no head!"
);
debug_assert_eq!(
self.len, 0,
"inconsistent state: a list was empty, but its length was not zero"
);
return true;
}

debug_assert_ne!(
self.len, 0,
"inconsistent state: a list was not empty, but its length was zero"
);
false
}

/// Returns the number of elements in the list.
#[inline]
pub fn len(&self) -> usize {
self.len
}
}

impl<T: Linked<Links<T>> + ?Sized> List<T> {
Expand All @@ -277,10 +294,19 @@ impl<T: Linked<Links<T>> + ?Sized> List<T> {
self.tail.is_none(),
"if the linked list's head is null, the tail must also be null"
);
assert_eq!(
self.len, 0,
"if a linked list's head is null, its length must be 0"
);
return;
}
};

assert_ne!(
self.len, 0,
"if a linked list's head is not null, its length must be greater than 0"
);

let tail = self
.tail
.expect("if the linked list has a head, it must also have a tail");
Expand All @@ -307,12 +333,16 @@ impl<T: Linked<Links<T>> + ?Sized> List<T> {
}

let mut curr = Some(head);
let mut actual_len = 0;
while let Some(node) = curr {
let links = unsafe { T::links(node) };
let links = unsafe { links.as_ref() };
links.assert_valid(head_links, tail_links);
curr = links.next();
actual_len += 1;
}

assert_eq!(self.len, actual_len);
}

/// Appends an item to the head of the list.
Expand All @@ -336,6 +366,7 @@ impl<T: Linked<Links<T>> + ?Sized> List<T> {
self.tail = Some(ptr);
}

self.len += 1;
// tracing::trace!(?self, "push_front: pushed");
}

Expand All @@ -355,11 +386,14 @@ impl<T: Linked<Links<T>> + ?Sized> List<T> {
if self.head.is_none() {
self.head = Some(ptr);
}

self.len += 1;
}

/// Remove an item from the head of the list
pub fn pop_front(&mut self) -> Option<T::Handle> {
let head = self.head?;
self.len -= 1;

unsafe {
let mut head_links = T::links(head);
Expand All @@ -378,6 +412,8 @@ impl<T: Linked<Links<T>> + ?Sized> List<T> {
/// Removes an item from the tail of the list.
pub fn pop_back(&mut self) -> Option<T::Handle> {
let tail = self.tail?;
self.len -= 1;

unsafe {
let mut tail_links = T::links(tail);
// tracing::trace!(?self, tail.addr = ?tail, tail.links = ?tail_links, "pop_back");
Expand Down Expand Up @@ -433,6 +469,7 @@ impl<T: Linked<Links<T>> + ?Sized> List<T> {
self.tail = prev;
}

self.len -= 1;
// tracing::trace!(?self, item.addr = ?item, "remove: done");
Some(T::from_ptr(item))
}
Expand Down Expand Up @@ -1209,6 +1246,7 @@ mod tests {
}
}
}
assert_eq!(ll.len(), reference.len());
ll.assert_valid();
}
}
Expand Down