Rustで単方向リストを実装する(unsafe版)

# 概要
腕試しに単方向リストを実装してみた。今回は unsafe 版になります。

* [Rustで単方向リストを実装する(Box版)](https://qiita.com/syuuu/items/e1379427e4d84b046b83)
* [Rustで単方向リストを実装する(Rc\<RefCell>版)](https://qiita.com/syuuu/items/db75947e979444b39c01)

## 環境

* rustc 1.57.0 (Rust 2021)
* WSL1 (Ubuntu 18.04 LTS)

# 実行結果の比較
今回で一通りの目的を達したので、振り返って比較します。
それぞれで素朴な実装で、差が出たのは次のケースです。

大雑把にいうと、イテレータの操作中に次ポインタの差す要素を取り除いてしまうケース(下図)ですね。

![list.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326797/1e0a07a5-d9ea-6202-c50b-076c9dabe21a.png)

次のような違いが出ました。

| 方式              |                    |
|-------------------|--------------------|
| Rc\<RefCell>版    | None を取得して終了 |
| Box版             | コンパイルエラー    |
| unsafe(NonNull)版 | 解放済みのメモリ参照で実行時エラー |

* Rc\<RefCell>版は、解放済みの場合 None を返してくれるので動きます。
* Box版は、イテレータがimutableの参照をしている状態で、pop_back()が更新しようとするのだから所有できずにコンパイルエラーになります
* unsafe版は、イテレータでポインターを直に参照している実装としたので実行時エラーとなりました

このNGのパターンは本質的に、複数のアクセス先が共有を行おうとしている時点で、参照カウントやら解放済みのメモリの認識が必要になる訳です。Rc\<RefCell>版は自然とこれを実現できていたということですね。

## コード(unsafe版)

## Cargo.toml

```toml
[package]
name = "singly-linked-list-unsafe"
version = "0.1.0"
edition = "2021"
rust-version = "1.57"

[dependencies]
```

## main.rs

コメントアウト部分はNGとなったパターン。

```rust
use singly_linked_list_unsafe::SinglyLinkedList;

fn main() {
    let mut list: SinglyLinkedList<u8> = Default::default();
    list.push_back(1);
    // list.push_back(2);
    // let mut iter = list.iter();
    // assert_eq!(iter.next(), Some(1));
    // assert_eq!(list.pop_back(), Some(2));
    // assert_eq!(iter.next(), None);  // NG: Accessing the freed memory!
    // assert_eq!(list.iter().collect::<Vec<_>>(), vec![1]);

    list.push_back(2);
    list.push_back(3);
    println!("{}", list);
    assert_eq!(list.iter().collect::<Vec<_>>(), vec![1, 2, 3]);
    for v in list.iter() {
        println!("{:?}", v);
    }
    assert_eq!(list.pop_back(), Some(3));
    assert_eq!(list.pop_back(), Some(2));
    assert_eq!(list.pop_back(), Some(1));
    assert_eq!(list.pop_back(), None);

    list.push_back(1);
    list.push_back(2);
    assert_eq!(list.pop_front(), Some(1));
    assert_eq!(list.iter().collect::<Vec<_>>(), vec![2]);
}
```

## lib.rs

* `push_back`
  * NonNull::<ListNode<T>>::new() の部分は、Rc\<RefCell>版のようにスタック上の変数を指定すると、呼び出し後にメモリが蒸発するので無限ループに陥ります。なので、ヒープ上の領域を指定する必要があります。
  * Box::into_raw<...> でBoxを消費してポインターに変換できるので、それを使っています
* `pop_back`
  * `cur.as_ptr().value` でも値が取得できるのですが、Dropトレイトを見るに ListNode が解放されていないように見えます
  * `node = unsafe { Box::from_raw(cur.as_ptr()) }` と Box に戻してやると、解放されるようになります  
    ただ、unsafe版は参照カウンターを持たず、メモリが解放済みであるかを知らないため、NGケースも動かせるようにするには解放させずにリークさせるしかない訳です。

```rust
use std::default::Default;
use std::ptr::NonNull;
use std::fmt::{Display, Debug, Formatter, Result};

#[derive(Debug)]
pub struct ListNode<T: Debug> {
    value: T,
    next: Option<NonNull<ListNode<T>>>,
}

#[derive(Default, Debug)]
pub struct SinglyLinkedList<T: Debug> {
    head: Option<NonNull<ListNode<T>>>,
}

impl<T: Debug> ListNode<T> {
    pub fn new(v: T) -> ListNode<T> {
        ListNode { value: v, next: None }
    }
}

impl<T: Debug> Display for ListNode<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        match self.next {
            Some(ref next) => {
                unsafe {
                    write!(f, "ListNode({:?}), {}", self.value, next.as_ref())
                }
            },
            None => write!(f, "ListNode({:?})", self.value)
        }
    }
}

impl<T: Debug> Display for SinglyLinkedList<T> {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        match self.head {
            Some(ref head) => {
                unsafe {
                    write!(f, "SinglyLinkedList[{}]", head.as_ref())
                }
            }
            None => write!(f, "SinglyLinkedList[]")
        }
    }
}

impl<T: Clone + Debug> SinglyLinkedList<T> {
    /// # Examples
    ///
    /// ```
    /// use singly_linked_list_unsafe::SinglyLinkedList;
    /// let mut list: SinglyLinkedList<u8> = Default::default();
    /// list.push_back(1);
    /// list.push_back(2);
    /// ```
    pub fn push_back(&mut self, v: T) {
        let node_new = NonNull::<ListNode<T>>::new(
            Box::into_raw(Box::new(ListNode::<T>::new(v)))
        );
        let mut cur: NonNull<ListNode<T>>;
        cur = match self.head {
            Some(cur) => cur,
            None => {
                self.head = node_new;
                return;
            }
        };

        unsafe {
            while let Some(next) = cur.as_ref().next {
                cur = next;
            }
            cur.as_mut().next = node_new;
        }
        return;
    }

    /// # Examples
    ///
    /// ```
    /// use singly_linked_list_unsafe::SinglyLinkedList;
    /// let mut list: SinglyLinkedList<u8> = Default::default();
    /// list.push_back(1);
    /// list.push_back(2);
    /// assert_eq!(list.pop_back(), Some(2));
    /// assert_eq!(list.pop_back(), Some(1));
    /// assert_eq!(list.pop_back(), None);
    /// ```
    pub fn pop_back(&mut self) -> Option<T> {
        let mut cur: NonNull<ListNode<T>>;
        cur = match self.head {
            Some(cur) => cur,
            None => return None,
        };

        let mut some_prev: Option<NonNull<ListNode<T>>> = None;
        while let Some(next) = unsafe { cur.as_ref().next } {
            some_prev = Some(cur);
            cur = next;
        }

        if let Some(mut prev) = some_prev {
            unsafe {
                println!(
                    "pop_back({:?}): prev(value:{:?}, next: {:?} => None)",
                    cur.as_ref().value,
                    prev.as_ref().value,
                    prev.as_ref().next
                );
                prev.as_mut().next = None;
            }
        } else {
            self.head = None;
        }

        let node : Box<ListNode<T>>;
        node = unsafe { Box::from_raw(cur.as_ptr()) };
        Some(node.value.clone())
    }

    /// # Examples
    ///
    /// ```
    /// use singly_linked_list_unsafe::SinglyLinkedList;
    /// let mut list: SinglyLinkedList<u8> = Default::default();
    /// list.push_back(1);
    /// list.push_back(2);
    /// assert_eq!(list.pop_front(), Some(1));
    /// assert_eq!(list.pop_front(), Some(2));
    /// assert_eq!(list.pop_front(), None);
    /// ```
    pub fn pop_front(&mut self) -> Option<T> {
        let head = match self.head {
            Some(head) => head,
            None => return None,
        };
        self.head = None;
        let node : Box<ListNode<T>> = unsafe {
            Box::from_raw(head.as_ptr())
        };
        self.head = node.next;
        let value = node.value.clone();
        Some(value)
    }

    /// # Examples
    ///
    /// ```
    /// use singly_linked_list_unsafe::SinglyLinkedList;
    /// let mut list: SinglyLinkedList<u8> = Default::default();
    /// list.push_back(1);
    /// list.push_back(2);
    /// let mut iter = list.iter();
    /// assert_eq!(iter.next(), Some(1));
    /// assert_eq!(iter.next(), Some(2));
    /// assert_eq!(iter.next(), None);
    /// ```
    pub fn iter(&self) -> SinglyLinkedListIterator<T> {
        if let Some(head) = self.head {
            SinglyLinkedListIterator {
                cur: Some(head)
            }    
        } else {
            SinglyLinkedListIterator { cur: None }
        }
    }
}

pub struct SinglyLinkedListIterator<T: Debug> {
    cur: Option<NonNull<ListNode<T>>>
}

impl<T: Clone + Debug> Iterator for SinglyLinkedListIterator<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        let cur = match self.cur {
            Some(cur) => cur,
            None => return None,
        };
        let cur_val: T;
        unsafe {
            cur_val = cur.as_ref().value.clone();
            if let Some(next) = cur.as_ref().next {
                self.cur = Some(next);
            } else {
                self.cur = None;
            }
        }
        Some(cur_val)
    }
}

