From d7e1f56e4dd8af5a993249ebb8d46d4461d8ddfc Mon Sep 17 00:00:00 2001 From: YK Date: Sun, 8 Dec 2024 06:30:20 +0300 Subject: [PATCH] bad safe deque (chapter 4) --- src/bad_safe_deque.rs | 216 ++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 217 insertions(+) create mode 100644 src/bad_safe_deque.rs diff --git a/src/bad_safe_deque.rs b/src/bad_safe_deque.rs new file mode 100644 index 0000000..8f90f77 --- /dev/null +++ b/src/bad_safe_deque.rs @@ -0,0 +1,216 @@ +use std::rc::Rc; +use std::cell::{ Ref, RefCell, RefMut }; + +pub struct List { + head: Link, + tail: Link, +} + +type Link = Option>>>; + +struct Node { + value: T, + next: Link, + prev: Link, +} + + +impl Node { + fn new (value: T) -> Rc> { + Rc::new(RefCell::new(Self { value, next: None, prev: None, })) + } +} + +pub struct IntoIter (List); + + +impl Iterator for IntoIter { + type Item = T; + fn next (&mut self) -> Option { + self.0.pop_front() + } +} + +impl DoubleEndedIterator for IntoIter { + fn next_back (&mut self) -> Option { + self.0.pop_back() + } +} + + +impl List { + pub fn new () -> Self { + Self { head: None, tail: None } + } + + pub fn push_front (&mut self, value: T) { + let new = Node::new(value); + match self.head.take() { + Some(old) => { + old.borrow_mut().prev = Some(new.clone()); + new.borrow_mut().next = Some(old); + self.head = Some(new); + }, + None => { + self.tail = Some(new.clone()); + self.head = Some(new); + } + } + } + + pub fn push_back (&mut self, value: T) { + let new = Node::new(value); + match self.tail.take() { + Some(old) => { + old.borrow_mut().next = Some(new.clone()); + new.borrow_mut().prev = Some(old); + self.tail = Some(new); + }, + None => { + self.head = Some(new.clone()); + self.tail = Some(new); + } + } + } + + pub fn pop_front (&mut self) -> Option { + self.head.take().map(|old| { + match old.borrow_mut().next.take() { + Some(new) => { + new.borrow_mut().prev.take(); + self.head = Some(new); + }, + None => { + self.tail.take(); + } + } + + Rc::try_unwrap(old).ok().unwrap().into_inner().value + }) + } + + + pub fn pop_back (&mut self) -> Option { + self.tail.take().map(|old| { + match old.borrow_mut().prev.take() { + Some(new) => { + new.borrow_mut().next.take(); + self.tail = Some(new); + }, + None => { + self.head.take(); + } + } + + Rc::try_unwrap(old).ok().unwrap().into_inner().value + }) + } + + pub fn peek_front (&self) -> Option> { + self.head.as_ref().map(|node| Ref::map(node.borrow(), |node| &node.value)) + } + + pub fn peek_back (&self) -> Option> { + self.tail.as_ref().map(|node| Ref::map(node.borrow(), |node| &node.value)) + } + + pub fn peek_front_mut (&self) -> Option> { + self.head.as_ref().map(|node| RefMut::map(node.borrow_mut(), |node| &mut node.value)) + } + + pub fn peek_back_mut (&self) -> Option> { + self.tail.as_ref().map(|node| RefMut::map(node.borrow_mut(), |node| &mut node.value)) + } + + pub fn into_iter (self) -> IntoIter { + IntoIter(self) + } + +} + +impl Drop for List { + fn drop (&mut self) { + while self.pop_front().is_some() {} + } +} + + + +#[cfg(test)] +mod test { + use super::List; + + #[test] + fn basics() { + let mut list = List::new(); + + // Check empty list behaves right + assert_eq!(list.pop_front(), None); + + // Populate list + list.push_front(1); + list.push_front(2); + list.push_front(3); + + // Check normal removal + assert_eq!(list.pop_front(), Some(3)); + assert_eq!(list.pop_front(), Some(2)); + + // Push some more just to make sure nothing's corrupted + list.push_front(4); + list.push_front(5); + + // Check normal removal + assert_eq!(list.pop_front(), Some(5)); + assert_eq!(list.pop_front(), Some(4)); + + // Check exhaustion + assert_eq!(list.pop_front(), Some(1)); + assert_eq!(list.pop_front(), None); + + // ---- back ----- + + // Check empty list behaves right + assert_eq!(list.pop_back(), None); + + // Populate list + list.push_back(1); + list.push_back(2); + list.push_back(3); + + // Check normal removal + assert_eq!(list.pop_back(), Some(3)); + assert_eq!(list.pop_back(), Some(2)); + + // Push some more just to make sure nothing's corrupted + list.push_back(4); + list.push_back(5); + + // Check normal removal + assert_eq!(list.pop_back(), Some(5)); + assert_eq!(list.pop_back(), Some(4)); + + // Check exhaustion + assert_eq!(list.pop_back(), Some(1)); + assert_eq!(list.pop_back(), None); + } + + #[test] + fn peek() { + let mut list = List::new(); + assert!(list.peek_front().is_none()); + assert!(list.peek_back().is_none()); + assert!(list.peek_front_mut().is_none()); + assert!(list.peek_back_mut().is_none()); + + list.push_front(1); list.push_front(2); list.push_front(3); + + assert_eq!(&*list.peek_front().unwrap(), &3); + assert_eq!(&mut *list.peek_front_mut().unwrap(), &mut 3); + assert_eq!(&*list.peek_back().unwrap(), &1); + assert_eq!(&mut *list.peek_back_mut().unwrap(), &mut 1); + } + + + +} diff --git a/src/lib.rs b/src/lib.rs index ed55793..9964669 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ pub mod bad; pub mod ok; pub mod persistent; +pub mod bad_safe_deque;