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
//! Range iteration.
//!
//! [`Lsm::scan`](crate::Lsm::scan) merges the in-memory buffer and the on-disk
//! run into one ascending key stream and returns a [`Scan`] over the entries
//! that fall in the requested range.
//!
//! For the foundation release the merge is materialised under the read lock that
//! `scan` takes: the returned [`Scan`] is a consistent point-in-time snapshot of
//! the range, decoupled from later writes, and iterating it never blocks writers.
//! Streaming the merge lazily is a later optimisation (see the roadmap); the
//! snapshot semantics it provides are part of the contract and will not change.
/// An ascending iterator over a key range, returned by
/// [`Lsm::scan`](crate::Lsm::scan).
///
/// Yields `(key, value)` pairs in ascending key order. Deleted keys are already
/// resolved away — a tombstone in the buffer hides the matching on-disk value,
/// and neither appears in the stream.
///
/// # Examples
///
/// ```
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let dir = tempfile::tempdir()?;
/// let db = lsm_db::Lsm::open(dir.path())?;
/// db.put(b"a", b"1")?;
/// db.put(b"b", b"2")?;
/// db.put(b"c", b"3")?;
///
/// let pairs: Vec<_> = db.scan(b"a".to_vec()..b"c".to_vec())?.collect();
/// assert_eq!(pairs, vec![(b"a".to_vec(), b"1".to_vec()), (b"b".to_vec(), b"2".to_vec())]);
/// # Ok(())
/// # }
/// ```