Last active
September 15, 2018 02:05
-
-
Save DarinM223/7cebf527fe575b45deb7d27dbc1e9286 to your computer and use it in GitHub Desktop.
Example of NonNull in Rust with a doubly linked list
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::fmt::Debug; | |
use std::ptr::NonNull; | |
#[derive(Debug)] | |
pub struct DListNode<T: Debug> { | |
data: T, | |
next: Option<Box<DListNode<T>>>, | |
prev: Option<NonNull<DListNode<T>>>, | |
} | |
impl<T: Debug> DListNode<T> { | |
pub fn new(value: T) -> DListNode<T> { | |
DListNode { | |
data: value, | |
next: None, | |
prev: None, | |
} | |
} | |
} | |
impl<T: Debug> Drop for DListNode<T> { | |
fn drop(&mut self) { | |
println!("Dropping node: {:?}", *self); | |
} | |
} | |
pub struct DList<T: Debug> { | |
head: Box<DListNode<T>>, | |
tail: NonNull<DListNode<T>>, | |
} | |
impl<T: Debug> DList<T> { | |
pub fn from_value(value: T) -> DList<T> { | |
let mut head = Box::new(DListNode::new(value)); | |
let tail = NonNull::new(&mut *head).unwrap(); | |
DList { head, tail } | |
} | |
pub fn from_iterator<I>(iter: &mut I) -> Option<DList<T>> | |
where | |
I: Iterator<Item = T>, | |
{ | |
let mut list = DList::from_value(iter.next()?); | |
for value in iter { | |
list.add(value); | |
} | |
Some(list) | |
} | |
pub fn add(&mut self, value: T) { | |
let mut next = Box::new(DListNode { | |
data: value, | |
next: None, | |
prev: Some(self.tail), | |
}); | |
let next_ptr = NonNull::new(&mut *next).unwrap(); | |
unsafe { self.tail.as_mut().next = Some(next) }; | |
self.tail = next_ptr; | |
} | |
pub fn print(&self) { | |
print(&self.head); | |
} | |
} | |
pub fn remove<T: Debug>(mut node: DListNode<T>) { | |
let mut next = node.next.take(); | |
let mut prev = node.prev.take(); | |
if let Some(ref mut next) = next { | |
next.prev = prev; | |
} | |
if let Some(ref mut prev) = prev { | |
unsafe { prev.as_mut().next = next }; | |
} | |
} | |
pub fn print<T: Debug>(node: &DListNode<T>) { | |
print!("{:?}", node.data); | |
if let Some(ref next) = node.next { | |
print!(" -> "); | |
print(next); | |
} else { | |
println!(); | |
} | |
} | |
fn main() { | |
let list = DList::from_iterator(&mut vec![1, 2, 3].into_iter()); | |
if let Some(mut list) = list { | |
list.print(); | |
if let Some(next) = list.head.next.take() { | |
remove(*next); | |
list.print(); | |
list.print(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment