quill_sql/storage/codec/
freelist_page.rs

1use crate::buffer::PAGE_SIZE;
2use crate::error::QuillSQLResult;
3use crate::storage::codec::{CommonCodec, DecodedData};
4use crate::storage::page::{FreelistPage, FreelistPageHeader};
5
6pub struct FreelistPageHeaderCodec;
7
8impl FreelistPageHeaderCodec {
9    pub fn encode(header: &FreelistPageHeader) -> Vec<u8> {
10        let mut bytes = Vec::new();
11        bytes.extend(CommonCodec::encode_u32(header.next_page_id));
12        bytes.extend(CommonCodec::encode_u32(header.current_size));
13        bytes.extend(CommonCodec::encode_u32(header.max_size));
14        bytes
15    }
16
17    pub fn decode(bytes: &[u8]) -> QuillSQLResult<DecodedData<FreelistPageHeader>> {
18        let mut left_bytes = bytes;
19
20        let (next_page_id, offset) = CommonCodec::decode_u32(left_bytes)?;
21        left_bytes = &left_bytes[offset..];
22
23        let (current_size, offset) = CommonCodec::decode_u32(left_bytes)?;
24        left_bytes = &left_bytes[offset..];
25
26        let (max_size, offset) = CommonCodec::decode_u32(left_bytes)?;
27        left_bytes = &left_bytes[offset..];
28
29        Ok((
30            FreelistPageHeader {
31                next_page_id,
32                current_size,
33                max_size,
34            },
35            bytes.len() - left_bytes.len(),
36        ))
37    }
38}
39
40pub struct FreelistPageCodec;
41
42impl FreelistPageCodec {
43    pub fn encode(page: &FreelistPage) -> Vec<u8> {
44        let mut bytes = Vec::new();
45        bytes.extend(FreelistPageHeaderCodec::encode(&page.header));
46        for i in 0..page.header.current_size {
47            bytes.extend(CommonCodec::encode_u32(page.array[i as usize]))
48        }
49        // make sure length of bytes is BUSTUBX_PAGE_SIZE
50        assert!(bytes.len() <= PAGE_SIZE);
51        bytes.extend(vec![0; PAGE_SIZE - bytes.len()]);
52        bytes
53    }
54
55    pub fn decode(bytes: &[u8]) -> QuillSQLResult<DecodedData<FreelistPage>> {
56        let mut left_bytes = bytes;
57
58        let (header, offset) = FreelistPageHeaderCodec::decode(left_bytes)?;
59        left_bytes = &left_bytes[offset..];
60
61        let mut array = Vec::new();
62        for _ in 0..header.current_size {
63            let (page_id, offset) = CommonCodec::decode_u32(left_bytes)?;
64            left_bytes = &left_bytes[offset..];
65            array.push(page_id);
66        }
67
68        Ok((FreelistPage { header, array }, PAGE_SIZE))
69    }
70}
71
72#[cfg(test)]
73mod tests {
74    use crate::storage::codec::FreelistPageCodec;
75    use crate::storage::page::{FreelistPage, FreelistPageHeader, FREELIST_PAGE_MAX_SIZE};
76
77    #[test]
78    fn freelist_page_codec() {
79        let page = FreelistPage {
80            header: FreelistPageHeader {
81                next_page_id: 1,
82                current_size: 3,
83                max_size: *FREELIST_PAGE_MAX_SIZE as u32,
84            },
85            array: vec![5, 6, 8],
86        };
87        let (new_page, _) = FreelistPageCodec::decode(&FreelistPageCodec::encode(&page)).unwrap();
88        assert_eq!(page, new_page);
89    }
90}