oxigdal_streaming/
mmap.rs1use std::fs::File;
9use std::io::{Read, Seek, SeekFrom};
10use std::path::{Path, PathBuf};
11
12use crate::error::StreamingError;
13
14pub struct MappedFile {
16 path: PathBuf,
17 data: Vec<u8>,
18 file_size: u64,
19}
20
21impl MappedFile {
22 pub fn open(path: impl AsRef<Path>) -> Result<Self, StreamingError> {
27 let path = path.as_ref().to_path_buf();
28 let mut file = File::open(&path)?;
29 let file_size = file.seek(SeekFrom::End(0))?;
30 file.seek(SeekFrom::Start(0))?;
31
32 let mut data = Vec::with_capacity(file_size as usize);
33 file.read_to_end(&mut data)?;
34
35 Ok(Self {
36 path,
37 data,
38 file_size,
39 })
40 }
41
42 pub fn read_range(&self, start: u64, len: usize) -> Result<&[u8], StreamingError> {
47 let start_usize = start as usize;
48 let end = start_usize + len;
49 if end > self.data.len() {
50 return Err(StreamingError::Other(format!(
51 "Range [{start_usize}, {end}) out of bounds (file size {})",
52 self.file_size
53 )));
54 }
55 Ok(&self.data[start_usize..end])
56 }
57
58 #[must_use]
60 pub fn as_slice(&self) -> &[u8] {
61 &self.data
62 }
63
64 #[must_use]
66 pub fn file_size(&self) -> u64 {
67 self.file_size
68 }
69
70 #[must_use]
72 pub fn path(&self) -> &Path {
73 &self.path
74 }
75
76 #[must_use]
78 pub fn is_empty(&self) -> bool {
79 self.data.is_empty()
80 }
81
82 pub fn read_ranges(&self, ranges: &[(u64, usize)]) -> Vec<Result<&[u8], StreamingError>> {
86 ranges
87 .iter()
88 .map(|(start, len)| self.read_range(*start, *len))
89 .collect()
90 }
91}
92
93#[derive(Debug, Clone, PartialEq, Eq)]
97pub enum PrefetchPriority {
98 Low,
100 Normal,
102 High,
104}
105
106impl PartialOrd for PrefetchPriority {
107 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
108 Some(self.cmp(other))
109 }
110}
111
112impl Ord for PrefetchPriority {
113 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
114 let rank = |p: &PrefetchPriority| match p {
115 PrefetchPriority::Low => 0u8,
116 PrefetchPriority::Normal => 1,
117 PrefetchPriority::High => 2,
118 };
119 rank(self).cmp(&rank(other))
120 }
121}
122
123#[derive(Debug, Clone)]
125pub struct PrefetchHint {
126 pub offset: u64,
128 pub length: usize,
130 pub priority: PrefetchPriority,
132}
133
134pub struct PrefetchScheduler {
136 hints: Vec<PrefetchHint>,
137 max_prefetch_bytes: usize,
138}
139
140impl PrefetchScheduler {
141 #[must_use]
143 pub fn new(max_prefetch_bytes: usize) -> Self {
144 Self {
145 hints: Vec::new(),
146 max_prefetch_bytes,
147 }
148 }
149
150 pub fn add_hint(&mut self, hint: PrefetchHint) {
152 self.hints.push(hint);
153 }
154
155 #[must_use]
157 pub fn sorted_hints(&self) -> Vec<&PrefetchHint> {
158 let mut sorted: Vec<&PrefetchHint> = self.hints.iter().collect();
159 sorted.sort_by(|a, b| b.priority.cmp(&a.priority).then(a.offset.cmp(&b.offset)));
160 sorted
161 }
162
163 #[must_use]
165 pub fn hint_count(&self) -> usize {
166 self.hints.len()
167 }
168
169 #[must_use]
171 pub fn total_bytes_hinted(&self) -> usize {
172 self.hints.iter().map(|h| h.length).sum()
173 }
174
175 #[must_use]
177 pub fn max_prefetch_bytes(&self) -> usize {
178 self.max_prefetch_bytes
179 }
180
181 pub fn clear(&mut self) {
183 self.hints.clear();
184 }
185}