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}