serbzip_core/
codecs.rs

1//! Machinery common to all codec implementations.
2
3use crate::transcoder;
4use crate::transcoder::TranscodeError;
5use std::convert::Infallible;
6use std::error::Error;
7use std::io;
8use std::io::BufRead;
9use std::io::Write;
10
11pub mod armenoid;
12pub mod balkanoid;
13
14/// The specification of a codec.
15///
16/// Codecs work line by line. As such, they require two method implementations:
17/// [`compress_line`](Codec::compress_line) — to encode one line of input text, and
18/// [`expand_line`](Codec::expand_line) — to perform the reverse operation.
19///
20/// Compression is not allowed to return an error; the thinking is that all
21/// text should be compressible. Expansion, however, may return an error. It is possible
22/// that the output of compression may have been mangled with, in which case expansion
23/// is not possible.
24pub trait Codec {
25    /// The type of error returned during expansion.
26    type ExpandError: Error;
27
28    /// Compresses a line of text, returning its encoded representation as a [`String`].
29    fn compress_line(&self, line: &str) -> String;
30
31    /// Expands a line of text, returning its decoded representation as a [`String`].
32    ///
33    /// # Errors
34    /// Expansion is not always possible, in which case an [`ExpandError`](Self::ExpandError)
35    /// is returned.
36    fn expand_line(&self, line: &str) -> Result<String, Self::ExpandError>;
37
38    /// A helper method for compressing a series of lines from a given buffered reader,
39    /// outputting the result into the given writer.
40    ///
41    /// # Errors
42    /// [`io::Error`] if the reader or the writer encountered an I/O error.
43    fn compress(&self, r: &mut impl BufRead, w: &mut impl Write) -> Result<(), io::Error> {
44        let result: Result<(), TranscodeError<Infallible>> =
45            transcoder::transcode(r, w, |_, line| Ok(self.compress_line(line)));
46        result.map_err(|err| err.into_io_error().unwrap())
47    }
48
49    /// A helper method for expanding a series of lines from a given buffered reader,
50    /// outputting the result into the given writer.
51    ///
52    /// # Errors
53    /// [`TranscodeError`] if the reader or the writer encountered an I/O error, or
54    /// if the codec was unable to expand a line.
55    fn expand(
56        &self,
57        r: &mut impl BufRead,
58        w: &mut impl Write,
59    ) -> Result<(), TranscodeError<Self::ExpandError>> {
60        transcoder::transcode(r, w, |_, line| self.expand_line(line))
61    }
62}
63
64#[cfg(test)]
65mod tests;