1use reifydb_codec::{key::encoded::EncodedKey, row::bytes::EncodedBytes};
5use reifydb_value::util::cowvec::CowVec;
6use reifydb_wal::{
7 body::Body,
8 error::{Result, WalError},
9};
10
11use crate::{
12 common::CommitVersion,
13 delta::{Delta, RemoveAnnounce, SetPre},
14 key::any::TaggedKey,
15};
16
17const OP_SET: u8 = 0;
18const OP_REMOVE: u8 = 1;
19
20const PRE_ABSENT: u8 = 0;
21const PRE_PRESENT: u8 = 1;
22
23const ANNOUNCE_SILENT: u8 = 0;
24const ANNOUNCE_ANNOUNCED: u8 = 1;
25const ANNOUNCE_UNOBSERVED: u8 = 2;
26
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub struct CommitRecord {
29 pub version: CommitVersion,
30 pub deltas: Vec<Delta>,
31}
32
33impl CommitRecord {
34 pub const KIND: u32 = 1;
35
36 pub fn stamp_version(encoded: &mut [u8], version: CommitVersion) {
37 encoded[..8].copy_from_slice(&version.0.to_le_bytes());
38 }
39
40 pub fn encode_refs(version: CommitVersion, deltas: &[&Delta], out: &mut Vec<u8>) {
41 out.extend_from_slice(&version.0.to_le_bytes());
42 put_len(out, deltas.len());
43 for delta in deltas {
44 match delta {
45 Delta::Set {
46 key,
47 bytes,
48 pre,
49 } => {
50 out.push(OP_SET);
51 put_bytes(out, key.encode().as_bytes());
52 put_bytes(out, bytes.as_ref());
53 match pre {
54 SetPre::Absent => out.push(PRE_ABSENT),
55 SetPre::Present(pre) => {
56 out.push(PRE_PRESENT);
57 put_bytes(out, pre.as_ref());
58 }
59 SetPre::Unknown => panic!(
60 "commit {} has an unresolved pre for key {:?}",
61 version.0, key
62 ),
63 }
64 }
65 Delta::Remove {
66 key,
67 announce,
68 } => {
69 out.push(OP_REMOVE);
70 put_bytes(out, key.encode().as_bytes());
71 match announce {
72 RemoveAnnounce::Silent => out.push(ANNOUNCE_SILENT),
73 RemoveAnnounce::Announced {
74 pre,
75 } => {
76 out.push(ANNOUNCE_ANNOUNCED);
77 put_bytes(out, pre.as_ref());
78 }
79 RemoveAnnounce::Unobserved {
80 pre,
81 } => {
82 out.push(ANNOUNCE_UNOBSERVED);
83 put_bytes(out, pre.as_ref());
84 }
85 }
86 }
87 }
88 }
89 }
90}
91
92impl Body for CommitRecord {
93 fn kind(&self) -> u32 {
94 Self::KIND
95 }
96
97 fn encode(&self, out: &mut Vec<u8>) {
98 Self::encode_refs(self.version, &self.deltas.iter().collect::<Vec<_>>(), out);
99 }
100
101 fn decode(kind: u32, bytes: &[u8]) -> Result<Self> {
102 if kind != Self::KIND {
103 return Err(WalError::Body(format!("unknown commit record kind {kind}")));
104 }
105 let mut reader = Reader {
106 bytes,
107 at: 0,
108 };
109 let version = CommitVersion(reader.u64()?);
110 let count = reader.u32()?;
111 let mut deltas = Vec::new();
112 for _ in 0..count {
113 deltas.push(reader.delta()?);
114 }
115 if reader.at != bytes.len() {
116 return Err(WalError::Body(format!(
117 "{} trailing bytes after delta {count}",
118 bytes.len() - reader.at
119 )));
120 }
121 Ok(Self {
122 version,
123 deltas,
124 })
125 }
126}
127
128#[derive(Debug, Clone, PartialEq, Eq)]
129pub struct SingleRecord {
130 pub deltas: Vec<Delta>,
131}
132
133impl SingleRecord {
134 pub const KIND: u32 = 2;
135
136 pub fn encode_deltas(deltas: &[Delta], out: &mut Vec<u8>) {
137 put_len(out, deltas.len());
138 for delta in deltas {
139 match delta {
140 Delta::Set {
141 key,
142 bytes,
143 ..
144 } => {
145 out.push(OP_SET);
146 put_bytes(out, key.encode().as_bytes());
147 put_bytes(out, bytes.as_ref());
148 }
149 Delta::Remove {
150 key,
151 ..
152 } => {
153 out.push(OP_REMOVE);
154 put_bytes(out, key.encode().as_bytes());
155 }
156 }
157 }
158 }
159}
160
161impl Body for SingleRecord {
162 fn kind(&self) -> u32 {
163 Self::KIND
164 }
165
166 fn encode(&self, out: &mut Vec<u8>) {
167 Self::encode_deltas(&self.deltas, out);
168 }
169
170 fn decode(kind: u32, bytes: &[u8]) -> Result<Self> {
171 if kind != Self::KIND {
172 return Err(WalError::Body(format!("unknown single record kind {kind}")));
173 }
174 let mut reader = Reader {
175 bytes,
176 at: 0,
177 };
178 let count = reader.u32()?;
179 let mut deltas = Vec::new();
180 for _ in 0..count {
181 deltas.push(reader.single_delta()?);
182 }
183 if reader.at != bytes.len() {
184 return Err(WalError::Body(format!(
185 "{} trailing bytes after single delta {count}",
186 bytes.len() - reader.at
187 )));
188 }
189 Ok(Self {
190 deltas,
191 })
192 }
193}
194
195#[derive(Debug, Clone, PartialEq, Eq)]
196pub enum WalRecord {
197 Multi(CommitRecord),
198 Single(SingleRecord),
199}
200
201impl Body for WalRecord {
202 fn kind(&self) -> u32 {
203 match self {
204 Self::Multi(record) => record.kind(),
205 Self::Single(record) => record.kind(),
206 }
207 }
208
209 fn encode(&self, out: &mut Vec<u8>) {
210 match self {
211 Self::Multi(record) => record.encode(out),
212 Self::Single(record) => record.encode(out),
213 }
214 }
215
216 fn decode(kind: u32, bytes: &[u8]) -> Result<Self> {
217 match kind {
218 CommitRecord::KIND => Ok(Self::Multi(CommitRecord::decode(kind, bytes)?)),
219 SingleRecord::KIND => Ok(Self::Single(SingleRecord::decode(kind, bytes)?)),
220 kind => Err(WalError::Body(format!("unknown wal record kind {kind}"))),
221 }
222 }
223}
224
225fn put_len(out: &mut Vec<u8>, len: usize) {
226 let len = u32::try_from(len).unwrap_or_else(|_| panic!("commit record length {len} does not fit in u32"));
227 out.extend_from_slice(&len.to_le_bytes());
228}
229
230fn put_bytes(out: &mut Vec<u8>, bytes: &[u8]) {
231 put_len(out, bytes.len());
232 out.extend_from_slice(bytes);
233}
234
235struct Reader<'a> {
236 bytes: &'a [u8],
237 at: usize,
238}
239
240impl<'a> Reader<'a> {
241 fn take(&mut self, len: usize) -> Result<&'a [u8]> {
242 let end = self.at.checked_add(len).filter(|end| *end <= self.bytes.len()).ok_or_else(|| {
243 WalError::Body(format!(
244 "truncated at byte {}: needs {len} of {} remaining",
245 self.at,
246 self.bytes.len() - self.at
247 ))
248 })?;
249 let slice = &self.bytes[self.at..end];
250 self.at = end;
251 Ok(slice)
252 }
253
254 fn u8(&mut self) -> Result<u8> {
255 Ok(self.take(1)?[0])
256 }
257
258 fn u32(&mut self) -> Result<u32> {
259 let mut buf = [0u8; 4];
260 buf.copy_from_slice(self.take(4)?);
261 Ok(u32::from_le_bytes(buf))
262 }
263
264 fn u64(&mut self) -> Result<u64> {
265 let mut buf = [0u8; 8];
266 buf.copy_from_slice(self.take(8)?);
267 Ok(u64::from_le_bytes(buf))
268 }
269
270 fn bytes(&mut self) -> Result<&'a [u8]> {
271 let len = self.u32()? as usize;
272 self.take(len)
273 }
274
275 fn encoded(&mut self) -> Result<EncodedBytes> {
276 Ok(EncodedBytes(CowVec::new(self.bytes()?.to_vec())))
277 }
278
279 fn key(&mut self) -> Result<TaggedKey> {
280 let at = self.at;
281 let key = EncodedKey::new(self.bytes()?);
282 TaggedKey::decode(&key).ok_or_else(|| WalError::Body(format!("undecodable key at byte {at}")))
283 }
284
285 fn delta(&mut self) -> Result<Delta> {
286 let at = self.at;
287 match self.u8()? {
288 OP_SET => {
289 let key = self.key()?;
290 let bytes = self.encoded()?;
291 let pre_at = self.at;
292 let pre = match self.u8()? {
293 PRE_ABSENT => SetPre::Absent,
294 PRE_PRESENT => SetPre::Present(self.encoded()?),
295 tag => {
296 return Err(WalError::Body(format!(
297 "unknown pre tag {tag} at byte {pre_at}"
298 )));
299 }
300 };
301 Ok(Delta::Set {
302 key,
303 bytes,
304 pre,
305 })
306 }
307 OP_REMOVE => {
308 let key = self.key()?;
309 let announce_at = self.at;
310 let announce = match self.u8()? {
311 ANNOUNCE_SILENT => RemoveAnnounce::Silent,
312 ANNOUNCE_ANNOUNCED => RemoveAnnounce::Announced {
313 pre: self.encoded()?,
314 },
315 ANNOUNCE_UNOBSERVED => RemoveAnnounce::Unobserved {
316 pre: self.encoded()?,
317 },
318 tag => {
319 return Err(WalError::Body(format!(
320 "unknown announce tag {tag} at byte {announce_at}"
321 )));
322 }
323 };
324 Ok(Delta::Remove {
325 key,
326 announce,
327 })
328 }
329 op => Err(WalError::Body(format!("unknown delta op {op} at byte {at}"))),
330 }
331 }
332
333 fn single_delta(&mut self) -> Result<Delta> {
334 let at = self.at;
335 match self.u8()? {
336 OP_SET => {
337 let key = self.key()?;
338 let bytes = self.encoded()?;
339 Ok(Delta::Set {
340 key,
341 bytes,
342 pre: SetPre::Unknown,
343 })
344 }
345 OP_REMOVE => Ok(Delta::remove_silent(self.key()?)),
346 op => Err(WalError::Body(format!("unknown single delta op {op} at byte {at}"))),
347 }
348 }
349}