impl<T: Debug> Drop for SinglyLinkedList<T> {
    fn drop(&mut self) {
        println!("> Dropping: SinglyLinkedList");
    }
}

impl<T: Debug> Drop for ListNode<T> {
    fn drop(&mut self) {
        println!("> Dropping: {:p}(value: {:?}, next: {:?})", self, self.value, self.next);
    }
}

#[cfg(test)]
mod tests {
    use super::SinglyLinkedList;

    #[test]
    fn test_push_pop_1() {
        let mut list: SinglyLinkedList<u8> = Default::default();
        list.push_back(1);
        assert_eq!(list.pop_back(), Some(1));
        assert_eq!(list.pop_back(), None);
        list.push_back(1);
        assert_eq!(list.pop_back(), Some(1));
        assert_eq!(list.pop_back(), None);
    }

    #[test]
    fn test_push_pop_2() {
        let mut list: SinglyLinkedList<&str> = Default::default();
        list.push_back("hello");
        list.push_back("world");
        assert_eq!(list.pop_back(), Some("world"));
        assert_eq!(list.pop_back(), Some("hello"));
        assert_eq!(list.pop_back(), None);
        list.push_back("hello");
        list.push_back("world");
        assert_eq!(list.pop_back(), Some("world"));
        assert_eq!(list.pop_back(), Some("hello"));
        assert_eq!(list.pop_back(), None);
    }

