binary_cookies/tokio/
cookie.rs

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