quill_sql/recovery/wal/codec/
page.rs1use crate::buffer::PageId;
2use crate::error::{QuillSQLError, QuillSQLResult};
3use crate::recovery::Lsn;
4
5#[derive(Debug, Clone)]
6pub struct PageWritePayload {
7 pub page_id: PageId,
8 pub prev_page_lsn: Lsn,
9 pub page_image: Vec<u8>,
10}
11
12#[derive(Debug, Clone)]
13pub struct PageDeltaPayload {
14 pub page_id: PageId,
15 pub prev_page_lsn: Lsn,
16 pub offset: u16,
17 pub data: Vec<u8>,
18}
19
20pub fn encode_page_write(body: &PageWritePayload) -> Vec<u8> {
21 let mut buf = Vec::with_capacity(4 + 8 + 4 + body.page_image.len());
24 buf.extend_from_slice(&body.page_id.to_le_bytes());
25 buf.extend_from_slice(&body.prev_page_lsn.to_le_bytes());
26 buf.extend_from_slice(&(body.page_image.len() as u32).to_le_bytes());
27 buf.extend_from_slice(&body.page_image);
28 buf
29}
30
31pub fn encode_page_delta(body: &PageDeltaPayload) -> Vec<u8> {
32 let mut buf = Vec::with_capacity(4 + 8 + 2 + 4 + body.data.len());
35 buf.extend_from_slice(&body.page_id.to_le_bytes());
36 buf.extend_from_slice(&body.prev_page_lsn.to_le_bytes());
37 buf.extend_from_slice(&body.offset.to_le_bytes());
38 buf.extend_from_slice(&(body.data.len() as u32).to_le_bytes());
39 buf.extend_from_slice(&body.data);
40 buf
41}
42
43pub fn decode_page_write(bytes: &[u8]) -> QuillSQLResult<PageWritePayload> {
44 if bytes.len() < 4 + 8 + 4 {
45 return Err(QuillSQLError::Internal(
46 "PageWrite payload too short".to_string(),
47 ));
48 }
49 let page_id = u32::from_le_bytes(bytes[0..4].try_into().unwrap()) as PageId;
50 let prev_page_lsn = u64::from_le_bytes(bytes[4..12].try_into().unwrap()) as Lsn;
51 let image_len = u32::from_le_bytes(bytes[12..16].try_into().unwrap()) as usize;
52 if bytes.len() != 16 + image_len {
53 return Err(QuillSQLError::Internal(
54 "PageWrite payload length mismatch".to_string(),
55 ));
56 }
57 let page_image = bytes[16..].to_vec();
58 Ok(PageWritePayload {
59 page_id,
60 prev_page_lsn,
61 page_image,
62 })
63}
64
65pub fn decode_page_delta(bytes: &[u8]) -> QuillSQLResult<PageDeltaPayload> {
66 if bytes.len() < 4 + 8 + 2 + 4 {
67 return Err(QuillSQLError::Internal(
68 "PageDelta payload too short".to_string(),
69 ));
70 }
71 let page_id = u32::from_le_bytes(bytes[0..4].try_into().unwrap()) as PageId;
72 let prev_page_lsn = u64::from_le_bytes(bytes[4..12].try_into().unwrap()) as Lsn;
73 let offset = u16::from_le_bytes(bytes[12..14].try_into().unwrap());
74 let data_len = u32::from_le_bytes(bytes[14..18].try_into().unwrap()) as usize;
75 if bytes.len() != 18 + data_len {
76 return Err(QuillSQLError::Internal(
77 "PageDelta payload length mismatch".to_string(),
78 ));
79 }
80 let data = bytes[18..].to_vec();
81 Ok(PageDeltaPayload {
82 page_id,
83 prev_page_lsn,
84 offset,
85 data,
86 })
87}