trine_kv/types.rs
1use std::ops::Bound;
2
3/// Stable numeric cursor for a committed database state.
4///
5/// `ReadVersion` is the public identifier callers use when they want to open a
6/// [`Snapshot`](crate::Snapshot) at a specific historical state. Values are
7/// database-scoped: a read version is meaningful only for the database lineage
8/// that produced it, even if another database happens to contain the same
9/// numeric value.
10///
11/// Use [`Db::latest_read_version`](crate::Db::latest_read_version) to capture
12/// the newest visible state, and [`Db::snapshot_at`](crate::Db::snapshot_at) to
13/// validate and pin a version before reading. Versions older than
14/// [`Db::oldest_retained_read_version`](crate::Db::oldest_retained_read_version)
15/// are expired and must not be read by falling back to latest.
16///
17/// # Examples
18///
19/// ```rust
20/// use trine_kv::{Db, DbOptions, ReadVersion};
21///
22/// # fn main() -> trine_kv::Result<()> {
23/// let db = Db::open_sync(DbOptions::memory())?;
24/// assert_eq!(db.latest_read_version(), ReadVersion::ZERO);
25///
26/// db.put_sync(b"k", b"v1")?;
27/// let version = db.latest_read_version();
28/// let keep_version = db.snapshot_at(version)?;
29///
30/// db.put_sync(b"k", b"v2")?;
31/// let snapshot = db.snapshot_at(version)?;
32/// assert_eq!(db.get_at_sync(&snapshot, b"k")?, Some(b"v1".to_vec()));
33/// drop(keep_version);
34/// # Ok(())
35/// # }
36/// ```
37#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
38pub struct ReadVersion(u64);
39
40impl ReadVersion {
41 /// Read version for the empty database state before the first successful
42 /// state-changing write.
43 pub const ZERO: Self = Self(0);
44
45 /// Creates a read version from its stable numeric cursor value.
46 ///
47 /// The value is suitable for application-owned cursors that were
48 /// previously obtained from this same database lineage. Creating a
49 /// `ReadVersion` from a number does not prove the version is still
50 /// retained; call [`Db::snapshot_at`](crate::Db::snapshot_at) to validate
51 /// it before reading.
52 #[must_use]
53 pub const fn from_u64(value: u64) -> Self {
54 Self(value)
55 }
56
57 /// Returns the stable numeric cursor value.
58 ///
59 /// Applications may persist this value and later rebuild it with
60 /// [`ReadVersion::from_u64`]. The number is a public cursor, not a promise
61 /// about Trine's internal commit allocation machinery.
62 #[must_use]
63 pub const fn as_u64(self) -> u64 {
64 self.0
65 }
66
67 pub(crate) const fn from_sequence(sequence: Sequence) -> Self {
68 Self(sequence.get())
69 }
70
71 pub(crate) const fn to_sequence(self) -> Sequence {
72 Sequence::new(self.0)
73 }
74}
75
76#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
77pub(crate) struct Sequence(u64);
78
79impl Sequence {
80 pub(crate) const ZERO: Self = Self(0);
81
82 #[must_use]
83 pub(crate) const fn new(value: u64) -> Self {
84 Self(value)
85 }
86
87 #[must_use]
88 pub(crate) const fn get(self) -> u64 {
89 self.0
90 }
91
92 #[must_use]
93 #[cfg(test)]
94 pub(crate) const fn next(self) -> Option<Self> {
95 match self.0.checked_add(1) {
96 Some(value) => Some(Self(value)),
97 None => None,
98 }
99 }
100}
101
102/// Value bytes stored for a key.
103pub type Value = Vec<u8>;
104
105/// Owned key/value row returned by eager iterators.
106#[derive(Debug, Clone, PartialEq, Eq)]
107pub struct KeyValue {
108 /// User key bytes.
109 pub key: Vec<u8>,
110 /// Value bytes visible for the key.
111 pub value: Value,
112}
113
114impl KeyValue {
115 /// Creates an owned key/value row.
116 #[must_use]
117 pub fn new(key: impl Into<Vec<u8>>, value: impl Into<Value>) -> Self {
118 Self {
119 key: key.into(),
120 value: value.into(),
121 }
122 }
123}
124
125/// User-key range used by range scans and range deletes.
126#[derive(Debug, Clone, PartialEq, Eq)]
127pub struct KeyRange {
128 /// Inclusive, exclusive, or unbounded start key.
129 pub start: Bound<Vec<u8>>,
130 /// Inclusive, exclusive, or unbounded end key.
131 pub end: Bound<Vec<u8>>,
132}
133
134impl KeyRange {
135 /// Returns an unbounded range over all user keys.
136 #[must_use]
137 pub const fn all() -> Self {
138 Self {
139 start: Bound::Unbounded,
140 end: Bound::Unbounded,
141 }
142 }
143
144 /// Creates a half-open range `[start, end)`.
145 #[must_use]
146 pub fn half_open(start: impl Into<Vec<u8>>, end: impl Into<Vec<u8>>) -> Self {
147 Self {
148 start: Bound::Included(start.into()),
149 end: Bound::Excluded(end.into()),
150 }
151 }
152}
153
154impl Default for KeyRange {
155 fn default() -> Self {
156 Self::all()
157 }
158}
159
160/// Information returned after a write becomes committed.
161#[derive(Debug, Clone, Copy, PartialEq, Eq)]
162pub struct CommitInfo {
163 sequence: Sequence,
164}
165
166impl CommitInfo {
167 #[must_use]
168 pub(crate) const fn new(sequence: Sequence) -> Self {
169 Self { sequence }
170 }
171
172 #[must_use]
173 #[cfg(test)]
174 pub(crate) const fn sequence(self) -> Sequence {
175 self.sequence
176 }
177
178 /// Returns the read version made visible by this write.
179 ///
180 /// For a state-changing atomic write, every operation in the write becomes
181 /// visible at this read version. An accepted empty write batch does not
182 /// create a new database state and returns the latest read version that was
183 /// already visible.
184 #[must_use]
185 pub const fn read_version(self) -> ReadVersion {
186 ReadVersion::from_sequence(self.sequence)
187 }
188}