quill_sql/storage/codec/
freelist_page.rs1use 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 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}