1#![cfg_attr(feature = "nightly", deny(missing_docs))]
2#![cfg_attr(feature = "nightly", feature(external_doc))]
3#![cfg_attr(feature = "nightly", doc(include = "../README.md"))]
4#![cfg_attr(test, deny(warnings))]
5
6mod iter;
7mod page;
8
9pub use crate::iter::Iter;
10pub use crate::page::Page;
11
12use std::fs::File;
13use std::io;
14use std::io::Read;
15
16#[derive(Debug)]
20pub struct Pager {
21 pages: Vec<Option<Page>>,
22 page_size: usize,
23}
24
25impl Pager {
26 #[inline]
31 pub fn new(page_size: usize) -> Self {
32 Pager {
33 page_size,
34 pages: Vec::new(),
35 }
36 }
37
38 #[inline]
72 pub fn from_file(
73 file: &mut File,
74 page_size: usize,
75 offset: Option<usize>,
76 ) -> Result<Self, io::Error> {
77 let offset = offset.unwrap_or(0);
78 let len = file.metadata()?.len() as usize - offset;
79
80 if len % page_size != 0 {
81 return Err(io::Error::new(
82 io::ErrorKind::Other,
83 format!(
84 "<memory-pager>: Reader len ({}) is not a multiple of {}",
85 len, page_size
86 ),
87 ));
88 }
89
90 let page_count = len / page_size;
91 let mut pages = Vec::with_capacity(page_count);
92 let mut buf = vec![0; page_size];
93
94 for index in 0..page_count {
95 let bytes_read = file.read(&mut buf)?;
96
97 if bytes_read < page_size {
99 break;
100 }
101
102 if is_zeroed(&buf) {
104 pages.push(None);
105 } else {
106 pages.push(Some(Page::new(index, buf)));
107 buf = vec![0; page_size];
108 }
109 }
110
111 Ok(Self { pages, page_size })
112 }
113
114 #[inline]
118 pub fn get_mut_or_alloc(&mut self, page_num: usize) -> &mut Page {
119 if page_num >= self.pages.len() {
120 self.grow_pages(page_num);
121 }
122
123 if self.pages[page_num].is_none() {
125 let buf = vec![0; self.page_size];
126 let page = Page::new(page_num, buf);
127 self.pages[page_num] = Some(page);
128 }
129
130 self.pages[page_num].as_mut().unwrap()
131 }
132
133 #[inline]
137 pub fn get(&self, page_num: usize) -> Option<&Page> {
138 self.pages.get(page_num).and_then(|page| page.as_ref())
139 }
140
141 #[inline]
146 pub fn get_mut(&mut self, page_num: usize) -> Option<&mut Page> {
147 self.pages.get_mut(page_num).and_then(|page| page.as_mut())
148 }
149
150 #[inline]
152 fn grow_pages(&mut self, index: usize) {
153 self.pages.resize(index + 1, None);
154 }
155
156 #[inline]
159 pub fn len(&self) -> usize {
160 self.pages.len()
161 }
162
163 #[inline]
165 pub fn is_empty(&self) -> bool {
166 self.pages.is_empty()
167 }
168
169 #[inline]
171 pub fn page_size(&self) -> usize {
172 self.page_size
173 }
174
175 #[inline]
177 pub fn iter(&self) -> Iter<'_> {
178 Iter::new(self)
179 }
180}
181
182impl Default for Pager {
187 fn default() -> Self {
188 Pager::new(1024)
189 }
190}
191
192#[inline]
193fn is_zeroed(vec: &[u8]) -> bool {
194 for byte in vec {
195 if *byte != 0 {
196 return false;
197 }
198 }
199 true
200}