1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//! The mapper of the layer that can either live on the **heap** or **disk**

use std::{borrow::Cow, io::{Read, Seek, Write}};
use crate::{base::layer::get_u64, errors::Error};
use super::{Section, REWIND_IDX};

/// The mapper that holds all the writes to the layer and their location mapping in the database
#[derive(Debug)]
pub enum Mapper<'l> {
    /// A **read-write** version of the mapper on the **heap**
    Heap {
        /// The current write cursor to speed up sequential qrites
        write_cursor: (u64, usize),
        /// *self explainitory*
        mapper: Vec<Section<'l>>,
    },
    /// A **read-only** version of the mapper on the **disk**
    Disk,
}

/// A read-only iterator of the mapper that can live on either the heap or disk 
pub struct MapperIter<'l, Stream: Write + Read + Seek> {
    mapper: &'l Mapper<'l>,
    stream: &'l mut Stream,
    size: u64,
    /// the index in the mapper
    idx: usize,
    /// the **actual** location in the layer
    cursor: u64,
}

impl<'l> Default for Mapper<'l> {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl<'l> Mapper<'l> {
    /// Creates a new **heap**-based mapper
    #[inline]
    pub fn new() -> Self {
        Self::Heap {
            write_cursor: (0, 0),
            mapper: Vec::new(),
        }
    }

    /// Grabs the internal heap representation; if on disk, throw the `ReadOnly` error
    #[inline]
    pub fn get_writer(&mut self) -> Result<(&mut Vec<Section<'l>>, &mut (u64, usize)), Error> {
        if let Self::Heap { write_cursor, mapper } = self {
            Ok((mapper, write_cursor))
        } else {
            Err(Error::ReadOnly)
        }
    }

    /// Generates an iterator over the interal mapper, from the stream, size and layer read cursor position
    pub fn iter<'a, Stream: Read + Write + Seek>(&'a self, stream: &'a mut Stream, size: u64, cursor: u64) -> Result<MapperIter<'a, Stream>, Error> {
        stream.seek(std::io::SeekFrom::Start(cursor))?;
        Ok(MapperIter {
            mapper: self,
            stream,
            size,
            idx: 0,
            cursor: cursor - REWIND_IDX,
        })
    }
}

/// for unwrapping results within a function that returns an optional result concisely
macro_rules! optres {
    ($expr:expr) => {
        match $expr {
            Ok(x) => x,
            Err(e) => return Some(Err(e.into())),
        }
    }
}

impl<'l, Stream: Write + Read + Seek> Iterator for MapperIter<'l, Stream> {
    type Item = Result<Section<'l>, Error>;

    fn next(&mut self) -> Option<Self::Item> { // probably not a issue but, it loads the entire layer section into memory
        Some(Ok(match self.mapper {
            Mapper::Heap { mapper, .. } => {
                if self.idx == mapper.len() { return None };
                let out = mapper[self.idx].clone();
                self.idx += 1;
                out
            },
            Mapper::Disk => {
                // check for end of layer
                if self.cursor == self.size { return None };
                
                // read bounds
                let mut buffer = [0u8; (u64::BITS as usize/8) * 2]; // buffer for two `u64` values: `bounds.start` & `bounds.end`
                match self.stream.read_exact(&mut buffer) {
                    Ok(_) => (),
                    Err(_) => return Some(Err(Error::DBCorrupt(Box::new(Error::InvalidLayer)))),
                }

                let bounds = optres!(get_u64(&buffer, 0..8))..optres!(get_u64(&buffer, 8..16));

                // load layer section data into the heap
                let size = if let Some(x) = bounds.end.checked_sub(bounds.start) { x } else {return Some(Err(Error::DBCorrupt(Box::new(Error::InvalidLayer)))) };
                let mut data = vec![0u8; size as usize];
                optres!(self.stream.read_exact(&mut data));

                self.cursor += size;
                (bounds, Cow::Owned(data))
            },
        }))
    }
}