Skip to main content

thin_fetch/parcel/
mod.rs

1use std::{
2    io::{Read, Write},
3    ops::Deref,
4};
5
6use crate::error::Error;
7
8mod decoder;
9mod encoder;
10
11pub use decoder::{ParcelDecoder, ParcelItem};
12pub use encoder::ParcelEncoder;
13
14const MARKER_SEP: [u8; 4] = [0x30, 0x30, 0x30, 0x31];
15const MARKER_END: [u8; 4] = [0x30, 0x30, 0x30, 0x30];
16
17#[derive(Debug, Clone)]
18pub struct Parcel {
19    pub sections: Vec<Section>,
20}
21
22impl Parcel {
23    #[must_use]
24    pub fn new(sections: Vec<Section>) -> Self {
25        Self { sections }
26    }
27
28    /// Parse new parcel from a slice of bytes.
29    ///
30    /// # Errors
31    ///
32    /// Returns an error on parsing errors.
33    pub fn from_bytes(data: &[u8]) -> Result<Self, Error> {
34        let dec = ParcelDecoder::new(data);
35        dec.collect()
36    }
37
38    /// Parse new parcel from a slice of bytes.
39    ///
40    /// # Errors
41    ///
42    /// Returns an error on reading or parsing errors.
43    pub fn from_reader<R: Read>(reader: R) -> Result<Self, Error> {
44        let dec = ParcelDecoder::new(reader);
45        dec.collect()
46    }
47
48    /// Write parcel to a writer.
49    ///
50    /// # Errors
51    ///
52    /// Returns an error on writing or encoding errors.
53    pub fn write_to<W: Write>(&self, writer: W) -> Result<(), Error> {
54        let mut enc = ParcelEncoder::new(writer);
55
56        let mut first = true;
57
58        for section in &self.sections {
59            if first {
60                first = false;
61            } else {
62                enc.new_section()?;
63            }
64
65            for data in section.iter() {
66                enc.write_data(data)?;
67            }
68        }
69
70        enc.finish()
71    }
72}
73
74impl FromIterator<ParcelItem> for Parcel {
75    fn from_iter<T: IntoIterator<Item = ParcelItem>>(iter: T) -> Self {
76        let mut res = Self::new(vec![]);
77        let mut current = Section::new(vec![]);
78
79        for item in iter {
80            match item {
81                ParcelItem::Data(chunk) => current.chunks.push(chunk),
82                ParcelItem::Separator | ParcelItem::End => {
83                    res.sections.push(current);
84                    current = Section::new(vec![]);
85                }
86            }
87        }
88
89        if !current.is_empty() {
90            res.sections.push(current);
91        }
92
93        res
94    }
95}
96
97#[derive(Debug, Clone)]
98pub struct Section {
99    pub chunks: Vec<Vec<u8>>,
100}
101
102impl Section {
103    pub fn new(chunks: Vec<Vec<u8>>) -> Self {
104        Self { chunks }
105    }
106}
107
108impl Deref for Section {
109    type Target = Vec<Vec<u8>>;
110
111    fn deref(&self) -> &Self::Target {
112        &self.chunks
113    }
114}
115
116impl PartialEq<[&str]> for Section {
117    fn eq(&self, other: &[&str]) -> bool {
118        if self.chunks.len() != other.len() {
119            return false;
120        }
121
122        for (a, b) in self.chunks.iter().zip(other) {
123            if a != b.as_bytes() {
124                return false;
125            }
126        }
127
128        true
129    }
130}