binary_cookies/sync/
page.rs

1use std::io::Read;
2
3use snafu::ResultExt;
4
5use crate::{
6    decode::{
7        cookies::CookiesOffset,
8        pages::{PageFsm, PagesOffset},
9        DecodeResult, OffsetSize,
10    },
11    error::{self, Result},
12    sync::{cookie::CookieHandle, cursor::CookieCursor},
13};
14
15#[derive(Clone)]
16#[derive(Debug)]
17pub struct PagesHandle<'a, F: CookieCursor> {
18    pub(crate) file: &'a F,
19    pub(crate) offset: PagesOffset,
20}
21
22impl<'a, F: CookieCursor> PagesHandle<'a, F> {
23    pub fn decoders(
24        &self,
25    ) -> impl Iterator<Item = PageDecoder<'_, <F as CookieCursor>::Cursor<'_>, F>> {
26        self.offset
27            .offset_sizes
28            .iter()
29            .map(|&OffsetSize { offset, size }| PageDecoder {
30                file: self.file,
31                rd: self.file.cursor_at(offset),
32                offset,
33                size,
34            })
35    }
36
37    pub fn into_decoders(
38        self,
39    ) -> impl Iterator<Item = PageDecoder<'a, <F as CookieCursor>::Cursor<'a>, F>> {
40        self.offset
41            .offset_sizes
42            .into_iter()
43            .map(|OffsetSize { offset, size }| PageDecoder {
44                file: self.file,
45                rd: self.file.cursor_at(offset),
46                offset,
47                size,
48            })
49    }
50}
51
52#[derive(Clone, Copy)]
53#[derive(Debug)]
54#[derive(PartialEq, Eq, PartialOrd, Ord)]
55pub struct PageDecoder<'a, R: Read, F: CookieCursor> {
56    pub(crate) file: &'a F,
57    pub(crate) rd: R,
58    pub(crate) offset: u64,
59    pub(crate) size: u32,
60}
61
62impl<'a, R: Read, F: CookieCursor> PageDecoder<'a, R, F> {
63    pub fn decode(&mut self) -> Result<CookieHandle<'a, F>> {
64        let mut fsm = PageFsm::new();
65        loop {
66            self.rd
67                .read_exact(fsm.buffer.space())
68                .context(error::ReadSnafu)?;
69            let count = fsm.buffer.available_space();
70            fsm.buffer.fill(count);
71            match fsm.process()? {
72                DecodeResult::Continue(fsm_) => {
73                    fsm = fsm_;
74                    continue;
75                },
76                DecodeResult::Done((cookie_offset_in_page, _)) => {
77                    let cookies_offset =
78                        CookiesOffset::new(self.offset, self.size, &cookie_offset_in_page);
79                    return Ok(CookieHandle::new(self.file, cookies_offset));
80                },
81            }
82        }
83    }
84}