1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::{linked_list::IS_SOME, node::LinkedListNode, LinkedList, LinkedListX};
use orx_imp_vec::{prelude::PinnedVec, ImpVec};
use std::fmt::Debug;

impl<'a, T, P> Clone for LinkedList<'a, T, P>
where
    T: 'a + Clone + Debug,
    P: PinnedVec<LinkedListNode<'a, T>> + 'a,
{
    fn clone(&self) -> Self {
        let mut imp: ImpVec<_, _> = unsafe { self.vec.unsafe_clone() }.into();
        for i in 0..imp.len() {
            if i == 0 || imp[i].data.is_some() {
                if let Some(prev) = self.vec[i].prev {
                    imp.set_prev(i, self.vec.index_of(prev));
                }
                if let Some(next) = self.vec[i].next {
                    imp.set_next(i, self.vec.index_of(next));
                }
            }
        }

        Self {
            vec: imp,
            len: self.len,
            memory_utilization: self.memory_utilization,
        }
    }
}
impl<'a, T, P> Clone for LinkedListX<'a, T, P>
where
    T: 'a + Clone,
    P: PinnedVec<LinkedListNode<'a, T>> + 'a,
{
    fn clone(&self) -> Self {
        let mut imp: ImpVec<_, _> = unsafe { self.vec.unsafe_clone() }.into();
        for i in 0..imp.len() {
            if i == 0 || imp[i].data.is_some() {
                if let Some(prev) = self.vec.get(i).expect(IS_SOME).prev {
                    imp.set_prev(i, self.vec.index_of(prev));
                }
                if let Some(next) = self.vec.get(i).expect(IS_SOME).next {
                    imp.set_next(i, self.vec.index_of(next));
                }
            }
        }

        Self {
            vec: imp.into_pinned(),
            len: self.len,
            marker: Default::default(),
        }
    }
}

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

    #[test]
    fn clone() {
        let list = || {
            let mut list = LinkedList::with_linear_growth(3);
            for i in 0..1000 {
                list.push_back(i);
                list.push_front(1000 + i);
                _ = list.pop_back();
            }
            list
        };

        let expected = list().collect_vec();

        let original = list();
        let clone = original.clone();
        drop(original);
        assert_eq!(expected, clone.collect_vec());

        let original = list().built();
        let clone = original.clone();
        drop(original);
        assert_eq!(expected, clone.collect_vec());

        let original = list().built().continue_building();
        let clone = original.clone();
        drop(original);
        assert_eq!(expected, clone.collect_vec());
    }

    #[test]
    fn validate_references() {
        let mut original = LinkedList::new();
        original.push_back('a');
        original.push_back('b');
        original.push_back('c');
        assert_eq!(vec!['a', 'b', 'c'], original.collect_vec());

        let clone = original.clone();
        assert_eq!(vec!['a', 'b', 'c'], clone.collect_vec());

        let originalx = original.built();
        let clonex = originalx.clone();
        assert_eq!(vec!['a', 'b', 'c'], clonex.collect_vec());

        // mutate original
        let mut original = originalx.continue_building();
        original.remove_at(1);
        original.memory_reclaim();
        original.push_back('d');
        original.push_front('e');
        original.pop_back();
        original.pop_front();
        original.pop_back();
        original.memory_reclaim();

        assert_eq!(vec!['a', 'b', 'c'], clone.collect_vec());
        assert_eq!(vec!['a', 'b', 'c'], clonex.collect_vec());
    }
}