stack_db/base/layer/
mapper.rs1use std::{borrow::Cow, io::{Read, Seek, Write}};
4use crate::{base::layer::get_u64, errors::Error};
5use super::{Section, REWIND_IDX};
6
7#[derive(Debug)]
9pub enum Mapper<'l> {
10 Heap {
12 write_cursor: (u64, usize),
14 mapper: Vec<Section<'l>>,
16 },
17 Disk,
19}
20
21pub struct MapperIter<'l, Stream: Write + Read + Seek> {
23 mapper: &'l Mapper<'l>,
24 stream: &'l mut Stream,
25 size: u64,
26 idx: usize,
28 cursor: u64,
30}
31
32impl<'l> Default for Mapper<'l> {
33 #[inline]
34 fn default() -> Self {
35 Self::new()
36 }
37}
38
39impl<'l> Mapper<'l> {
40 #[inline]
42 pub fn new() -> Self {
43 Self::Heap {
44 write_cursor: (0, 0),
45 mapper: Vec::new(),
46 }
47 }
48
49 #[inline]
51 pub fn get_writer(&mut self) -> Result<(&mut Vec<Section<'l>>, &mut (u64, usize)), Error> {
52 if let Self::Heap { write_cursor, mapper } = self {
53 Ok((mapper, write_cursor))
54 } else {
55 Err(Error::ReadOnly)
56 }
57 }
58
59 pub fn iter<'a, Stream: Read + Write + Seek>(&'a self, stream: &'a mut Stream, size: u64, cursor: u64) -> Result<MapperIter<'a, Stream>, Error> {
61 stream.seek(std::io::SeekFrom::Start(cursor))?;
62 Ok(MapperIter {
63 mapper: self,
64 stream,
65 size,
66 idx: 0,
67 cursor: cursor - REWIND_IDX,
68 })
69 }
70}
71
72macro_rules! optres {
74 ($expr:expr) => {
75 match $expr {
76 Ok(x) => x,
77 Err(e) => return Some(Err(e.into())),
78 }
79 }
80}
81
82impl<'l, Stream: Write + Read + Seek> Iterator for MapperIter<'l, Stream> {
83 type Item = Result<Section<'l>, Error>;
84
85 fn next(&mut self) -> Option<Self::Item> { Some(Ok(match self.mapper {
87 Mapper::Heap { mapper, .. } => {
88 if self.idx == mapper.len() { return None };
89 let out = mapper[self.idx].clone();
90 self.idx += 1;
91 out
92 },
93 Mapper::Disk => {
94 if self.cursor == self.size { return None };
96
97 let mut buffer = [0u8; (u64::BITS as usize/8) * 2]; match self.stream.read_exact(&mut buffer) {
100 Ok(_) => (),
101 Err(_) => return Some(Err(Error::DBCorrupt(Box::new(Error::InvalidLayer)))),
102 }
103
104 let bounds = optres!(get_u64(&buffer, 0..8))..optres!(get_u64(&buffer, 8..16));
105
106 let size = if let Some(x) = bounds.end.checked_sub(bounds.start) { x } else {return Some(Err(Error::DBCorrupt(Box::new(Error::InvalidLayer)))) };
108 let mut data = vec![0u8; size as usize];
109 optres!(self.stream.read_exact(&mut data));
110
111 self.cursor += size;
112 (bounds, Cow::Owned(data))
113 },
114 }))
115 }
116}