本书github链接: inside-rust-std-library 本文摘自以上链接的书籍,如果对本文中涉及的若干知识想进一步了解,请阅读此书。
LinkedList<T> 代码分析
因为数据结构本身都是非常熟悉的内容,重点是了解RUST与其他语言的不同,本书将只分析LinkedList一个通常意义的数据结构,理解清楚RUST的独特点,其他的数据结构也就不是问题: LinkedList<T> 结构定义如下:
pub struct LinkedList<T> {
head: Option<NonNull<Node<T>>>,
tail: Option<NonNull<Node<T>>>,
len: usize,
marker: PhantomData<Box<Node<T>>>,
}
struct Node<T> {
next: Option<NonNull<Node<T>>>,
prev: Option<NonNull<Node<T>>>,
element: T,
}
Node方法代码:
impl<T> Node<T> {
fn new(element: T) -> Self {
Node { next: None, prev: None, element }
}
fn into_element(self: Box<Self>) -> T {
self.element
}
}
LinkedList的创建及简单的增减方法:
impl<T> LinkedList<T> {
pub const fn new() -> Self {
LinkedList { head: None, tail: None, len: 0, marker: PhantomData }
}
在头部增加一个成员及删除一个成员:
pub fn push_front(&mut self, elt: T) {
self.push_front_node(box Node::new(elt));
}
fn push_front_node(&mut self, mut node: Box<Node<T>>) {
unsafe {
node.next = self.head;
node.prev = None;
let node = Some(Box::leak(node).into());
match self.head {
None => self.tail = node,
Some(head) => (*head.as_ptr()).prev = node,
}
self.head = node;
self.len += 1;
}
}
pub fn pop_front(&mut self) -> Option<T> {
self.pop_front_node().map(Node::into_element)
}
fn pop_front_node(&mut self) -> Option<Box<Node<T>>> {
self.head.map(|node| unsafe {
let node = Box::from_raw(node.as_ptr());
self.head = node.next;
match self.head {
None => self.tail = None,
Some(head) => (*head.as_ptr()).prev = None,
}
self.len -= 1;
node
})
}
在尾部增加一个成员及删除一个成员
pub fn push_back(&mut self, elt: T) {
self.push_back_node(box Node::new(elt));
}
fn push_back_node(&mut self, mut node: Box<Node<T>>) {
unsafe {
node.next = None;
node.prev = self.tail;
let node = Some(Box::leak(node).into());
match self.tail {
None => self.head = node,
Some(tail) => (*tail.as_ptr()).next = node,
}
self.tail = node;
self.len += 1;
}
}
pub fn pop_back(&mut self) -> Option<T> {
self.pop_back_node().map(Node::into_element)
}
fn pop_back_node(&mut self) -> Option<Box<Node<T>>> {
self.tail.map(|node| unsafe {
let node = Box::from_raw(node.as_ptr());
self.tail = node.prev;
match self.tail {
None => self.head = None,
Some(tail) => (*tail.as_ptr()).next = None,
}
self.len -= 1;
node
})
}
...
}
unsafe impl<#[may_dangle] T> Drop for LinkedList<T> {
fn drop(&mut self) {
struct DropGuard<'a, T>(&'a mut LinkedList<T>);
impl<'a, T> Drop for DropGuard<'a, T> {
fn drop(&mut self) {
while self.0.pop_front_node().is_some() {}
}
}
while let Some(node) = self.pop_front_node() {
let guard = DropGuard(self);
drop(node);
mem::forget(guard);
}
}
}
以上基本上说明了RUST的LinkedList的设计及代码的一些关键点。
用Iterator来对List进行访问,Iterator的相关结构代码如下: into_iter()相关结构及方法:
pub struct IntoIter<T> {
list: LinkedList<T>,
}
impl<T> IntoIterator for LinkedList<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> {
IntoIter { list: self }
}
}
impl<T> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
self.list.pop_front()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.list.len, Some(self.list.len))
}
}
iter_mut()调用相关结构及方法
pub struct IterMut<'a, T: 'a> {
head: Option<NonNull<Node<T>>>,
tail: Option<NonNull<Node<T>>>,
len: usize,
marker: PhantomData<&'a mut Node<T>>,
}
impl <T> LinkedList<T> {
...
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
IterMut { head: self.head, tail: self.tail, len: self.len, marker: PhantomData }
}
...
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<&'a mut T> {
if self.len == 0 {
None
} else {
self.head.map(|node| unsafe {
let node = &mut *node.as_ptr();
self.len -= 1;
self.head = node.next;
&mut node.element
})
}
}
...
}
pub struct Iter<'a, T: 'a> {
head: Option<NonNull<Node<T>>>,
tail: Option<NonNull<Node<T>>>,
len: usize,
marker: PhantomData<&'a Node<T>>,
}
impl<T> Clone for Iter<'_, T> {
fn clone(&self) -> Self {
Iter { ..*self }
}
}
LinkedList其他的代码略。
|