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
//! A generic cursor implementation merging pairs of different cursors.

use std::cmp::Ordering;

use super::Cursor;

/// A cursor over the combined updates of two different cursors.
///
/// A `CursorPair` wraps two cursors over the same types of updates, and provides navigation
/// through their merged updates.
pub struct CursorPair<C1, C2> {
    cursor1: C1,
    cursor2: C2,
    key_order: Ordering,    // Invalid keys are `Greater` than all other keys. `Equal` implies both valid.
    val_order: Ordering,    // Invalid vals are `Greater` than all other vals. `Equal` implies both valid.
}

impl<K, V, T, R, C1, C2> Cursor for CursorPair<C1, C2>
where
    K: Ord,
    V: Ord,
    C1: Cursor<Key = K, Val = V, Time = T, Diff = R>,
    C2: Cursor<Key = K, Val = V, Time = T, Diff = R>,
{
    type Key = K;
    type Val = V;
    type Time = T;
    type Diff = R;

    type Storage = (C1::Storage, C2::Storage);

    // validation methods
    fn key_valid(&self, storage: &(C1::Storage, C2::Storage)) -> bool {
        match self.key_order {
            Ordering::Less => self.cursor1.key_valid(&storage.0),
            Ordering::Equal => true,
            Ordering::Greater => self.cursor2.key_valid(&storage.1),
        }
    }
    fn val_valid(&self, storage: &(C1::Storage, C2::Storage)) -> bool {
        match (self.key_order, self.val_order) {
            (Ordering::Less, _) => self.cursor1.val_valid(&storage.0),
            (Ordering::Greater, _) => self.cursor2.val_valid(&storage.1),
            (Ordering::Equal, Ordering::Less) => self.cursor1.val_valid(&storage.0),
            (Ordering::Equal, Ordering::Greater) => self.cursor2.val_valid(&storage.1),
            (Ordering::Equal, Ordering::Equal) => true,
        }
    }

    // accessors
    fn key<'a>(&self, storage: &'a (C1::Storage, C2::Storage)) -> &'a K {
        match self.key_order {
            Ordering::Less => self.cursor1.key(&storage.0),
            _ => self.cursor2.key(&storage.1),
        }
    }
    fn val<'a>(&self, storage: &'a (C1::Storage, C2::Storage)) -> &'a V {
        if self.key_order == Ordering::Less || (self.key_order == Ordering::Equal && self.val_order != Ordering::Greater) {
            self.cursor1.val(&storage.0)
        }
        else {
            self.cursor2.val(&storage.1)
        }
    }
    fn map_times<L: FnMut(&T, &R)>(&mut self, storage: &(C1::Storage, C2::Storage), mut logic: L) {
        if self.key_order == Ordering::Less || (self.key_order == Ordering::Equal && self.val_order != Ordering::Greater) {
            self.cursor1.map_times(&storage.0, |t,d| logic(t,d));
        }
        if self.key_order == Ordering::Greater || (self.key_order == Ordering::Equal && self.val_order != Ordering::Less) {
            self.cursor2.map_times(&storage.1, |t,d| logic(t,d));
        }
    }

    // key methods
    fn step_key(&mut self, storage: &(C1::Storage, C2::Storage)) {

        if self.key_order != Ordering::Greater { self.cursor1.step_key(&storage.0); }
        if self.key_order != Ordering::Less { self.cursor2.step_key(&storage.1); }

        self.key_order = match (self.cursor1.key_valid(&storage.0), self.cursor2.key_valid(&storage.1)) {
            (false, _) => Ordering::Greater,
            (_, false) => Ordering::Less,
            (true, true) => self.cursor1.key(&storage.0).cmp(self.cursor2.key(&storage.1)),
        };
    }
    fn seek_key(&mut self, storage: &(C1::Storage, C2::Storage), key: &K) {

        self.cursor1.seek_key(&storage.0, key);
        self.cursor2.seek_key(&storage.1, key);

        self.key_order = match (self.cursor1.key_valid(&storage.0), self.cursor2.key_valid(&storage.1)) {
            (false, _) => Ordering::Greater,
            (_, false) => Ordering::Less,
            (true, true) => self.cursor1.key(&storage.0).cmp(self.cursor2.key(&storage.1)),
        };
    }

    // value methods
    fn step_val(&mut self, storage: &(C1::Storage, C2::Storage)) {
        match self.key_order {
            Ordering::Less => self.cursor1.step_val(&storage.0),
            Ordering::Equal => {
                if self.val_order != Ordering::Greater { self.cursor1.step_val(&storage.0); }
                if self.val_order != Ordering::Less { self.cursor2.step_val(&storage.1); }
                self.val_order = match (self.cursor1.val_valid(&storage.0), self.cursor2.val_valid(&storage.1)) {
                    (false, _) => Ordering::Greater,
                    (_, false) => Ordering::Less,
                    (true, true) => self.cursor1.val(&storage.0).cmp(self.cursor2.val(&storage.1)),
                };
            },
            Ordering::Greater => self.cursor2.step_val(&storage.1),
        }
    }
    fn seek_val(&mut self, storage: &(C1::Storage, C2::Storage), val: &V) {
        match self.key_order {
            Ordering::Less => self.cursor1.seek_val(&storage.0, val),
            Ordering::Equal => {
                self.cursor1.seek_val(&storage.0, val);
                self.cursor2.seek_val(&storage.1, val);
                self.val_order = match (self.cursor1.val_valid(&storage.0), self.cursor2.val_valid(&storage.1)) {
                    (false, _) => Ordering::Greater,
                    (_, false) => Ordering::Less,
                    (true, true) => self.cursor1.val(&storage.0).cmp(self.cursor2.val(&storage.1)),
                };
            },
            Ordering::Greater => self.cursor2.seek_val(&storage.1, val),
        }
    }

    // rewinding methods
    fn rewind_keys(&mut self, storage: &(C1::Storage, C2::Storage)) {
        self.cursor1.rewind_keys(&storage.0);
        self.cursor2.rewind_keys(&storage.1);
    }
    fn rewind_vals(&mut self, storage: &(C1::Storage, C2::Storage)) {
        if self.key_order != Ordering::Greater { self.cursor1.rewind_vals(&storage.0); }
        if self.key_order != Ordering::Less { self.cursor2.rewind_vals(&storage.1); }
    }
}