qubit_text_io/adapters/
encoded_text_reader.rs1use std::io::{
11 self,
12 Read,
13};
14
15use encoding_rs::Encoding;
16
17use crate::{
18 CodingErrorPolicy,
19 StringTextReader,
20 TextLineRead,
21 TextRead,
22};
23
24#[derive(Debug)]
30pub struct EncodedTextReader {
31 inner: StringTextReader,
32}
33
34impl EncodedTextReader {
35 pub fn new<R>(
49 mut reader: R,
50 encoding: &'static Encoding,
51 policy: CodingErrorPolicy,
52 ) -> io::Result<Self>
53 where
54 R: Read,
55 {
56 let mut bytes = Vec::new();
57 reader.read_to_end(&mut bytes)?;
58 let text = decode_bytes(bytes.as_slice(), encoding, policy)?;
59 Ok(Self {
60 inner: StringTextReader::new(text),
61 })
62 }
63
64 #[must_use]
69 pub fn into_inner(self) -> StringTextReader {
70 self.inner
71 }
72}
73
74impl TextRead for EncodedTextReader {
75 type Error = io::Error;
76
77 #[inline]
78 fn read_char(&mut self) -> Result<Option<char>, Self::Error> {
79 self.inner.read_char().map_err(|error| match error {})
80 }
81
82 #[inline]
83 fn read_chars(&mut self, output: &mut Vec<char>, max: usize) -> Result<usize, Self::Error> {
84 self.inner
85 .read_chars(output, max)
86 .map_err(|error| match error {})
87 }
88
89 #[inline]
90 fn read_to_string(&mut self, output: &mut String) -> Result<usize, Self::Error> {
91 self.inner
92 .read_to_string(output)
93 .map_err(|error| match error {})
94 }
95}
96
97impl TextLineRead for EncodedTextReader {
98 #[inline]
99 fn read_line(&mut self, output: &mut String) -> Result<bool, Self::Error> {
100 self.inner.read_line(output).map_err(|error| match error {})
101 }
102}
103
104fn decode_bytes(
118 bytes: &[u8],
119 encoding: &'static Encoding,
120 policy: CodingErrorPolicy,
121) -> io::Result<String> {
122 let (text, _, had_errors) = encoding.decode(bytes);
123 if had_errors && policy == CodingErrorPolicy::Strict {
124 return Err(io::Error::new(
125 io::ErrorKind::InvalidData,
126 format!("input is not valid {}", encoding.name()),
127 ));
128 }
129 Ok(text.into_owned())
130}