1pub mod page;
2
3use std::num::NonZeroU32;
4
5use crate::{
6 header::{
7 FileFormatReadVersion, FileFormatWriteVersion, MagicHeaderString, PageSize,
8 ReservedBytesPerPage,
9 },
10 io::SqliteIo,
11 result::{SqliteError, SqliteResult},
12 traits::ParseBytes,
13};
14
15use self::page::Page;
16
17#[derive(Debug)]
18pub struct SqlitePager {
19 io: SqliteIo,
20 page_size: PageSize,
21 reserved_bytes_per_page: ReservedBytesPerPage,
22 }
25
26impl SqlitePager {
27 pub fn connect(mut io: SqliteIo) -> SqliteResult<Self> {
28 io.rewind()?;
29 const BYTES_TO_READ: usize = MagicHeaderString::LENGTH_BYTES
30 + PageSize::LENGTH_BYTES
31 + FileFormatWriteVersion::LENGTH_BYTES
32 + FileFormatReadVersion::LENGTH_BYTES
33 + ReservedBytesPerPage::LENGTH_BYTES;
34 let mut buf = [0u8; BYTES_TO_READ];
35
36 let bytes_read = io.read(&mut buf)?;
37 trace!("[{bytes_read}] Bytes read from [{}]", io.mode());
38 let pager = if bytes_read > 0 {
39 Self {
40 io,
41 page_size: PageSize::parse_bytes(&buf[16..=17])?,
42 reserved_bytes_per_page: ReservedBytesPerPage::parse_bytes(&[buf[20]])?,
43 }
44 } else {
45 Self {
46 io,
47 page_size: PageSize::default(),
48 reserved_bytes_per_page: ReservedBytesPerPage::default(),
49 }
50 };
51 Ok(pager)
52 }
53 pub fn first(&mut self) -> SqliteResult<Page> {
54 self.read(1)
55 }
56
57 pub fn read(&mut self, page_number: u32) -> SqliteResult<Page> {
58 if self.io.is_empty()? {
59 return Err(SqliteError::EmptyDb);
60 }
61 let page_number = NonZeroU32::new(page_number)
62 .ok_or(SqliteError::Custom("page number can't be zero `0`.".into()))?
63 .get();
64 let page_size = self.page_size().clone();
65 let offset_from_start = (page_number - 1) * u32::from(&page_size);
66 self.io.seek(offset_from_start.into())?;
68
69 match page_size {
70 PageSize::L512 => {
71 const BUF_SIZE: usize = 512;
72 let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
73 self.io.read(&mut buf)?;
75
76 Ok(Page {
77 length: page_size,
78 raw_data: buf.to_vec(),
79 })
80 }
81 PageSize::L1024 => {
82 const BUF_SIZE: usize = 1024;
83 let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
84 self.io.read(&mut buf)?;
85
86 Ok(Page {
87 length: page_size,
88 raw_data: buf.to_vec(),
89 })
90 }
91 PageSize::L2048 => {
92 const BUF_SIZE: usize = 2048;
93 let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
94 self.io.read(&mut buf)?;
95
96 Ok(Page {
97 length: page_size,
98 raw_data: buf.to_vec(),
99 })
100 }
101 PageSize::L4096 => {
102 const BUF_SIZE: usize = 4096;
103 let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
104 self.io.read(&mut buf)?;
105
106 Ok(Page {
107 length: page_size,
108 raw_data: buf.to_vec(),
109 })
110 }
111 PageSize::L8192 => {
112 const BUF_SIZE: usize = 8192;
113 let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
114 self.io.read(&mut buf)?;
115
116 Ok(Page {
117 length: page_size,
118 raw_data: buf.to_vec(),
119 })
120 }
121 PageSize::L16384 => {
122 const BUF_SIZE: usize = 16384;
123 let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
124 self.io.read(&mut buf)?;
125
126 Ok(Page {
127 length: page_size,
128 raw_data: buf.to_vec(),
129 })
130 }
131 PageSize::L32768 => {
132 const BUF_SIZE: usize = 32768;
133 let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
134 self.io.read(&mut buf)?;
135 let mut final_buffer = [0u8; Page::MAX_LENGTH];
136 for (idx, byte) in buf.iter().enumerate() {
137 final_buffer[idx] = *byte;
138 }
139 Ok(Page {
140 length: page_size,
141 raw_data: buf.to_vec(),
142 })
143 }
144 PageSize::L65536 => {
145 const BUF_SIZE: usize = 65536;
146 let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
147 self.io.read(&mut buf)?;
148 let mut final_buffer = [0u8; Page::MAX_LENGTH];
149 for (idx, byte) in buf.iter().enumerate() {
150 final_buffer[idx] = *byte;
151 }
152 Ok(Page {
153 length: page_size,
154 raw_data: buf.to_vec(),
155 })
156 }
157 }
158 }
159
160 pub fn page_size(&self) -> &PageSize {
161 &self.page_size
162 }
163
164 pub fn reserved_bytes_per_page(&self) -> &ReservedBytesPerPage {
165 &self.reserved_bytes_per_page
166 }
167
168 pub fn io(&self) -> &SqliteIo {
169 &self.io
170 }
171
172 pub fn io_mut(&mut self) -> &mut SqliteIo {
173 &mut self.io
174 }
175}