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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
pub mod split_signal;

use futures_signals::signal::Mutable;
use futures_signals::signal_vec::MutableVec;
use std::cmp::min;

use std::hash::Hash;
use std::ops::Deref;

pub trait Updateable {
    fn update(&self, other: Self);
}

pub trait Identifiable {
    type Key: Eq + Hash + Clone;
    fn id(&self) -> &Self::Key;
}

impl<K, V> Identifiable for (K, V)
where
    K: Eq + Hash + Clone,
{
    type Key = K;

    fn id(&self) -> &K {
        &self.0
    }
}

impl<K, V> Updateable for (K, V)
where
    V: Updateable,
{
    fn update(&self, other: Self) {
        self.1.update(other.1)
    }
}

impl<T> Updateable for MutableVec<T>
where
    T: Updateable + Clone,
{
    fn update(&self, other: Self) {
        let mut self_lock = self.lock_mut();
        let mut other_lock = other.lock_mut();

        let self_len = self_lock.len();
        let other_len = other_lock.len();

        let last_common_idx = min(self_len, other_len);

        let other_moved = other_lock.drain(..last_common_idx);

        self_lock
            .iter()
            .zip(other_moved)
            .take(last_common_idx)
            .for_each(|(s, o)| s.update(o));

        match self_len.cmp(&other_len) {
            std::cmp::Ordering::Less => {
                self_lock.extend(other_lock.drain(..));
            }
            std::cmp::Ordering::Greater => {
                self_lock.truncate(other_len);
            }
            std::cmp::Ordering::Equal => {}
        }
    }
}

impl<T> Updateable for Mutable<T>
where
    T: PartialEq,
{
    fn update(&self, other: Self) {
        {
            let s = self.lock_ref();
            let o = other.lock_ref();

            if s.deref() == o.deref() {
                return;
            }
        }

        self.swap(&other);
    }
}

pub fn update_vec_direct_cloned<T: PartialEq + Clone>(
    target: &MutableVec<T>,
    other: MutableVec<T>,
) {
    let mut target_lock = target.lock_mut();
    let mut other_lock = other.lock_mut();

    let self_len = target_lock.len();
    let other_len = other_lock.len();

    let last_common_idx = min(self_len, other_len);

    {
        let mut other_moved = other_lock.drain(..last_common_idx);

        for i in 0..last_common_idx {
            let next_other = other_moved.next().unwrap();

            if target_lock[i] == next_other {
                continue;
            }

            target_lock.set_cloned(i, next_other);
        }
    }

    match self_len.cmp(&other_len) {
        std::cmp::Ordering::Less => {
            target_lock.extend(other_lock.drain(..));
        }
        std::cmp::Ordering::Greater => {
            target_lock.truncate(other_len);
        }
        std::cmp::Ordering::Equal => {}
    }
}

pub fn update_vec_direct_copied<T: PartialEq + Copy>(target: &MutableVec<T>, other: MutableVec<T>) {
    let mut target_lock = target.lock_mut();
    let mut other_lock = other.lock_mut();

    let self_len = target_lock.len();
    let other_len = other_lock.len();

    let last_common_idx = min(self_len, other_len);

    {
        let mut other_moved = other_lock.drain(..last_common_idx);

        for i in 0..last_common_idx {
            let next_other = other_moved.next().unwrap();

            if target_lock[i] == next_other {
                continue;
            }

            target_lock.set(i, next_other);
        }
    }

    match self_len.cmp(&other_len) {
        std::cmp::Ordering::Less => {
            target_lock.extend(other_lock.drain(..));
        }
        std::cmp::Ordering::Greater => {
            target_lock.truncate(other_len);
        }
        std::cmp::Ordering::Equal => {}
    }
}