diff --git a/README.md b/README.md
index abf9535a..bce7566b 100644
--- a/README.md
+++ b/README.md
@@ -76,6 +76,13 @@
diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index ba853bac..9f89edeb 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -6,18 +6,13 @@
[社区和锈书](community.md)
-
---
[Datav: 可编程的数据可视化平台和可观测性平台](some-thoughts.md)
-
-
-
-
# Rust 语言基础学习
---
@@ -29,7 +24,6 @@
- [不仅仅是 Hello world](first-try/hello-world.md)
- [下载依赖太慢了?](first-try/slowly-downloading.md)
-
- [Rust 基础入门](basic/intro.md)
- [变量绑定与解构](basic/variable.md)
@@ -135,7 +129,6 @@
- [多线程版本](advance-practice1/multi-threads.md)
- [优雅关闭和资源清理](advance-practice1/graceful-shutdown.md)
-
- [进阶实战2: 实现一个简单 Redis](advance-practice/intro.md)
- [tokio 概览](advance-practice/overview.md)
- [使用初印象](advance-practice/getting-startted.md)
@@ -247,8 +240,19 @@
- [数据布局 2](too-many-lists/unsafe-queue/layout2.md)
- [额外的操作](too-many-lists/unsafe-queue/extra-junk.md)
- [最终代码](too-many-lists/unsafe-queue/final-code.md)
+ - [生产级的双向 unsafe 队列](too-many-lists/production-unsafe-deque/intro.md)
+ - [数据布局](too-many-lists/production-unsafe-deque/layout.md)
+ - [型变与子类型](too-many-lists/production-unsafe-deque/variance-and-phantomData.md)
+ - [基础结构](too-many-lists/production-unsafe-deque/basics.md)
+ - [恐慌与安全](too-many-lists/production-unsafe-deque/drop-and-panic-safety.md)
+ - [无聊的组合](too-many-lists/production-unsafe-deque/boring-combinatorics.md)
+ - [其它特征](too-many-lists/production-unsafe-deque/filling-in-random-bits.md)
+ - [测试](too-many-lists/production-unsafe-deque/testing.md)
+ - [Send,Sync和编译测试](too-many-lists/production-unsafe-deque/send-sync-and-compile-tests.md)
+ - [实现游标](too-many-lists/production-unsafe-deque/implementing-cursors.md)
+ - [测试游标](too-many-lists/production-unsafe-deque/testing-cursors.md)
+ - [最终代码](too-many-lists/production-unsafe-deque/final-code.md)
- [使用高级技巧实现链表](too-many-lists/advanced-lists/intro.md)
- - [生产级可用的双向链表](too-many-lists/advanced-lists/unsafe-deque.md)
- [双单向链表](too-many-lists/advanced-lists/double-singly.md)
- [栈上的链表](too-many-lists/advanced-lists/stack-allocated.md)
@@ -313,8 +317,6 @@
- [编译器优化 todo](profiling/compiler/optimization/intro.md)
- [Option 枚举 todo](profiling/compiler/optimization/option.md)
-
-
src\lib.rs:39:17
+ |
+39 | (*old).front = Some(new);
+ | ^^^^^^
+```
+
+是的,我真恨 `NonNull>`。我们需要明确地使用 `as_ptr` 从 NonNull 中获取原始指针,因为 DerefMut 是以 `&mut` 定义的,我们不想在不安全代码中随意引入安全引用!
+
+```rust
+ (*old.as_ptr()).front = Some(new);
+ (*new.as_ptr()).back = Some(old);
+ Compiling linked-list v0.0.3
+warning: field is never read: `elem`
+ --> src\lib.rs:16:5
+ |
+16 | elem: T,
+ | ^^^^^^^
+ |
+ = note: `#[warn(dead_code)]` on by default
+
+warning: `linked-list` (lib) generated 1 warning (1 duplicate)
+warning: `linked-list` (lib test) generated 1 warning
+ Finished test [unoptimized + debuginfo] target(s) in 0.33s
+```
+
+很好,接下来是 `pop` 和 `len`:
+
+```rust
+pub fn pop_front(&mut self) -> Option {
+ unsafe {
+ // Only have to do stuff if there is a front node to pop.
+ // Note that we don't need to mess around with `take` anymore
+ // because everything is Copy and there are no dtors that will
+ // run if we mess up... right? :) Riiiight? :)))
+ self.front.map(|node| {
+ // Bring the Box back to life so we can move out its value and
+ // Drop it (Box continues to magically understand this for us).
+ let boxed_node = Box::from_raw(node.as_ptr());
+ let result = boxed_node.elem;
+
+ // Make the next node into the new front.
+ self.front = boxed_node.back;
+ if let Some(new) = self.front {
+ // Cleanup its reference to the removed node
+ (*new.as_ptr()).front = None;
+ } else {
+ // If the front is now null, then this list is now empty!
+ debug_assert!(self.len == 1);
+ self.back = None;
+ }
+
+ self.len -= 1;
+ result
+ // Box gets implicitly freed here, knows there is no T.
+ })
+ }
+}
+
+pub fn len(&self) -> usize {
+ self.len
+}
+ Compiling linked-list v0.0.3
+ Finished dev [unoptimized + debuginfo] target(s) in 0.37s
+```
+
+在我看来是合法的,是时候写一个测试了!
+
+```rust
+#[cfg(test)]
+mod test {
+ use super::LinkedList;
+
+ #[test]
+ fn test_basic_front() {
+ let mut list = LinkedList::new();
+
+ // Try to break an empty list
+ assert_eq!(list.len(), 0);
+ assert_eq!(list.pop_front(), None);
+ assert_eq!(list.len(), 0);
+
+ // Try to break a one item list
+ list.push_front(10);
+ assert_eq!(list.len(), 1);
+ assert_eq!(list.pop_front(), Some(10));
+ assert_eq!(list.len(), 0);
+ assert_eq!(list.pop_front(), None);
+ assert_eq!(list.len(), 0);
+
+ // Mess around
+ list.push_front(10);
+ assert_eq!(list.len(), 1);
+ list.push_front(20);
+ assert_eq!(list.len(), 2);
+ list.push_front(30);
+ assert_eq!(list.len(), 3);
+ assert_eq!(list.pop_front(), Some(30));
+ assert_eq!(list.len(), 2);
+ list.push_front(40);
+ assert_eq!(list.len(), 3);
+ assert_eq!(list.pop_front(), Some(40));
+ assert_eq!(list.len(), 2);
+ assert_eq!(list.pop_front(), Some(20));
+ assert_eq!(list.len(), 1);
+ assert_eq!(list.pop_front(), Some(10));
+ assert_eq!(list.len(), 0);
+ assert_eq!(list.pop_front(), None);
+ assert_eq!(list.len(), 0);
+ assert_eq!(list.pop_front(), None);
+ assert_eq!(list.len(), 0);
+ }
+}
+ Compiling linked-list v0.0.3
+ Finished test [unoptimized + debuginfo] target(s) in 0.40s
+ Running unittests src\lib.rs
+
+running 1 test
+test test::test_basic_front ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
+```
+
+万幸,我们是完美的!是吗?
diff --git a/src/too-many-lists/production-unsafe-deque/boring-combinatorics.md b/src/too-many-lists/production-unsafe-deque/boring-combinatorics.md
new file mode 100644
index 00000000..0e294d9c
--- /dev/null
+++ b/src/too-many-lists/production-unsafe-deque/boring-combinatorics.md
@@ -0,0 +1,565 @@
+# Boring Combinatorics
+
+好了,回到我们的常规链接列表!
+
+首先,让我们来解决 `Drop` 的问题:
+
+```rust
+impl Drop for LinkedList {
+ fn drop(&mut self) {
+ // Pop until we have to stop
+ while let Some(_) = self.pop_front() { }
+ }
+}
+```
+
+我们必须填写一堆非常无聊的组合实现,如 front、front_mut、back、back_mut、iter、iter_mut、into_iter......
+
+我已经精心设计了之前的 push/pop 实现,因此我们只需前后对调,代码就能做正确的事情!痛苦的经验万岁!(对于节点来说,使用 "prev和next "是很有诱惑力的,但我发现,为了避免错误,尽量使用 "front "和 "back"才是真正对的)。
+
+首先是 `front`:
+
+```rust
+pub fn front(&self) -> Option<&T> {
+ unsafe {
+ self.front.map(|node| &(*node.as_ptr()).elem)
+ }
+}
+```
+
+接着是:
+
+```rust
+pub fn front_mut(&mut self) -> Option<&mut T> {
+ unsafe {
+ self.front.map(|node| &mut (*node.as_ptr()).elem)
+ }
+}
+```
+
+我会把所有的 `back` 版本放到文章最终的代码中。
+
+接下来是迭代器。与之前的所有列表不同,我们终于解锁了双端迭代器([DoubleEndedIterator](https://doc.rust-lang.org/std/iter/trait.DoubleEndedIterator.html))的功能,而且如果要达到生产质量,我们还要支持精确大小迭代器( [ExactSizeIterator](https://doc.rust-lang.org/std/iter/trait.ExactSizeIterator.html))。
+
+因此,除了 `next` 和 `size_hint`,我们还将支持 `next_back` 和 `len`。
+
+```rust
+pub struct Iter<'a, T> {
+ front: Link,
+ back: Link,
+ len: usize,
+ _boo: PhantomData<&'a T>,
+}
+
+impl LinkedList {
+ pub fn iter(&self) -> Iter {
+ Iter {
+ front: self.front,
+ back: self.back,
+ len: self.len,
+ _boo: PhantomData,
+ }
+ }
+}
+
+
+impl<'a, T> IntoIterator for &'a LinkedList {
+ type IntoIter = Iter<'a, T>;
+ type Item = &'a T;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+impl<'a, T> Iterator for Iter<'a, T> {
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option {
+ // While self.front == self.back is a tempting condition to check here,
+ // it won't do the right for yielding the last element! That sort of
+ // thing only works for arrays because of "one-past-the-end" pointers.
+ if self.len > 0 {
+ // We could unwrap front, but this is safer and easier
+ self.front.map(|node| unsafe {
+ self.len -= 1;
+ self.front = (*node.as_ptr()).back;
+ &(*node.as_ptr()).elem
+ })
+ } else {
+ None
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option) {
+ (self.len, Some(self.len))
+ }
+}
+
+impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
+ fn next_back(&mut self) -> Option {
+ if self.len > 0 {
+ self.back.map(|node| unsafe {
+ self.len -= 1;
+ self.back = (*node.as_ptr()).front;
+ &(*node.as_ptr()).elem
+ })
+ } else {
+ None
+ }
+ }
+}
+
+impl<'a, T> ExactSizeIterator for Iter<'a, T> {
+ fn len(&self) -> usize {
+ self.len
+ }
+}
+```
+
+...这只是 `.iter()`...
+
+我们将在最后粘贴 IterMut,它在很多地方与 `mut` 的代码完全相同,让我们先敲掉 `into_iter`。我们仍然可以使用我们屡试不爽的解决方案,即让它包裹我们的集合,并在下一步中使用 `pop`:
+
+```rust
+pub struct IntoIter {
+ list: LinkedList,
+}
+
+impl LinkedList {
+ pub fn into_iter(self) -> IntoIter {
+ IntoIter {
+ list: self
+ }
+ }
+}
+
+
+impl IntoIterator for LinkedList {
+ type IntoIter = IntoIter;
+ type Item = T;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.into_iter()
+ }
+}
+
+impl Iterator for IntoIter {
+ type Item = T;
+
+ fn next(&mut self) -> Option {
+ self.list.pop_front()
+ }
+
+ fn size_hint(&self) -> (usize, Option) {
+ (self.list.len, Some(self.list.len))
+ }
+}
+
+impl DoubleEndedIterator for IntoIter {
+ fn next_back(&mut self) -> Option {
+ self.list.pop_back()
+ }
+}
+
+impl ExactSizeIterator for IntoIter {
+ fn len(&self) -> usize {
+ self.list.len
+ }
+}
+```
+
+仍然是一大堆模板,但至少是令人满意的模板。
+
+好了,这是我们所有的代码,其中包含了所有的组合:
+
+```rust
+use std::ptr::NonNull;
+use std::marker::PhantomData;
+
+pub struct LinkedList {
+ front: Link,
+ back: Link,
+ len: usize,
+ _boo: PhantomData,
+}
+
+type Link = Option>>;
+
+struct Node {
+ front: Link,
+ back: Link,
+ elem: T,
+}
+
+pub struct Iter<'a, T> {
+ front: Link,
+ back: Link,
+ len: usize,
+ _boo: PhantomData<&'a T>,
+}
+
+pub struct IterMut<'a, T> {
+ front: Link,
+ back: Link,
+ len: usize,
+ _boo: PhantomData<&'a mut T>,
+}
+
+pub struct IntoIter {
+ list: LinkedList,
+}
+
+impl LinkedList {
+ pub fn new() -> Self {
+ Self {
+ front: None,
+ back: None,
+ len: 0,
+ _boo: PhantomData,
+ }
+ }
+
+ pub fn push_front(&mut self, elem: T) {
+ // SAFETY: it's a linked-list, what do you want?
+ unsafe {
+ let new = NonNull::new_unchecked(Box::into_raw(Box::new(Node {
+ front: None,
+ back: None,
+ elem,
+ })));
+ if let Some(old) = self.front {
+ // Put the new front before the old one
+ (*old.as_ptr()).front = Some(new);
+ (*new.as_ptr()).back = Some(old);
+ } else {
+ // If there's no front, then we're the empty list and need
+ // to set the back too.
+ self.back = Some(new);
+ }
+ // These things always happen!
+ self.front = Some(new);
+ self.len += 1;
+ }
+ }
+
+ pub fn push_back(&mut self, elem: T) {
+ // SAFETY: it's a linked-list, what do you want?
+ unsafe {
+ let new = NonNull::new_unchecked(Box::into_raw(Box::new(Node {
+ back: None,
+ front: None,
+ elem,
+ })));
+ if let Some(old) = self.back {
+ // Put the new back before the old one
+ (*old.as_ptr()).back = Some(new);
+ (*new.as_ptr()).front = Some(old);
+ } else {
+ // If there's no back, then we're the empty list and need
+ // to set the front too.
+ self.front = Some(new);
+ }
+ // These things always happen!
+ self.back = Some(new);
+ self.len += 1;
+ }
+ }
+
+ pub fn pop_front(&mut self) -> Option {
+ unsafe {
+ // Only have to do stuff if there is a front node to pop.
+ self.front.map(|node| {
+ // Bring the Box back to life so we can move out its value and
+ // Drop it (Box continues to magically understand this for us).
+ let boxed_node = Box::from_raw(node.as_ptr());
+ let result = boxed_node.elem;
+
+ // Make the next node into the new front.
+ self.front = boxed_node.back;
+ if let Some(new) = self.front {
+ // Cleanup its reference to the removed node
+ (*new.as_ptr()).front = None;
+ } else {
+ // If the front is now null, then this list is now empty!
+ self.back = None;
+ }
+
+ self.len -= 1;
+ result
+ // Box gets implicitly freed here, knows there is no T.
+ })
+ }
+ }
+
+ pub fn pop_back(&mut self) -> Option {
+ unsafe {
+ // Only have to do stuff if there is a back node to pop.
+ self.back.map(|node| {
+ // Bring the Box front to life so we can move out its value and
+ // Drop it (Box continues to magically understand this for us).
+ let boxed_node = Box::from_raw(node.as_ptr());
+ let result = boxed_node.elem;
+
+ // Make the next node into the new back.
+ self.back = boxed_node.front;
+ if let Some(new) = self.back {
+ // Cleanup its reference to the removed node
+ (*new.as_ptr()).back = None;
+ } else {
+ // If the back is now null, then this list is now empty!
+ self.front = None;
+ }
+
+ self.len -= 1;
+ result
+ // Box gets implicitly freed here, knows there is no T.
+ })
+ }
+ }
+
+ pub fn front(&self) -> Option<&T> {
+ unsafe {
+ self.front.map(|node| &(*node.as_ptr()).elem)
+ }
+ }
+
+ pub fn front_mut(&mut self) -> Option<&mut T> {
+ unsafe {
+ self.front.map(|node| &mut (*node.as_ptr()).elem)
+ }
+ }
+
+ pub fn back(&self) -> Option<&T> {
+ unsafe {
+ self.back.map(|node| &(*node.as_ptr()).elem)
+ }
+ }
+
+ pub fn back_mut(&mut self) -> Option<&mut T> {
+ unsafe {
+ self.back.map(|node| &mut (*node.as_ptr()).elem)
+ }
+ }
+
+ pub fn len(&self) -> usize {
+ self.len
+ }
+
+ pub fn iter(&self) -> Iter {
+ Iter {
+ front: self.front,
+ back: self.back,
+ len: self.len,
+ _boo: PhantomData,
+ }
+ }
+
+ pub fn iter_mut(&mut self) -> IterMut {
+ IterMut {
+ front: self.front,
+ back: self.back,
+ len: self.len,
+ _boo: PhantomData,
+ }
+ }
+
+ pub fn into_iter(self) -> IntoIter {
+ IntoIter {
+ list: self
+ }
+ }
+}
+
+impl Drop for LinkedList {
+ fn drop(&mut self) {
+ // Pop until we have to stop
+ while let Some(_) = self.pop_front() { }
+ }
+}
+
+impl<'a, T> IntoIterator for &'a LinkedList {
+ type IntoIter = Iter<'a, T>;
+ type Item = &'a T;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+impl<'a, T> Iterator for Iter<'a, T> {
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option {
+ // While self.front == self.back is a tempting condition to check here,
+ // it won't do the right for yielding the last element! That sort of
+ // thing only works for arrays because of "one-past-the-end" pointers.
+ if self.len > 0 {
+ // We could unwrap front, but this is safer and easier
+ self.front.map(|node| unsafe {
+ self.len -= 1;
+ self.front = (*node.as_ptr()).back;
+ &(*node.as_ptr()).elem
+ })
+ } else {
+ None
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option) {
+ (self.len, Some(self.len))
+ }
+}
+
+impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
+ fn next_back(&mut self) -> Option {
+ if self.len > 0 {
+ self.back.map(|node| unsafe {
+ self.len -= 1;
+ self.back = (*node.as_ptr()).front;
+ &(*node.as_ptr()).elem
+ })
+ } else {
+ None
+ }
+ }
+}
+
+impl<'a, T> ExactSizeIterator for Iter<'a, T> {
+ fn len(&self) -> usize {
+ self.len
+ }
+}
+
+impl<'a, T> IntoIterator for &'a mut LinkedList {
+ type IntoIter = IterMut<'a, T>;
+ type Item = &'a mut T;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter_mut()
+ }
+}
+
+impl<'a, T> Iterator for IterMut<'a, T> {
+ type Item = &'a mut T;
+
+ fn next(&mut self) -> Option {
+ // While self.front == self.back is a tempting condition to check here,
+ // it won't do the right for yielding the last element! That sort of
+ // thing only works for arrays because of "one-past-the-end" pointers.
+ if self.len > 0 {
+ // We could unwrap front, but this is safer and easier
+ self.front.map(|node| unsafe {
+ self.len -= 1;
+ self.front = (*node.as_ptr()).back;
+ &mut (*node.as_ptr()).elem
+ })
+ } else {
+ None
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option) {
+ (self.len, Some(self.len))
+ }
+}
+
+impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
+ fn next_back(&mut self) -> Option {
+ if self.len > 0 {
+ self.back.map(|node| unsafe {
+ self.len -= 1;
+ self.back = (*node.as_ptr()).front;
+ &mut (*node.as_ptr()).elem
+ })
+ } else {
+ None
+ }
+ }
+}
+
+impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
+ fn len(&self) -> usize {
+ self.len
+ }
+}
+
+impl IntoIterator for LinkedList {
+ type IntoIter = IntoIter;
+ type Item = T;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.into_iter()
+ }
+}
+
+impl Iterator for IntoIter {
+ type Item = T;
+
+ fn next(&mut self) -> Option {
+ self.list.pop_front()
+ }
+
+ fn size_hint(&self) -> (usize, Option) {
+ (self.list.len, Some(self.list.len))
+ }
+}
+
+impl DoubleEndedIterator for IntoIter {
+ fn next_back(&mut self) -> Option {
+ self.list.pop_back()
+ }
+}
+
+impl ExactSizeIterator for IntoIter {
+ fn len(&self) -> usize {
+ self.list.len
+ }
+}
+
+
+#[cfg(test)]
+mod test {
+ use super::LinkedList;
+
+ #[test]
+ fn test_basic_front() {
+ let mut list = LinkedList::new();
+
+ // Try to break an empty list
+ assert_eq!(list.len(), 0);
+ assert_eq!(list.pop_front(), None);
+ assert_eq!(list.len(), 0);
+
+ // Try to break a one item list
+ list.push_front(10);
+ assert_eq!(list.len(), 1);
+ assert_eq!(list.pop_front(), Some(10));
+ assert_eq!(list.len(), 0);
+ assert_eq!(list.pop_front(), None);
+ assert_eq!(list.len(), 0);
+
+ // Mess around
+ list.push_front(10);
+ assert_eq!(list.len(), 1);
+ list.push_front(20);
+ assert_eq!(list.len(), 2);
+ list.push_front(30);
+ assert_eq!(list.len(), 3);
+ assert_eq!(list.pop_front(), Some(30));
+ assert_eq!(list.len(), 2);
+ list.push_front(40);
+ assert_eq!(list.len(), 3);
+ assert_eq!(list.pop_front(), Some(40));
+ assert_eq!(list.len(), 2);
+ assert_eq!(list.pop_front(), Some(20));
+ assert_eq!(list.len(), 1);
+ assert_eq!(list.pop_front(), Some(10));
+ assert_eq!(list.len(), 0);
+ assert_eq!(list.pop_front(), None);
+ assert_eq!(list.len(), 0);
+ assert_eq!(list.pop_front(), None);
+ assert_eq!(list.len(), 0);
+ }
+}
+```
diff --git a/src/too-many-lists/production-unsafe-deque/drop-and-panic-safety.md b/src/too-many-lists/production-unsafe-deque/drop-and-panic-safety.md
new file mode 100644
index 00000000..5c0cdc06
--- /dev/null
+++ b/src/too-many-lists/production-unsafe-deque/drop-and-panic-safety.md
@@ -0,0 +1,162 @@
+# Drop and Panic Safety
+
+嘿,你注意到这些注释了吗:
+
+```rust
+// Note that we don't need to mess around with `take` anymore
+// because everything is Copy and there are no dtors that will
+// run if we mess up... right? :) Riiiight? :)))
+```
+
+这对吗?
+
+你忘记你正在读那本书了吗?当然这是错误的(部分上是)。
+
+让我们再次看看 pop_front 内部:
+
+```rust
+// Bring the Box back to life so we can move out its value and
+// Drop it (Box continues to magically understand this for us).
+let boxed_node = Box::from_raw(node.as_ptr());
+let result = boxed_node.elem;
+
+// Make the next node into the new front.
+self.front = boxed_node.back;
+if let Some(new) = self.front {
+ // Cleanup its reference to the removed node
+ (*new.as_ptr()).front = None;
+} else {
+ // If the front is now null, then this list is now empty!
+ debug_assert!(self.len == 1);
+ self.back = None;
+}
+
+self.len -= 1;
+result
+// Box gets implicitly freed here, knows there is no T.
+```
+
+你看到 bug 了吗? 真可怕, 是这一行:
+
+```rust
+debug_assert!(self.len == 1);
+```
+
+大多数情况下,你不需要考虑或担心恐慌,但一旦你开始编写真正不安全的代码,并在 "invariants(不可变性) "上大做文章,你就需要对恐慌保持高度警惕!
+
+我们必须谈谈 [*异常安全*](https://doc.rust-lang.org/nightly/nomicon/exception-safety.html) (又名恐慌安全、解除安全......)。
+
+情况是这样的:在默认情况下,恐慌会被 unwinding。unwind 只是 "让每个函数立即返回 "的一种花哨说法。你可能会想:"好吧,如果每个函数都返回,那么程序就要结束了,何必在乎它呢?"但你错了!
+
+我们必须关注有两个原因:当函数返回时,析构函数会运行,而且可以捕获 unwind。在这两种情况下,代码都可能在恐慌发生后继续运行,因此我们必须非常小心,确保我们的不安全的集合在恐慌发生时始终处于某种一致的状态,因为每次恐慌都是隐式的提前返回!
+
+让我们想一想,到这一行时,我们的集合处于什么状态:
+
+我们将 boxed_node 放在栈上,并从中提取了元素。如果我们在此时返回,Box 将被丢弃,节点将被释放。self.back 仍然指向那个被释放的节点!一旦我们使用 self.back 来处理一些事情,这就可能导致释放后再使用!
+
+有趣的是,这行也有类似的问题,但它要安全得多:
+
+```rust
+self.len -= 1;
+```
+
+默认情况下,Rust 会在调试构建时检查上溢和下溢,并在发生时产生恐慌。是的,每一次算术运算都会带来恐慌安全隐患!这行还好,他不会导致内存错误,因为之前已经完成了该做的所有操作。所以调试断言哪行在某种意义上更糟糕,因为它可能将一个小问题升级为关键问题!
+
+在实现过程中,只要我们确保在别人注意到之前修复它们,我们可以临时性的破坏invariants(不可变性)。这实际上是 Rust 的集合所有权和借用系统的 "杀手级应用 "之一:如果一个操作需要一个 `&mut Self`,那么我们就能保证对我们的集合拥有独占访问权,而且我们可以暂时破坏invariants(不可变性),因为我们知道没有人能偷偷摸摸地破坏它。
+
+我们有两种方法可以让我们的代码更健壮:
+
+- 更积极地使用 Option::take 这样的操作,因为它们更 "事务性",更倾向于保留invariants(不可变性)。
+- 放弃 debug_asserts,相信自己能写出更好的测试,并使用专用的 "完整性检查 "函数,而这些函数永远不会在用户代码中运行。
+
+原则上,我喜欢第一种方案,但它对双链路列表的实际效果并不好,因为所有内容都是双冗余编码的。Option::take 并不能解决这里的问题,但将 debug_assert 下移一行却可以。不过说真的,为什么要为难我们自己呢?让我们移除那些 debug_asserts,并确保任何可能引起恐慌的事情都发生在我们方法的开头或结尾,而我们在这些地方保持invariants(不可变性)。
+
+这是我们的全部实现:
+
+```rust
+use std::ptr::NonNull;
+use std::marker::PhantomData;
+
+pub struct LinkedList {
+ front: Link,
+ back: Link,
+ len: usize,
+ _boo: PhantomData,
+}
+
+type Link = Option>>;
+
+struct Node {
+ front: Link,
+ back: Link,
+ elem: T,
+}
+
+impl LinkedList {
+ pub fn new() -> Self {
+ Self {
+ front: None,
+ back: None,
+ len: 0,
+ _boo: PhantomData,
+ }
+ }
+
+ pub fn push_front(&mut self, elem: T) {
+ // SAFETY: it's a linked-list, what do you want?
+ unsafe {
+ let new = NonNull::new_unchecked(Box::into_raw(Box::new(Node {
+ front: None,
+ back: None,
+ elem,
+ })));
+ if let Some(old) = self.front {
+ // Put the new front before the old one
+ (*old.as_ptr()).front = Some(new);
+ (*new.as_ptr()).back = Some(old);
+ } else {
+ // If there's no front, then we're the empty list and need
+ // to set the back too.
+ self.back = Some(new);
+ }
+ // These things always happen!
+ self.front = Some(new);
+ self.len += 1;
+ }
+ }
+
+ pub fn pop_front(&mut self) -> Option {
+ unsafe {
+ // Only have to do stuff if there is a front node to pop.
+ self.front.map(|node| {
+ // Bring the Box back to life so we can move out its value and
+ // Drop it (Box continues to magically understand this for us).
+ let boxed_node = Box::from_raw(node.as_ptr());
+ let result = boxed_node.elem;
+
+ // Make the next node into the new front.
+ self.front = boxed_node.back;
+ if let Some(new) = self.front {
+ // Cleanup its reference to the removed node
+ (*new.as_ptr()).front = None;
+ } else {
+ // If the front is now null, then this list is now empty!
+ self.back = None;
+ }
+
+ self.len -= 1;
+ result
+ // Box gets implicitly freed here, knows there is no T.
+ })
+ }
+ }
+
+ pub fn len(&self) -> usize {
+ self.len
+ }
+}
+```
+
+这还有什么可以引发恐慌?老实说,要知道这些需要你是 Rust 专家,不过幸好我是!
+
+在这段代码中,我能看到的唯一可能引起恐慌的地方是 `Box::new`(用于内存不足的情况)和 `len` 运算。所有这些都在我们方法的最末端或最开始,所以,我们是安全的!
diff --git a/src/too-many-lists/production-unsafe-deque/filling-in-random-bits.md b/src/too-many-lists/production-unsafe-deque/filling-in-random-bits.md
new file mode 100644
index 00000000..79cfe4e6
--- /dev/null
+++ b/src/too-many-lists/production-unsafe-deque/filling-in-random-bits.md
@@ -0,0 +1,572 @@
+# Filling In Random Bits
+
+嘿,你不是说要做成精品吗?
+
+为了成为一个 "好 "系列,这里还有一些乱七八糟的东西:
+
+```rust
+impl LinkedList {
+ pub fn is_empty(&self) -> bool {
+ self.len == 0
+ }
+
+ pub fn clear(&mut self) {
+ // Oh look it's drop again
+ while let Some(_) = self.pop_front() { }
+ }
+}
+```
+
+现在,我们已经有了一大堆大家都期待的特性需要实现:
+
+```rust
+impl Default for LinkedList {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl Clone for LinkedList {
+ fn clone(&self) -> Self {
+ let mut new_list = Self::new();
+ for item in self {
+ new_list.push_back(item.clone());
+ }
+ new_list
+ }
+}
+
+impl Extend for LinkedList {
+ fn extend>(&mut self, iter: I) {
+ for item in iter {
+ self.push_back(item);
+ }
+ }
+}
+
+impl FromIterator for LinkedList {
+ fn from_iter>(iter: I) -> Self {
+ let mut list = Self::new();
+ list.extend(iter);
+ list
+ }
+}
+
+impl Debug for LinkedList {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self).finish()
+ }
+}
+
+impl PartialEq for LinkedList {
+ fn eq(&self, other: &Self) -> bool {
+ self.len() == other.len() && self.iter().eq(other)
+ }
+
+ fn ne(&self, other: &Self) -> bool {
+ self.len() != other.len() || self.iter().ne(other)
+ }
+}
+
+impl Eq for LinkedList { }
+
+impl PartialOrd for LinkedList {
+ fn partial_cmp(&self, other: &Self) -> Option {
+ self.iter().partial_cmp(other)
+ }
+}
+
+impl Ord for LinkedList {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.iter().cmp(other)
+ }
+}
+
+impl Hash for LinkedList {
+ fn hash(&self, state: &mut H) {
+ self.len().hash(state);
+ for item in self {
+ item.hash(state);
+ }
+ }
+}
+```
+
+另一个有趣的话题是哈希本身。你看到我们如何将 `len` 写入散列的吗?这其实非常重要!如果集合不把 `len` 加入散列,很可能会意外的造成前缀碰撞。例如,一个集合包含 `["he", "llo"]` 另一个集合包含 `["hello"]`,我们该如何区分?如果没有把集合长度或其它"分隔符"加入到散列 ,这将毫无意义!会让意外哈希碰撞发生变得太容易,会导致严重的后果,所以还是照做吧!
+
+好了,这是我们现在的代码:
+
+```rust
+use std::cmp::Ordering;
+use std::fmt::{self, Debug};
+use std::hash::{Hash, Hasher};
+use std::iter::FromIterator;
+use std::ptr::NonNull;
+use std::marker::PhantomData;
+
+pub struct LinkedList {
+ front: Link,
+ back: Link,
+ len: usize,
+ _boo: PhantomData,
+}
+
+type Link = Option>>;
+
+struct Node {
+ front: Link,
+ back: Link,
+ elem: T,
+}
+
+pub struct Iter<'a, T> {
+ front: Link,
+ back: Link,
+ len: usize,
+ _boo: PhantomData<&'a T>,
+}
+
+pub struct IterMut<'a, T> {
+ front: Link,
+ back: Link,
+ len: usize,
+ _boo: PhantomData<&'a mut T>,
+}
+
+pub struct IntoIter {
+ list: LinkedList,
+}
+
+impl LinkedList {
+ pub fn new() -> Self {
+ Self {
+ front: None,
+ back: None,
+ len: 0,
+ _boo: PhantomData,
+ }
+ }
+
+ pub fn push_front(&mut self, elem: T) {
+ // SAFETY: it's a linked-list, what do you want?
+ unsafe {
+ let new = NonNull::new_unchecked(Box::into_raw(Box::new(Node {
+ front: None,
+ back: None,
+ elem,
+ })));
+ if let Some(old) = self.front {
+ // Put the new front before the old one
+ (*old.as_ptr()).front = Some(new);
+ (*new.as_ptr()).back = Some(old);
+ } else {
+ // If there's no front, then we're the empty list and need
+ // to set the back too.
+ self.back = Some(new);
+ }
+ // These things always happen!
+ self.front = Some(new);
+ self.len += 1;
+ }
+ }
+
+ pub fn push_back(&mut self, elem: T) {
+ // SAFETY: it's a linked-list, what do you want?
+ unsafe {
+ let new = NonNull::new_unchecked(Box::into_raw(Box::new(Node {
+ back: None,
+ front: None,
+ elem,
+ })));
+ if let Some(old) = self.back {
+ // Put the new back before the old one
+ (*old.as_ptr()).back = Some(new);
+ (*new.as_ptr()).front = Some(old);
+ } else {
+ // If there's no back, then we're the empty list and need
+ // to set the front too.
+ self.front = Some(new);
+ }
+ // These things always happen!
+ self.back = Some(new);
+ self.len += 1;
+ }
+ }
+
+ pub fn pop_front(&mut self) -> Option {
+ unsafe {
+ // Only have to do stuff if there is a front node to pop.
+ self.front.map(|node| {
+ // Bring the Box back to life so we can move out its value and
+ // Drop it (Box continues to magically understand this for us).
+ let boxed_node = Box::from_raw(node.as_ptr());
+ let result = boxed_node.elem;
+
+ // Make the next node into the new front.
+ self.front = boxed_node.back;
+ if let Some(new) = self.front {
+ // Cleanup its reference to the removed node
+ (*new.as_ptr()).front = None;
+ } else {
+ // If the front is now null, then this list is now empty!
+ self.back = None;
+ }
+
+ self.len -= 1;
+ result
+ // Box gets implicitly freed here, knows there is no T.
+ })
+ }
+ }
+
+ pub fn pop_back(&mut self) -> Option {
+ unsafe {
+ // Only have to do stuff if there is a back node to pop.
+ self.back.map(|node| {
+ // Bring the Box front to life so we can move out its value and
+ // Drop it (Box continues to magically understand this for us).
+ let boxed_node = Box::from_raw(node.as_ptr());
+ let result = boxed_node.elem;
+
+ // Make the next node into the new back.
+ self.back = boxed_node.front;
+ if let Some(new) = self.back {
+ // Cleanup its reference to the removed node
+ (*new.as_ptr()).back = None;
+ } else {
+ // If the back is now null, then this list is now empty!
+ self.front = None;
+ }
+
+ self.len -= 1;
+ result
+ // Box gets implicitly freed here, knows there is no T.
+ })
+ }
+ }
+
+ pub fn front(&self) -> Option<&T> {
+ unsafe {
+ self.front.map(|node| &(*node.as_ptr()).elem)
+ }
+ }
+
+ pub fn front_mut(&mut self) -> Option<&mut T> {
+ unsafe {
+ self.front.map(|node| &mut (*node.as_ptr()).elem)
+ }
+ }
+
+ pub fn back(&self) -> Option<&T> {
+ unsafe {
+ self.back.map(|node| &(*node.as_ptr()).elem)
+ }
+ }
+
+ pub fn back_mut(&mut self) -> Option<&mut T> {
+ unsafe {
+ self.back.map(|node| &mut (*node.as_ptr()).elem)
+ }
+ }
+
+ pub fn len(&self) -> usize {
+ self.len
+ }
+
+ pub fn is_empty(&self) -> bool {
+ self.len == 0
+ }
+
+ pub fn clear(&mut self) {
+ // Oh look it's drop again
+ while let Some(_) = self.pop_front() { }
+ }
+
+ pub fn iter(&self) -> Iter {
+ Iter {
+ front: self.front,
+ back: self.back,
+ len: self.len,
+ _boo: PhantomData,
+ }
+ }
+
+ pub fn iter_mut(&mut self) -> IterMut {
+ IterMut {
+ front: self.front,
+ back: self.back,
+ len: self.len,
+ _boo: PhantomData,
+ }
+ }
+
+ pub fn into_iter(self) -> IntoIter {
+ IntoIter {
+ list: self
+ }
+ }
+}
+
+impl Drop for LinkedList {
+ fn drop(&mut self) {
+ // Pop until we have to stop
+ while let Some(_) = self.pop_front() { }
+ }
+}
+
+impl Default for LinkedList {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl Clone for LinkedList {
+ fn clone(&self) -> Self {
+ let mut new_list = Self::new();
+ for item in self {
+ new_list.push_back(item.clone());
+ }
+ new_list
+ }
+}
+
+impl Extend for LinkedList {
+ fn extend>(&mut self, iter: I) {
+ for item in iter {
+ self.push_back(item);
+ }
+ }
+}
+
+impl FromIterator for LinkedList {
+ fn from_iter>(iter: I) -> Self {
+ let mut list = Self::new();
+ list.extend(iter);
+ list
+ }
+}
+
+impl Debug for LinkedList {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self).finish()
+ }
+}
+
+impl PartialEq for LinkedList {
+ fn eq(&self, other: &Self) -> bool {
+ self.len() == other.len() && self.iter().eq(other)
+ }
+
+ fn ne(&self, other: &Self) -> bool {
+ self.len() != other.len() || self.iter().ne(other)
+ }
+}
+
+impl Eq for LinkedList { }
+
+impl PartialOrd for LinkedList {
+ fn partial_cmp(&self, other: &Self) -> Option {
+ self.iter().partial_cmp(other)
+ }
+}
+
+impl Ord for LinkedList {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.iter().cmp(other)
+ }
+}
+
+impl Hash for LinkedList {
+ fn hash(&self, state: &mut H) {
+ self.len().hash(state);
+ for item in self {
+ item.hash(state);
+ }
+ }
+}
+
+impl<'a, T> IntoIterator for &'a LinkedList {
+ type IntoIter = Iter<'a, T>;
+ type Item = &'a T;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+impl<'a, T> Iterator for Iter<'a, T> {
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option {
+ // While self.front == self.back is a tempting condition to check here,
+ // it won't do the right for yielding the last element! That sort of
+ // thing only works for arrays because of "one-past-the-end" pointers.
+ if self.len > 0 {
+ // We could unwrap front, but this is safer and easier
+ self.front.map(|node| unsafe {
+ self.len -= 1;
+ self.front = (*node.as_ptr()).back;
+ &(*node.as_ptr()).elem
+ })
+ } else {
+ None
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option) {
+ (self.len, Some(self.len))
+ }
+}
+
+impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
+ fn next_back(&mut self) -> Option {
+ if self.len > 0 {
+ self.back.map(|node| unsafe {
+ self.len -= 1;
+ self.back = (*node.as_ptr()).front;
+ &(*node.as_ptr()).elem
+ })
+ } else {
+ None
+ }
+ }
+}
+
+impl<'a, T> ExactSizeIterator for Iter<'a, T> {
+ fn len(&self) -> usize {
+ self.len
+ }
+}
+
+impl<'a, T> IntoIterator for &'a mut LinkedList {
+ type IntoIter = IterMut<'a, T>;
+ type Item = &'a mut T;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter_mut()
+ }
+}
+
+impl<'a, T> Iterator for IterMut<'a, T> {
+ type Item = &'a mut T;
+
+ fn next(&mut self) -> Option {
+ // While self.front == self.back is a tempting condition to check here,
+ // it won't do the right for yielding the last element! That sort of
+ // thing only works for arrays because of "one-past-the-end" pointers.
+ if self.len > 0 {
+ // We could unwrap front, but this is safer and easier
+ self.front.map(|node| unsafe {
+ self.len -= 1;
+ self.front = (*node.as_ptr()).back;
+ &mut (*node.as_ptr()).elem
+ })
+ } else {
+ None
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option) {
+ (self.len, Some(self.len))
+ }
+}
+
+impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
+ fn next_back(&mut self) -> Option {
+ if self.len > 0 {
+ self.back.map(|node| unsafe {
+ self.len -= 1;
+ self.back = (*node.as_ptr()).front;
+ &mut (*node.as_ptr()).elem
+ })
+ } else {
+ None
+ }
+ }
+}
+
+impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
+ fn len(&self) -> usize {
+ self.len
+ }
+}
+
+impl IntoIterator for LinkedList {
+ type IntoIter = IntoIter;
+ type Item = T;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.into_iter()
+ }
+}
+
+impl Iterator for IntoIter {
+ type Item = T;
+
+ fn next(&mut self) -> Option {
+ self.list.pop_front()
+ }
+
+ fn size_hint(&self) -> (usize, Option) {
+ (self.list.len, Some(self.list.len))
+ }
+}
+
+impl DoubleEndedIterator for IntoIter {
+ fn next_back(&mut self) -> Option {
+ self.list.pop_back()
+ }
+}
+
+impl ExactSizeIterator for IntoIter {
+ fn len(&self) -> usize {
+ self.list.len
+ }
+}
+
+
+#[cfg(test)]
+mod test {
+ use super::LinkedList;
+
+ #[test]
+ fn test_basic_front() {
+ let mut list = LinkedList::new();
+
+ // Try to break an empty list
+ assert_eq!(list.len(), 0);
+ assert_eq!(list.pop_front(), None);
+ assert_eq!(list.len(), 0);
+
+ // Try to break a one item list
+ list.push_front(10);
+ assert_eq!(list.len(), 1);
+ assert_eq!(list.pop_front(), Some(10));
+ assert_eq!(list.len(), 0);
+ assert_eq!(list.pop_front(), None);
+ assert_eq!(list.len(), 0);
+
+ // Mess around
+ list.push_front(10);
+ assert_eq!(list.len(), 1);
+ list.push_front(20);
+ assert_eq!(list.len(), 2);
+ list.push_front(30);
+ assert_eq!(list.len(), 3);
+ assert_eq!(list.pop_front(), Some(30));
+ assert_eq!(list.len(), 2);
+ list.push_front(40);
+ assert_eq!(list.len(), 3);
+ assert_eq!(list.pop_front(), Some(40));
+ assert_eq!(list.len(), 2);
+ assert_eq!(list.pop_front(), Some(20));
+ assert_eq!(list.len(), 1);
+ assert_eq!(list.pop_front(), Some(10));
+ assert_eq!(list.len(), 0);
+ assert_eq!(list.pop_front(), None);
+ assert_eq!(list.len(), 0);
+ assert_eq!(list.pop_front(), None);
+ assert_eq!(list.len(), 0);
+ }
+}
+```
diff --git a/src/too-many-lists/production-unsafe-deque/final-code.md b/src/too-many-lists/production-unsafe-deque/final-code.md
new file mode 100644
index 00000000..515b0823
--- /dev/null
+++ b/src/too-many-lists/production-unsafe-deque/final-code.md
@@ -0,0 +1,1210 @@
+# Final Code
+
+我真不敢相信,我居然让你坐在那里,听我从头开始重新实现 std::collections::LinkedList,一路上我犯了很多繁琐的小错误。
+
+我做到了,书写完了,我终于可以休息了。
+
+好了,下面是我们完整重写的 1200 行代码的全部内容。这应该与 [this commit](https://github.com/contain-rs/linked-list/commit/5b69cc29454595172a5167a09277660342b78092) 的文本相同。
+
+```rust
+use std::cmp::Ordering;
+use std::fmt::{self, Debug};
+use std::hash::{Hash, Hasher};
+use std::iter::FromIterator;
+use std::marker::PhantomData;
+use std::ptr::NonNull;
+
+pub struct LinkedList {
+ front: Link,
+ back: Link,
+ len: usize,
+ _boo: PhantomData,
+}
+
+type Link = Option>>;
+
+struct Node {
+ front: Link,
+ back: Link,
+ elem: T,
+}
+
+pub struct Iter<'a, T> {
+ front: Link,
+ back: Link,
+ len: usize,
+ _boo: PhantomData<&'a T>,
+}
+
+pub struct IterMut<'a, T> {
+ front: Link,
+ back: Link,
+ len: usize,
+ _boo: PhantomData<&'a mut T>,
+}
+
+pub struct IntoIter {
+ list: LinkedList,
+}
+
+pub struct CursorMut<'a, T> {
+ list: &'a mut LinkedList,
+ cur: Link,
+ index: Option,
+}
+
+impl LinkedList {
+ pub fn new() -> Self {
+ Self {
+ front: None,
+ back: None,
+ len: 0,
+ _boo: PhantomData,
+ }
+ }
+
+ pub fn push_front(&mut self, elem: T) {
+ // SAFETY: it's a linked-list, what do you want?
+ unsafe {
+ let new = NonNull::new_unchecked(Box::into_raw(Box::new(Node {
+ front: None,
+ back: None,
+ elem,
+ })));
+ if let Some(old) = self.front {
+ // Put the new front before the old one
+ (*old.as_ptr()).front = Some(new);
+ (*new.as_ptr()).back = Some(old);
+ } else {
+ // If there's no front, then we're the empty list and need
+ // to set the back too.
+ self.back = Some(new);
+ }
+ // These things always happen!
+ self.front = Some(new);
+ self.len += 1;
+ }
+ }
+
+ pub fn push_back(&mut self, elem: T) {
+ // SAFETY: it's a linked-list, what do you want?
+ unsafe {
+ let new = NonNull::new_unchecked(Box::into_raw(Box::new(Node {
+ back: None,
+ front: None,
+ elem,
+ })));
+ if let Some(old) = self.back {
+ // Put the new back before the old one
+ (*old.as_ptr()).back = Some(new);
+ (*new.as_ptr()).front = Some(old);
+ } else {
+ // If there's no back, then we're the empty list and need
+ // to set the front too.
+ self.front = Some(new);
+ }
+ // These things always happen!
+ self.back = Some(new);
+ self.len += 1;
+ }
+ }
+
+ pub fn pop_front(&mut self) -> Option {
+ unsafe {
+ // Only have to do stuff if there is a front node to pop.
+ self.front.map(|node| {
+ // Bring the Box back to life so we can move out its value and
+ // Drop it (Box continues to magically understand this for us).
+ let boxed_node = Box::from_raw(node.as_ptr());
+ let result = boxed_node.elem;
+
+ // Make the next node into the new front.
+ self.front = boxed_node.back;
+ if let Some(new) = self.front {
+ // Cleanup its reference to the removed node
+ (*new.as_ptr()).front = None;
+ } else {
+ // If the front is now null, then this list is now empty!
+ self.back = None;
+ }
+
+ self.len -= 1;
+ result
+ // Box gets implicitly freed here, knows there is no T.
+ })
+ }
+ }
+
+ pub fn pop_back(&mut self) -> Option {
+ unsafe {
+ // Only have to do stuff if there is a back node to pop.
+ self.back.map(|node| {
+ // Bring the Box front to life so we can move out its value and
+ // Drop it (Box continues to magically understand this for us).
+ let boxed_node = Box::from_raw(node.as_ptr());
+ let result = boxed_node.elem;
+
+ // Make the next node into the new back.
+ self.back = boxed_node.front;
+ if let Some(new) = self.back {
+ // Cleanup its reference to the removed node
+ (*new.as_ptr()).back = None;
+ } else {
+ // If the back is now null, then this list is now empty!
+ self.front = None;
+ }
+
+ self.len -= 1;
+ result
+ // Box gets implicitly freed here, knows there is no T.
+ })
+ }
+ }
+
+ pub fn front(&self) -> Option<&T> {
+ unsafe { self.front.map(|node| &(*node.as_ptr()).elem) }
+ }
+
+ pub fn front_mut(&mut self) -> Option<&mut T> {
+ unsafe { self.front.map(|node| &mut (*node.as_ptr()).elem) }
+ }
+
+ pub fn back(&self) -> Option<&T> {
+ unsafe { self.back.map(|node| &(*node.as_ptr()).elem) }
+ }
+
+ pub fn back_mut(&mut self) -> Option<&mut T> {
+ unsafe { self.back.map(|node| &mut (*node.as_ptr()).elem) }
+ }
+
+ pub fn len(&self) -> usize {
+ self.len
+ }
+
+ pub fn is_empty(&self) -> bool {
+ self.len == 0
+ }
+
+ pub fn clear(&mut self) {
+ // Oh look it's drop again
+ while self.pop_front().is_some() {}
+ }
+
+ pub fn iter(&self) -> Iter {
+ Iter {
+ front: self.front,
+ back: self.back,
+ len: self.len,
+ _boo: PhantomData,
+ }
+ }
+
+ pub fn iter_mut(&mut self) -> IterMut {
+ IterMut {
+ front: self.front,
+ back: self.back,
+ len: self.len,
+ _boo: PhantomData,
+ }
+ }
+
+ pub fn cursor_mut(&mut self) -> CursorMut {
+ CursorMut {
+ list: self,
+ cur: None,
+ index: None,
+ }
+ }
+}
+
+impl Drop for LinkedList {
+ fn drop(&mut self) {
+ // Pop until we have to stop
+ while self.pop_front().is_some() {}
+ }
+}
+
+impl Default for LinkedList {
+ fn default() -> Self {
+ Self::new()
+ }
+}
+
+impl Clone for LinkedList {
+ fn clone(&self) -> Self {
+ let mut new_list = Self::new();
+ for item in self {
+ new_list.push_back(item.clone());
+ }
+ new_list
+ }
+}
+
+impl Extend for LinkedList {
+ fn extend>(&mut self, iter: I) {
+ for item in iter {
+ self.push_back(item);
+ }
+ }
+}
+
+impl FromIterator for LinkedList {
+ fn from_iter>(iter: I) -> Self {
+ let mut list = Self::new();
+ list.extend(iter);
+ list
+ }
+}
+
+impl Debug for LinkedList {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_list().entries(self).finish()
+ }
+}
+
+impl PartialEq for LinkedList {
+ fn eq(&self, other: &Self) -> bool {
+ self.len() == other.len() && self.iter().eq(other)
+ }
+}
+
+impl Eq for LinkedList {}
+
+impl PartialOrd for LinkedList {
+ fn partial_cmp(&self, other: &Self) -> Option {
+ self.iter().partial_cmp(other)
+ }
+}
+
+impl Ord for LinkedList {
+ fn cmp(&self, other: &Self) -> Ordering {
+ self.iter().cmp(other)
+ }
+}
+
+impl Hash for LinkedList {
+ fn hash(&self, state: &mut H) {
+ self.len().hash(state);
+ for item in self {
+ item.hash(state);
+ }
+ }
+}
+
+impl<'a, T> IntoIterator for &'a LinkedList {
+ type IntoIter = Iter<'a, T>;
+ type Item = &'a T;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter()
+ }
+}
+
+impl<'a, T> Iterator for Iter<'a, T> {
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option {
+ // While self.front == self.back is a tempting condition to check here,
+ // it won't do the right for yielding the last element! That sort of
+ // thing only works for arrays because of "one-past-the-end" pointers.
+ if self.len > 0 {
+ // We could unwrap front, but this is safer and easier
+ self.front.map(|node| unsafe {
+ self.len -= 1;
+ self.front = (*node.as_ptr()).back;
+ &(*node.as_ptr()).elem
+ })
+ } else {
+ None
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option) {
+ (self.len, Some(self.len))
+ }
+}
+
+impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
+ fn next_back(&mut self) -> Option {
+ if self.len > 0 {
+ self.back.map(|node| unsafe {
+ self.len -= 1;
+ self.back = (*node.as_ptr()).front;
+ &(*node.as_ptr()).elem
+ })
+ } else {
+ None
+ }
+ }
+}
+
+impl<'a, T> ExactSizeIterator for Iter<'a, T> {
+ fn len(&self) -> usize {
+ self.len
+ }
+}
+
+impl<'a, T> IntoIterator for &'a mut LinkedList {
+ type IntoIter = IterMut<'a, T>;
+ type Item = &'a mut T;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.iter_mut()
+ }
+}
+
+impl<'a, T> Iterator for IterMut<'a, T> {
+ type Item = &'a mut T;
+
+ fn next(&mut self) -> Option {
+ // While self.front == self.back is a tempting condition to check here,
+ // it won't do the right for yielding the last element! That sort of
+ // thing only works for arrays because of "one-past-the-end" pointers.
+ if self.len > 0 {
+ // We could unwrap front, but this is safer and easier
+ self.front.map(|node| unsafe {
+ self.len -= 1;
+ self.front = (*node.as_ptr()).back;
+ &mut (*node.as_ptr()).elem
+ })
+ } else {
+ None
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option) {
+ (self.len, Some(self.len))
+ }
+}
+
+impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
+ fn next_back(&mut self) -> Option {
+ if self.len > 0 {
+ self.back.map(|node| unsafe {
+ self.len -= 1;
+ self.back = (*node.as_ptr()).front;
+ &mut (*node.as_ptr()).elem
+ })
+ } else {
+ None
+ }
+ }
+}
+
+impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
+ fn len(&self) -> usize {
+ self.len
+ }
+}
+
+impl IntoIterator for LinkedList {
+ type IntoIter = IntoIter;
+ type Item = T;
+
+ fn into_iter(self) -> Self::IntoIter {
+ IntoIter { list: self }
+ }
+}
+
+impl Iterator for IntoIter {
+ type Item = T;
+
+ fn next(&mut self) -> Option {
+ self.list.pop_front()
+ }
+
+ fn size_hint(&self) -> (usize, Option) {
+ (self.list.len, Some(self.list.len))
+ }
+}
+
+impl DoubleEndedIterator for IntoIter