BurritOS/src/utility/list.rs

358 lines
8.9 KiB
Rust
Raw Normal View History

//! Data structure and definition of a genericsingle-linked LIFO list.
2023-02-15 18:10:08 +01:00
2023-03-21 22:03:48 +01:00
use std::ptr;
2023-03-08 15:48:03 +01:00
#[derive(PartialEq)]
2023-03-01 16:55:17 +01:00
pub struct List<T: PartialEq> {
head: Link<T>,
2023-03-21 22:03:48 +01:00
tail: *mut Node<T>,
2023-02-15 18:10:08 +01:00
}
2023-03-21 22:03:48 +01:00
type Link<T> = *mut Node<T>;
2023-03-01 16:55:17 +01:00
2023-03-08 15:49:31 +01:00
#[derive(PartialEq)]
2023-03-01 16:55:17 +01:00
struct Node<T> {
elem: T,
next: Link<T>,
2023-02-15 18:10:08 +01:00
}
2023-03-21 22:03:48 +01:00
/// Iterator structure for use in a for loop, pop elements before returning it
pub struct IntoIter<T: PartialEq>(List<T>);
/// Iterator structure for use in a for loop, dereference before returning it
pub struct Iter<'a, T> {
next: Option<&'a Node<T>>,
}
/// Same as Iter structure, returned item are mutable
pub struct IterMut<'a, T> {
next: Option<&'a mut Node<T>>,
}
2023-02-15 18:10:08 +01:00
2023-03-01 16:55:17 +01:00
impl<T: PartialEq> List<T> {
2023-03-01 16:55:17 +01:00
/// Push an item at the end of the list
pub fn push(&mut self, elem: T) {
2023-03-21 22:03:48 +01:00
unsafe {
let new_tail = Box::into_raw(Box::new(Node {
elem,
2023-03-21 22:03:48 +01:00
next: ptr::null_mut(),
}));
if !self.tail.is_null() {
(*self.tail).next = new_tail;
} else {
self.head = new_tail;
}
2023-02-15 18:10:08 +01:00
2023-03-21 22:03:48 +01:00
self.tail = new_tail;
}
2023-03-01 16:55:17 +01:00
}
2023-02-15 18:10:08 +01:00
2023-03-21 22:03:48 +01:00
/// Retrieve and remove the item at the head of the list.
2023-03-01 16:55:17 +01:00
///
/// Return None if list is empty
pub fn pop(&mut self) -> Option<T> {
2023-03-21 22:03:48 +01:00
unsafe {
if self.head.is_null() {
None
} else {
let head = Box::from_raw(self.head);
self.head = head.next;
if self.head.is_null() {
self.tail = ptr::null_mut();
}
Some(head.elem)
}
}
2023-02-15 18:10:08 +01:00
}
2023-03-21 22:03:48 +01:00
/// Retrieve without removing the item at the head of the list
2023-03-01 16:55:17 +01:00
///
/// Return None if list is empty
pub fn peek(&self) -> Option<&T> {
2023-03-21 22:03:48 +01:00
unsafe {
self.head.as_ref().map(|node| &node.elem)
}
2023-02-15 18:10:08 +01:00
}
2023-03-21 22:03:48 +01:00
/// Retrieve without removing the item at the head of the list as mutable
2023-03-01 16:55:17 +01:00
///
/// Return None if lsit is empty
pub fn peek_mut(&mut self) -> Option<&mut T> {
2023-03-21 22:03:48 +01:00
unsafe {
self.head.as_mut().map(|node| &mut node.elem)
}
2023-02-15 18:10:08 +01:00
}
2023-03-01 16:55:17 +01:00
/// Search for an element in the list
///
/// Return **bool** true if the list contains the element, false otherwise
///
/// Worst case complexity of this function is O(n)
pub fn contains(&self, elem: &T) -> bool {
let mut iter = self.iter();
let mut element = iter.next();
2023-03-01 16:55:17 +01:00
while element.is_some() {
if element.unwrap() == elem {
return true;
} else {
element = iter.next();
2023-03-01 16:55:17 +01:00
}
2023-02-15 18:10:08 +01:00
}
2023-03-01 16:55:17 +01:00
false
2023-02-15 18:10:08 +01:00
}
2023-03-08 15:46:53 +01:00
/// Remove the item from the list
///
/// Return true if the item has been found, otherwise return false
///
/// Worst-case complexity is O(n)
2023-03-22 14:30:21 +01:00
pub fn remove(&mut self, item: T)-> bool {
2023-03-21 22:03:48 +01:00
unsafe {
let mut current: *mut Node<T> = self.head;
let mut previous: *mut Node<T> = ptr::null_mut();
while !current.is_null() {
2023-03-22 14:30:21 +01:00
if (*current).elem == item {
2023-03-21 22:03:48 +01:00
(*previous).next = (*current).next;
2023-03-22 14:30:21 +01:00
drop(Box::from_raw(current).elem);
2023-03-21 22:03:48 +01:00
return true;
} else {
previous = current;
current = (*current).next;
}
2023-03-08 15:46:53 +01:00
}
}
2023-03-21 22:03:48 +01:00
false
2023-03-08 15:46:53 +01:00
}
/// Return true if the list is empty, false otherwise
2023-03-08 15:46:53 +01:00
pub fn is_empty(&self) -> bool {
2023-03-21 22:03:48 +01:00
self.head.is_null()
2023-03-08 15:46:53 +01:00
}
/// Turn the list into an iterator for use in a for loop per example.
///
/// When you iter using into_iter, elements are remove from the list
2023-03-01 16:55:17 +01:00
pub fn into_iter(self) -> IntoIter<T> {
IntoIter(self)
2023-02-15 18:10:08 +01:00
}
2023-03-01 16:55:17 +01:00
/// Turn the list into an iterator for use in a for loop
///
/// When you iter using this method, elements are dereferenced
2023-03-01 16:55:17 +01:00
pub fn iter(&self) -> Iter<'_, T> {
2023-03-21 22:03:48 +01:00
unsafe {
Iter { next: self.head.as_ref() }
}
2023-02-15 18:10:08 +01:00
}
/// Same as iter but make the iterator mutable
2023-03-01 16:55:17 +01:00
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
2023-03-21 22:03:48 +01:00
unsafe {
IterMut { next: self.head.as_mut() }
}
2023-02-15 18:10:08 +01:00
}
}
impl<T: PartialEq> Default for List<T> {
/// Create an empty list
fn default() -> Self {
Self { head: ptr::null_mut(), tail: ptr::null_mut() }
}
}
2023-03-01 16:55:17 +01:00
impl<T: PartialEq> Drop for List<T> {
2023-02-15 18:10:08 +01:00
fn drop(&mut self) {
while self.pop().is_some() {} // removing every item from list (necessary as we using unsafe function)
2023-02-15 18:10:08 +01:00
}
}
2023-03-01 16:55:17 +01:00
impl<T: PartialEq> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
// access fields of a tuple struct numerically
self.0.pop()
2023-02-17 09:45:47 +01:00
}
}
2023-03-01 16:55:17 +01:00
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
2023-03-21 22:03:48 +01:00
2023-03-01 16:55:17 +01:00
fn next(&mut self) -> Option<Self::Item> {
2023-03-21 22:03:48 +01:00
unsafe {
self.next.map(|node| {
self.next = node.next.as_ref();
&node.elem
})
}
2023-02-17 09:45:47 +01:00
}
}
2023-03-01 16:55:17 +01:00
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
2023-02-17 09:45:47 +01:00
fn next(&mut self) -> Option<Self::Item> {
2023-03-21 22:03:48 +01:00
unsafe {
self.next.take().map(|node| {
self.next = node.next.as_mut();
&mut node.elem
})
}
2023-02-17 09:45:47 +01:00
}
}
2023-03-01 16:55:17 +01:00
#[cfg(test)]
mod test {
use super::List;
#[test]
fn basics() {
let mut list = List::default();
2023-03-01 16:55:17 +01:00
// Check empty list behaves right
assert_eq!(list.pop(), None);
// Populate list
list.push(1);
list.push(2);
list.push(3);
// Check normal removal
2023-03-21 22:03:48 +01:00
assert_eq!(list.pop(), Some(1));
2023-03-01 16:55:17 +01:00
assert_eq!(list.pop(), Some(2));
// Push some more just to make sure nothing's corrupted
list.push(4);
list.push(5);
// Check normal removal
2023-03-21 22:03:48 +01:00
assert_eq!(list.pop(), Some(3));
2023-03-01 16:55:17 +01:00
assert_eq!(list.pop(), Some(4));
// Check exhaustion
2023-03-21 22:03:48 +01:00
assert_eq!(list.pop(), Some(5));
2023-03-01 16:55:17 +01:00
assert_eq!(list.pop(), None);
2023-02-17 09:45:47 +01:00
}
2023-03-01 16:55:17 +01:00
#[test]
fn peek() {
let mut list = List::default();
2023-03-01 16:55:17 +01:00
assert_eq!(list.peek(), None);
assert_eq!(list.peek_mut(), None);
2023-03-21 22:03:48 +01:00
list.push(1);
list.push(2);
list.push(3);
2023-03-01 16:55:17 +01:00
2023-03-21 22:03:48 +01:00
assert_eq!(list.peek(), Some(&1));
assert_eq!(list.peek_mut(), Some(&mut 1));
2023-03-01 16:55:17 +01:00
}
#[test]
fn into_iter() {
let mut list = List::default();
2023-03-21 22:03:48 +01:00
list.push(1);
list.push(2);
list.push(3);
2023-03-01 16:55:17 +01:00
let mut iter = list.into_iter();
assert_eq!(iter.next(), Some(1));
2023-03-21 22:03:48 +01:00
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), Some(3));
2023-03-01 16:55:17 +01:00
assert_eq!(iter.next(), None);
}
2023-02-15 18:10:08 +01:00
#[test]
2023-03-01 16:55:17 +01:00
fn iter() {
let mut list = List::default();
2023-03-21 22:03:48 +01:00
list.push(1);
list.push(2);
list.push(3);
2023-03-01 16:55:17 +01:00
let mut iter = list.iter();
assert_eq!(iter.next(), Some(&1));
2023-03-21 22:03:48 +01:00
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), Some(&3));
2023-02-15 18:10:08 +01:00
}
2023-03-01 16:55:17 +01:00
#[test]
fn iter_mut() {
let mut list = List::default();
list.push(1);
list.push(2);
list.push(3);
2023-03-01 16:55:17 +01:00
let mut iter = list.iter_mut();
assert_eq!(iter.next(), Some(&mut 1));
2023-03-21 22:03:48 +01:00
assert_eq!(iter.next(), Some(&mut 2));
assert_eq!(iter.next(), Some(&mut 3));
}
#[test]
fn contains_test() {
let mut list = List::default();
assert_eq!(list.peek(), None);
list.push(1);
list.push(2);
list.push(3);
assert_eq!(list.contains(&1), true);
assert_eq!(list.contains(&4), false);
}
#[test]
fn remove_test() {
let mut list = List::default();
assert_eq!(list.peek(), None);
list.push(1);
list.push(2);
list.push(3);
assert_eq!(list.contains(&2), true);
2023-03-22 14:30:21 +01:00
list.remove(2);
assert_eq!(list.contains(&2), false);
assert_eq!(list.pop(), Option::Some(1));
assert_eq!(list.pop(), Option::Some(3));
2023-03-22 14:30:21 +01:00
assert_eq!(list.peek(), Option::None);
}
2023-03-21 22:03:48 +01:00
#[test]
fn miri_test() {
let mut list = List::default();
2023-03-21 22:03:48 +01:00
list.push(1);
list.push(2);
list.push(3);
assert!(list.pop() == Some(1));
list.push(4);
assert!(list.pop() == Some(2));
list.push(5);
assert!(list.peek() == Some(&3));
list.push(6);
list.peek_mut().map(|x| *x *= 10);
assert!(list.peek() == Some(&30));
assert!(list.pop() == Some(30));
for elem in list.iter_mut() {
*elem *= 100;
}
let mut iter = list.iter();
assert_eq!(iter.next(), Some(&400));
assert_eq!(iter.next(), Some(&500));
assert_eq!(iter.next(), Some(&600));
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
assert!(list.pop() == Some(400));
list.peek_mut().map(|x| *x *= 10);
assert!(list.peek() == Some(&5000));
list.push(7);
2023-03-01 16:55:17 +01:00
}
2023-02-15 18:10:08 +01:00
}