quill_sql/recovery/wal/codec/
page.rs

1use 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
12pub fn encode_page_write(body: &PageWritePayload) -> Vec<u8> {
13    // Page/PageWrite (rmid=Page, info=0)
14    // body: page_id(4) + prev_page_lsn(8) + image_len(4) + page_image[]
15    let mut buf = Vec::with_capacity(4 + 8 + 4 + body.page_image.len());
16    buf.extend_from_slice(&body.page_id.to_le_bytes());
17    buf.extend_from_slice(&body.prev_page_lsn.to_le_bytes());
18    buf.extend_from_slice(&(body.page_image.len() as u32).to_le_bytes());
19    buf.extend_from_slice(&body.page_image);
20    buf
21}
22
23pub fn decode_page_write(bytes: &[u8]) -> QuillSQLResult<PageWritePayload> {
24    if bytes.len() < 4 + 8 + 4 {
25        return Err(QuillSQLError::Internal(
26            "PageWrite payload too short".to_string(),
27        ));
28    }
29    let page_id = u32::from_le_bytes(bytes[0..4].try_into().unwrap()) as PageId;
30    let prev_page_lsn = u64::from_le_bytes(bytes[4..12].try_into().unwrap()) as Lsn;
31    let image_len = u32::from_le_bytes(bytes[12..16].try_into().unwrap()) as usize;
32    if bytes.len() != 16 + image_len {
33        return Err(QuillSQLError::Internal(
34            "PageWrite payload length mismatch".to_string(),
35        ));
36    }
37    let page_image = bytes[16..].to_vec();
38    Ok(PageWritePayload {
39        page_id,
40        prev_page_lsn,
41        page_image,
42    })
43}