serbzip_core/
transcoder.rs1use std::error::Error;
4use std::fmt::{Debug, Display, Formatter};
5use std::io::{BufRead, Write};
6use std::{error, io};
7
8#[derive(Debug)]
10pub enum TranscodeError<L> {
11 Conversion { line_no: u32, error: L },
13
14 Io(io::Error),
16}
17
18impl<L> TranscodeError<L> {
19 pub fn into_conversion_error(self) -> Option<(u32, L)> {
21 match self {
22 TranscodeError::Conversion { line_no, error } => Some((line_no, error)),
23 TranscodeError::Io(_) => None,
24 }
25 }
26
27 pub fn into_io_error(self) -> Option<io::Error> {
29 match self {
30 TranscodeError::Conversion { .. } => None,
31 TranscodeError::Io(error) => Some(error),
32 }
33 }
34}
35
36impl<L: Into<Box<dyn Error>>> TranscodeError<L> {
37 pub fn into_dynamic(self) -> TranscodeError<Box<dyn Error>> {
41 match self {
42 TranscodeError::Conversion { line_no, error } => TranscodeError::Conversion {
43 line_no,
44 error: error.into(),
45 },
46 TranscodeError::Io(error) => TranscodeError::Io(error),
47 }
48 }
49}
50
51impl<L: Display + Debug> Display for TranscodeError<L> {
52 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
53 match self {
54 TranscodeError::Conversion { line_no, error } => {
55 write!(f, "conversion error on line {line_no}: {error}")
56 }
57 TranscodeError::Io(error) => write!(f, "I/O error: {error:?}"),
58 }
59 }
60}
61
62impl<L: Display + Debug> error::Error for TranscodeError<L> {}
63
64impl<L> From<io::Error> for TranscodeError<L> {
65 fn from(error: io::Error) -> Self {
66 TranscodeError::Io(error)
67 }
68}
69
70pub fn transcode<L>(
80 r: &mut impl BufRead,
81 w: &mut impl Write,
82 mut processor: impl FnMut(u32, &str) -> Result<String, L>,
83) -> Result<(), TranscodeError<L>> {
84 let mut read_buf = String::new();
85 let mut line_no = 1u32;
86 loop {
87 match r.read_line(&mut read_buf)? {
88 0 => return Ok(()),
89 size => match processor(line_no, &read_buf[0..size - 1]) {
90 Ok(output) => {
91 writeln!(w, "{}", output)?;
92 read_buf.clear();
93 }
94 Err(error) => return Err(TranscodeError::Conversion { line_no, error }),
95 },
96 }
97 line_no += 1;
98 }
99}
100
101#[cfg(test)]
102mod tests;