quill_sql/recovery/wal/codec/
txn.rs1use crate::error::{QuillSQLError, QuillSQLResult};
2use crate::transaction::TransactionId;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5#[repr(u8)]
6pub enum TransactionRecordKind {
7 Begin = 1,
8 Commit = 2,
9 Abort = 3,
10}
11
12impl TransactionRecordKind {
13 pub fn from_u8(value: u8) -> QuillSQLResult<Self> {
14 match value {
15 1 => Ok(TransactionRecordKind::Begin),
16 2 => Ok(TransactionRecordKind::Commit),
17 3 => Ok(TransactionRecordKind::Abort),
18 other => Err(QuillSQLError::Internal(format!(
19 "Unknown transaction record kind: {}",
20 other
21 ))),
22 }
23 }
24}
25
26#[derive(Debug, Clone)]
27pub struct TransactionPayload {
28 pub marker: TransactionRecordKind,
29 pub txn_id: TransactionId,
30}
31
32pub fn encode_transaction(body: &TransactionPayload) -> (u8, Vec<u8>) {
33 let mut buf = Vec::with_capacity(8);
34 buf.extend_from_slice(&body.txn_id.to_le_bytes());
35 (body.marker as u8, buf)
36}
37
38pub fn decode_transaction(bytes: &[u8], info: u8) -> QuillSQLResult<TransactionPayload> {
39 if bytes.len() != 8 {
40 return Err(QuillSQLError::Internal(
41 "Transaction payload must be 8 bytes".to_string(),
42 ));
43 }
44 let txn_id = u64::from_le_bytes(bytes[0..8].try_into().unwrap()) as TransactionId;
45 let marker = TransactionRecordKind::from_u8(info)?;
46 Ok(TransactionPayload { marker, txn_id })
47}