reifydb_transaction/multi/
types.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
3
4// This file includes and modifies code from the skipdb project (https://github.com/al8n/skipdb),
5// originally licensed under the Apache License, Version 2.0.
6// Original copyright:
7//   Copyright (c) 2024 Al Liu
8//
9// The original Apache License can be found at:
10//   http://www.apache.org/licenses/LICENSE-2.0
11
12use std::{cmp, cmp::Reverse};
13
14use reifydb_core::{
15	CommitVersion, CowVec, EncodedKey, delta::Delta, interface::MultiVersionValues, value::encoded::EncodedValues,
16};
17
18pub enum TransactionValue {
19	PendingIter {
20		version: CommitVersion,
21		key: EncodedKey,
22		values: EncodedValues,
23	},
24	Pending(Pending),
25	Committed(Committed),
26}
27
28impl From<MultiVersionValues> for TransactionValue {
29	fn from(value: MultiVersionValues) -> Self {
30		Self::Committed(Committed {
31			key: value.key,
32			values: value.values,
33			version: value.version,
34		})
35	}
36}
37
38impl core::fmt::Debug for TransactionValue {
39	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
40		f.debug_struct("TransactionValue")
41			.field("key", self.key())
42			.field("version", &self.version())
43			.field("value", &self.values())
44			.finish()
45	}
46}
47
48impl Clone for TransactionValue {
49	fn clone(&self) -> Self {
50		match self {
51			Self::Committed(item) => Self::Committed(item.clone()),
52			Self::Pending(delta) => Self::Pending(delta.clone()),
53			Self::PendingIter {
54				version,
55				key,
56				values: value,
57			} => Self::PendingIter {
58				version: *version,
59				key: key.clone(),
60				values: value.clone(),
61			},
62		}
63	}
64}
65
66impl TransactionValue {
67	pub fn key(&self) -> &EncodedKey {
68		match self {
69			Self::PendingIter {
70				key,
71				..
72			} => key,
73			Self::Pending(item) => item.key(),
74			Self::Committed(item) => item.key(),
75		}
76	}
77
78	pub fn version(&self) -> CommitVersion {
79		match self {
80			Self::PendingIter {
81				version,
82				..
83			} => *version,
84			Self::Pending(item) => item.version(),
85			Self::Committed(item) => item.version(),
86		}
87	}
88
89	pub fn values(&self) -> &EncodedValues {
90		match self {
91			Self::PendingIter {
92				values,
93				..
94			} => values,
95			Self::Pending(item) => item.values().expect("encoded of pending cannot be `None`"),
96			Self::Committed(item) => &item.values,
97		}
98	}
99
100	pub fn is_committed(&self) -> bool {
101		matches!(self, Self::Committed(_))
102	}
103
104	pub fn into_multi_version_values(self) -> MultiVersionValues {
105		match self {
106			Self::PendingIter {
107				version,
108				key,
109				values,
110			} => MultiVersionValues {
111				key,
112				values,
113				version,
114			},
115			Self::Pending(item) => match item.delta {
116				Delta::Set {
117					key,
118					values,
119				} => MultiVersionValues {
120					key,
121					values,
122					version: item.version,
123				},
124				Delta::Remove {
125					key,
126					..
127				} => MultiVersionValues {
128					key,
129					values: EncodedValues(CowVec::default()),
130					version: item.version,
131				},
132			},
133			Self::Committed(item) => MultiVersionValues {
134				key: item.key,
135				values: item.values,
136				version: item.version,
137			},
138		}
139	}
140}
141
142impl From<(CommitVersion, EncodedKey, EncodedValues)> for TransactionValue {
143	fn from((version, k, b): (CommitVersion, EncodedKey, EncodedValues)) -> Self {
144		Self::PendingIter {
145			version,
146			key: k,
147			values: b,
148		}
149	}
150}
151
152impl From<(CommitVersion, &EncodedKey, &EncodedValues)> for TransactionValue {
153	fn from((version, k, b): (CommitVersion, &EncodedKey, &EncodedValues)) -> Self {
154		Self::PendingIter {
155			version,
156			key: k.clone(),
157			values: b.clone(),
158		}
159	}
160}
161
162impl From<Pending> for TransactionValue {
163	fn from(pending: Pending) -> Self {
164		Self::Pending(pending)
165	}
166}
167
168impl From<Committed> for TransactionValue {
169	fn from(item: Committed) -> Self {
170		Self::Committed(item)
171	}
172}
173
174#[derive(Clone, Debug)]
175pub struct Committed {
176	pub(crate) key: EncodedKey,
177	pub(crate) values: EncodedValues,
178	pub(crate) version: CommitVersion,
179}
180
181impl From<MultiVersionValues> for Committed {
182	fn from(value: MultiVersionValues) -> Self {
183		Self {
184			key: value.key,
185			values: value.values,
186			version: value.version,
187		}
188	}
189}
190
191impl Committed {
192	pub fn key(&self) -> &EncodedKey {
193		&self.key
194	}
195
196	pub fn values(&self) -> &EncodedValues {
197		&self.values
198	}
199
200	pub fn version(&self) -> CommitVersion {
201		self.version
202	}
203}
204
205#[derive(Debug, PartialEq, Eq)]
206pub struct Pending {
207	pub delta: Delta,
208	pub version: CommitVersion,
209}
210
211impl PartialOrd for Pending {
212	fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
213		Some(self.cmp(other))
214	}
215}
216
217impl Ord for Pending {
218	fn cmp(&self, other: &Self) -> cmp::Ordering {
219		self.delta.key().cmp(other.delta.key()).then_with(|| Reverse(self.version).cmp(&Reverse(other.version)))
220	}
221}
222
223impl Clone for Pending {
224	fn clone(&self) -> Self {
225		Self {
226			version: self.version,
227			delta: self.delta.clone(),
228		}
229	}
230}
231
232impl Pending {
233	pub fn delta(&self) -> &Delta {
234		&self.delta
235	}
236
237	pub fn version(&self) -> CommitVersion {
238		self.version
239	}
240
241	pub fn into_components(self) -> (CommitVersion, Delta) {
242		(self.version, self.delta)
243	}
244
245	pub fn key(&self) -> &EncodedKey {
246		self.delta.key()
247	}
248
249	pub fn values(&self) -> Option<&EncodedValues> {
250		self.delta.values()
251	}
252
253	pub fn was_removed(&self) -> bool {
254		matches!(self.delta, Delta::Remove { .. })
255	}
256}