lzfse_rust/encode/ring_encoder.rs
1use crate::fse::{V1_MAX_BLOCK_LEN, V2_MAX_BLOCK_LEN};
2use crate::ops::FlushLimit;
3use crate::ring::{RingBox, RingShortWriter};
4
5use super::constants::*;
6use super::encoder::LzfseEncoder;
7use super::frontend_ring::FrontendRing;
8use super::writer::LzfseWriter;
9use super::writer_bytes::LzfseWriterBytes;
10
11use std::fmt;
12use std::io::{self, Read, Write};
13
14/// LZFSE ring encoder.
15///
16///
17/// This implementation builds upon [LzfseEncoder] with the addition of internal ring buffers that
18/// enable efficient IO operations. It can be converted to a mutable [LzfseEncoder] reference using
19/// [as_mut()](AsMut::as_mut).
20pub struct LzfseRingEncoder {
21 core: LzfseEncoder,
22 input: RingBox<Input>,
23 output: RingBox<Output>,
24}
25
26impl LzfseRingEncoder {
27 /// Encode `reader` into `writer` returning a tuple (u, v) where u is the number of unencoded
28 /// bytes read from the reader and v is the number of encoded bytes written into the writer.
29 ///
30 /// Both the `reader` and `writer` are accessed efficiently by internal ring buffers, there is
31 /// no need to wrap them in [BufReader](std::io::BufReader) or
32 /// [BufWriter](std::io::BufWriter).
33 ///
34 ///
35 /// # Errors
36 ///
37 /// * [Error](std::io::Error) in case of `reader` or `writer` IO errors.
38 ///
39 /// # Examples
40 ///
41 /// ```
42 /// use lzfse_rust::LzfseRingEncoder;
43 /// use std::io;
44 ///
45 /// fn main() -> io::Result<()> {
46 /// let mut enc = Vec::default();
47 /// let mut encoder = LzfseRingEncoder::default();
48 /// let n_bytes = encoder.encode_bytes(b"test", &mut enc)?;
49 /// // "test" string encoded.
50 /// assert_eq!(enc, &[0x62, 0x76, 0x78, 0x2d, 0x04, 0x00, 0x00, 0x00, 0x74, 0x65, 0x73, 0x74,
51 /// 0x62, 0x76, 0x78, 0x24]);
52 /// Ok(())
53 /// }
54 /// ```
55 pub fn encode<I, O>(&mut self, reader: &mut I, writer: &mut O) -> io::Result<(u64, u64)>
56 where
57 I: Read,
58 O: Write,
59 {
60 let mut frontend = FrontendRing::new((&mut self.input).into(), &mut self.core.table);
61 frontend.init();
62 let mut writer = RingShortWriter::new((&mut self.output).into(), writer);
63 let n_raw_bytes = frontend.copy(&mut self.core.backend, &mut writer, reader)?;
64 frontend.flush(&mut self.core.backend, &mut writer)?;
65 let (_, n_payload_bytes) = writer.into_inner()?;
66 Ok((n_raw_bytes, n_payload_bytes))
67 }
68
69 /// This method bypasses the internal ring buffers and operates over the supplied buffers,
70 /// it is functionally identical to [LzfseEncoder::encode_bytes].
71 pub fn encode_bytes(&mut self, src: &[u8], dst: &mut Vec<u8>) -> io::Result<u64> {
72 self.core.encode_bytes(src, dst)
73 }
74
75 /// Create a new [LzfseWriter] encoder instance using the supplied `inner` writer.
76 ///
77 /// **It is imperative that the writer is [finalized](LzfseWriterBytes::finalize) after use to
78 /// complete the encoding process, [flushing](std::io::Write::flush) is not sufficient.**
79 pub fn writer<O: Write>(&mut self, inner: O) -> LzfseWriter<O> {
80 let mut frontend = FrontendRing::new((&mut self.input).into(), &mut self.core.table);
81 frontend.init();
82 let writer = RingShortWriter::new((&mut self.output).into(), inner);
83 LzfseWriter::new(frontend, &mut self.core.backend, writer)
84 }
85
86 /// Create a new [LzfseWriterBytes] decoder instance using the supplied `vec`.
87 ///
88 /// This method offers greater efficiency in comparison to [LzfseRingEncoder::writer]
89 /// when operating over byte vectors.
90 ///
91 /// **It is imperative that the writer is [finalized](LzfseWriterBytes::finalize) after use to
92 /// complete the encoding process, [flushing](std::io::Write::flush) is not sufficient.**
93 pub fn writer_bytes(&mut self, vec: Vec<u8>) -> LzfseWriterBytes {
94 let mut frontend = FrontendRing::new((&mut self.input).into(), &mut self.core.table);
95 frontend.init();
96 LzfseWriterBytes::new(frontend, &mut self.core.backend, vec)
97 }
98}
99
100impl Default for LzfseRingEncoder {
101 #[allow(clippy::assertions_on_constants)]
102 fn default() -> Self {
103 assert!(V1_MAX_BLOCK_LEN + 64 < RingShortWriter::<(), Output>::FLUSH_LIMIT);
104 assert!(V2_MAX_BLOCK_LEN + 64 < RingShortWriter::<(), Output>::FLUSH_LIMIT);
105 Self {
106 core: LzfseEncoder::default(),
107 input: RingBox::<Input>::default(),
108 output: RingBox::<Output>::default(),
109 }
110 }
111}
112
113impl fmt::Debug for LzfseRingEncoder {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 f.debug_struct("LzfseRingEncoder").finish()
116 }
117}