binary_cookies/sync/
cookie.rs

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