minify/io/
reader.rs

1use crate::io::{
2    multi_filter::MultiFilter,
3    unstable::{Chars, CharsError},
4};
5use std::{
6    fmt::{self, Formatter},
7    io::{Read, Result},
8    iter::{FilterMap, Iterator},
9    result,
10};
11
12pub type Filter<R> = FilterMap<Chars<R>, fn(result::Result<char, CharsError>) -> Option<char>>;
13
14pub struct InternalReader<R: Read, P, M> {
15    iter: MultiFilter<Filter<R>, P, M>,
16    bytes: Option<Vec<u8>>,
17    pos_bytes: usize,
18}
19
20impl<R: Read, P, M: Default> InternalReader<R, P, M> {
21    pub fn new(inner_reader: R, predicate: P) -> Self {
22        Self {
23            iter: MultiFilter::new(
24                Chars {
25                    inner: inner_reader,
26                }
27                .filter_map(Self::filter_map_result_error),
28                predicate,
29            ),
30            bytes: None,
31            pos_bytes: 0,
32        }
33    }
34
35    #[allow(clippy::needless_pass_by_value)]
36    fn filter_map_result_error(result: result::Result<char, CharsError>) -> Option<char> {
37        match result {
38            Ok(e) => Some(e),
39            _ => None,
40        }
41    }
42
43    fn handle_bytes(
44        &mut self,
45        bytes: Vec<u8>,
46        bytes_start: usize,
47        buf: &mut [u8],
48        buf_start: usize,
49    ) -> usize {
50        let mut pos_bytes = bytes_start;
51        let mut pos_buf = buf_start;
52
53        for item in buf.iter_mut().skip(buf_start) {
54            if pos_bytes < bytes.len() {
55                *item = bytes[pos_bytes];
56                pos_bytes += 1;
57                pos_buf += 1;
58            } else {
59                break;
60            }
61        }
62        if pos_bytes < bytes.len() {
63            self.pos_bytes = pos_bytes;
64            self.bytes = Some(bytes);
65        }
66        pos_buf
67    }
68}
69
70impl<R: Read + fmt::Debug, P, M> fmt::Debug for InternalReader<R, P, M> {
71    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
72        f.debug_struct("InternalReader")
73            .field("iter", &self.iter)
74            .field("bytes", &self.bytes)
75            .field("pos_bytes", &self.pos_bytes)
76            .finish()
77    }
78}
79
80impl<R, P, M> Read for InternalReader<R, P, M>
81where
82    R: Read,
83    P: FnMut(
84        &mut M,
85        char,
86        Option<char>,
87        Option<char>,
88        Option<char>,
89        Option<char>,
90        Option<char>,
91    ) -> bool,
92    M: Default,
93{
94    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
95        let mut pos_buffer = 0;
96
97        if let Some(item) = self.bytes.take() {
98            let pos_bytes = self.pos_bytes;
99            pos_buffer = self.handle_bytes(item, pos_bytes, buf, 0);
100            if pos_buffer >= buf.len() {
101                return Ok(pos_buffer);
102            }
103        }
104
105        while let Some(item) = self.iter.next() {
106            let bytes = item.to_string().into_bytes();
107            pos_buffer = self.handle_bytes(bytes, 0, buf, pos_buffer);
108            if pos_buffer >= buf.len() {
109                break;
110            }
111        }
112        Ok(pos_buffer)
113    }
114}