    #[test]
    fn test_pop_front_1() {
        let mut list: SinglyLinkedList<u8> = Default::default();
        assert_eq!(list.pop_front(), None);

        list.push_back(1);
        assert_eq!(list.pop_front(), Some(1));
        assert_eq!(list.pop_front(), None);

        list.push_back(1);
        assert_eq!(list.pop_front(), Some(1));
        assert_eq!(list.pop_front(), None);
    }

    #[test]
    fn test_pop_front_2() {
        let mut list: SinglyLinkedList<u8> = Default::default();
        list.push_back(1);
        list.push_back(2);
        assert_eq!(list.pop_front(), Some(1));
        assert_eq!(list.pop_front(), Some(2));
        assert_eq!(list.pop_front(), None);
    }

    #[ignore]
    #[test]
    fn test_iter_unwrap_failed() {
        let mut list: SinglyLinkedList<u8> = Default::default();
        list.push_back(1);
        list.push_back(2);
        let mut iter = list.iter();
        assert_eq!(iter.next(), Some(1));
        assert_eq!(list.pop_back(), Some(2));
        assert_eq!(iter.next(), None);  // NG: Accessing the freed memory!

        list.push_back(2);
        let mut iter = list.iter();
        assert_eq!(iter.next(), Some(1));
        assert_eq!(list.pop_back(), Some(2));
        assert_eq!(iter.next(), None);
    }

    #[test]
    fn test_iter_last_add() {
        let mut list: SinglyLinkedList<u8> = Default::default();
        list.push_back(1);
        let mut iter = list.iter();
        assert_eq!(iter.next(), Some(1));
        list.push_back(2);
        assert_eq!(list.pop_back(), Some(2));
        assert_eq!(iter.next(), None);
    }

    #[ignore]
    #[test]
    fn test_iter_and_pop_front_1() {
        let mut list: SinglyLinkedList<u8> = Default::default();
        list.push_back(1);
        list.push_back(2);
        let mut iter = list.iter();             // The next pointer points to 1.
        assert_eq!(list.pop_front(), Some(1));  // node 1 is dropped.
        assert_eq!(iter.next(), None);          // NG: Accessing the freed memory!
    }

    #[test]
    fn test_iter_and_pop_front1() {
        let mut list: SinglyLinkedList<u8> = Default::default();
        list.push_back(1);
        list.push_back(2);
        let mut iter = list.iter();            // The next pointer points to 1.
        assert_eq!(iter.next(), Some(1));      // The next pointer points to 2.
        assert_eq!(list.pop_front(), Some(1)); // node 1 is dropped.
        assert_eq!(iter.next(), Some(2));      // The next pointer points to None.
        assert_eq!(iter.next(), None);
    }
}
```

# あとがき

単方向リストの実装を通じて、Rc, RefCell, Box なりの理解が深まりました。
unsafe版を通じて、 Rc\<RefCell>版とBox版に相当するコードで unsafe 版にあるような競合の問題がコンパイル時に分かるのは流石です。

一方で、stdにあるライブラリは性能周りを考慮してか独自にメモリ管理し、生ポインターを使った実装をしています。
まだまだ深淵には程遠いですが、個人でさっと独自のデータ構造を作るなら Rc\<RefCell> でやるのが楽そうですね。
Rc\<RefCell>版を unsafe版に書き直すのはヒープ確保の部分が分かったあとは簡単だったので、性能で困ってきてから unsafe版に書き換えても良い気もします。