bytecodec/
monolithic.rs

1//! Monolithic encoder and decoder.
2use crate::bytes::BytesEncoder;
3use crate::{ByteCount, Decode, Encode, Eos, ErrorKind, Result};
4use std::io::{self, Read, Write};
5
6/// This trait allows for decoding items monolithically from a source byte stream.
7///
8/// Although this has less flexibility than `Decode` trait, it has the merit of being easy to implement.
9pub trait MonolithicDecode {
10    /// The type of items to be monolithically decoded.
11    type Item;
12
13    /// Decodes an item from the given reader.
14    fn monolithic_decode<R: Read>(&self, reader: R) -> Result<Self::Item>;
15}
16
17/// Monolithic decoder that implements `Decode` trait.
18#[derive(Debug, Default)]
19pub struct MonolithicDecoder<D: MonolithicDecode> {
20    inner: D,
21    item: Option<D::Item>,
22    buf: Vec<u8>,
23}
24impl<D: MonolithicDecode> MonolithicDecoder<D> {
25    /// Makes a new `MonolithicDecoder` instance.
26    pub fn new(inner: D) -> Self {
27        MonolithicDecoder {
28            inner,
29            item: None,
30            buf: Vec::new(),
31        }
32    }
33
34    /// Returns a reference to the inner decoder.
35    pub fn inner_ref(&self) -> &D {
36        &self.inner
37    }
38
39    /// Returns a mutable reference to the inner decoder.
40    pub fn inner_mut(&mut self) -> &mut D {
41        &mut self.inner
42    }
43
44    /// Takes ownership of `MonolithicDecoder` and returns the inner decoder.
45    pub fn into_inner(self) -> D {
46        self.inner
47    }
48}
49impl<D: MonolithicDecode> Decode for MonolithicDecoder<D> {
50    type Item = D::Item;
51
52    fn decode(&mut self, mut buf: &[u8], eos: Eos) -> Result<usize> {
53        if eos.is_reached() {
54            let original_len = buf.len();
55            let item = track!(
56                self.inner.monolithic_decode(self.buf.as_slice().chain(buf.by_ref()));
57                original_len, self.buf.len(), buf.len(), eos
58            )?;
59            self.buf.clear();
60            self.item = Some(item);
61            Ok(original_len - buf.len())
62        } else {
63            self.buf.extend_from_slice(buf);
64            Ok(buf.len())
65        }
66    }
67
68    fn finish_decoding(&mut self) -> Result<Self::Item> {
69        let item = track_assert_some!(self.item.take(), ErrorKind::IncompleteDecoding);
70        Ok(item)
71    }
72
73    fn requiring_bytes(&self) -> ByteCount {
74        if self.item.is_some() {
75            ByteCount::Finite(0)
76        } else {
77            ByteCount::Unknown
78        }
79    }
80
81    fn is_idle(&self) -> bool {
82        self.item.is_some()
83    }
84}
85
86/// This trait allows for encoding items monolithically to a destination byte stream.
87///
88/// Although this has less flexibility than `Encode` trait, it has the merit of being easy to implement.
89pub trait MonolithicEncode {
90    /// The type of items to be monolithically encoded.
91    type Item;
92
93    /// Encodes the item and writes the encoded bytes to the given writer.
94    fn monolithic_encode<W: Write>(&self, item: &Self::Item, writer: W) -> Result<()>;
95}
96
97/// Monolithic encoder that implements `Encode` trait.
98#[derive(Debug, Default)]
99pub struct MonolithicEncoder<E: MonolithicEncode> {
100    inner: E,
101    item: Option<E::Item>,
102    buf: BytesEncoder<Vec<u8>>,
103}
104impl<E: MonolithicEncode> MonolithicEncoder<E> {
105    /// Makes a new `MonolithicEncoder` instance.
106    pub fn new(inner: E) -> Self {
107        MonolithicEncoder {
108            inner,
109            item: None,
110            buf: BytesEncoder::new(),
111        }
112    }
113
114    /// Returns a reference to the inner encoder.
115    pub fn inner_ref(&self) -> &E {
116        &self.inner
117    }
118
119    /// Returns a mutable reference to the inner encoder.
120    pub fn inner_mut(&mut self) -> &mut E {
121        &mut self.inner
122    }
123
124    /// Takes ownership of `MonolithicEncoder` and returns the inner encoder.
125    pub fn into_inner(self) -> E {
126        self.inner
127    }
128}
129impl<E: MonolithicEncode> Encode for MonolithicEncoder<E> {
130    type Item = E::Item;
131
132    fn encode(&mut self, mut buf: &mut [u8], eos: Eos) -> Result<usize> {
133        if let Some(item) = self.item.take() {
134            let mut extra = Vec::new();
135            let original_len = buf.len();
136            {
137                let writer = WriterChain::new(&mut buf, &mut extra);
138                track!(self.inner.monolithic_encode(&item, writer))?;
139            }
140            if extra.is_empty() {
141                Ok(original_len - buf.len())
142            } else {
143                track!(self.buf.start_encoding(extra))?;
144                Ok(original_len)
145            }
146        } else {
147            track!(self.buf.encode(buf, eos))
148        }
149    }
150
151    fn start_encoding(&mut self, item: Self::Item) -> Result<()> {
152        track_assert!(self.is_idle(), ErrorKind::EncoderFull);
153        self.item = Some(item);
154        Ok(())
155    }
156
157    fn is_idle(&self) -> bool {
158        self.item.is_none() && self.buf.is_idle()
159    }
160
161    fn requiring_bytes(&self) -> ByteCount {
162        if self.is_idle() {
163            ByteCount::Finite(0)
164        } else if self.item.is_some() {
165            ByteCount::Unknown
166        } else {
167            self.buf.requiring_bytes()
168        }
169    }
170}
171
172#[derive(Debug)]
173struct WriterChain<A, B> {
174    a: A,
175    b: B,
176}
177impl<A, B> WriterChain<A, B> {
178    fn new(a: A, b: B) -> Self {
179        WriterChain { a, b }
180    }
181}
182impl<A: Write, B: Write> Write for WriterChain<A, B> {
183    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
184        match self.a.write(buf)? {
185            0 => self.b.write(buf),
186            n => Ok(n),
187        }
188    }
189
190    fn flush(&mut self) -> io::Result<()> {
191        Ok(())
192    }
193}