base64_ng/stream/
encoder.rs1use super::{EncoderDriver, OutputQueue, redacted_inner_state, stream_encoder_failed_error};
2use crate::{Alphabet, Engine};
3use std::io::{self, Write};
4
5pub struct Encoder<W, A, const PAD: bool>
13where
14 A: Alphabet,
15{
16 inner: Option<W>,
17 engine: Engine<A, PAD>,
18 driver: EncoderDriver,
19 output: OutputQueue<1024>,
20 finalized: bool,
21 failed: bool,
22}
23
24impl<W, A, const PAD: bool> Encoder<W, A, PAD>
25where
26 A: Alphabet,
27{
28 #[must_use]
30 pub const fn new(inner: W, engine: Engine<A, PAD>) -> Self {
31 Self {
32 inner: Some(inner),
33 engine,
34 driver: EncoderDriver::new::<A, PAD>(),
35 output: OutputQueue::new(),
36 finalized: false,
37 failed: false,
38 }
39 }
40
41 #[must_use]
43 pub fn get_ref(&self) -> &W {
44 self.inner_ref()
45 }
46
47 pub fn get_mut(&mut self) -> &mut W {
49 self.inner_mut()
50 }
51
52 #[must_use]
54 pub const fn engine(&self) -> Engine<A, PAD> {
55 self.engine
56 }
57
58 #[must_use]
60 pub const fn is_padded(&self) -> bool {
61 PAD
62 }
63
64 #[must_use]
67 pub const fn pending_len(&self) -> usize {
68 self.driver.pending_input_len()
69 }
70
71 #[must_use]
74 pub const fn has_pending_input(&self) -> bool {
75 self.pending_len() != 0
76 }
77
78 #[must_use]
83 pub const fn pending_input_needed_len(&self) -> usize {
84 if self.has_pending_input() {
85 3 - self.pending_len()
86 } else {
87 0
88 }
89 }
90
91 #[must_use]
94 pub const fn buffered_output_len(&self) -> usize {
95 self.output.len()
96 }
97
98 #[must_use]
101 pub const fn buffered_output_capacity(&self) -> usize {
102 self.output.capacity()
103 }
104
105 #[must_use]
108 pub const fn buffered_output_remaining_capacity(&self) -> usize {
109 self.output.available_capacity()
110 }
111
112 #[must_use]
115 pub const fn has_buffered_output(&self) -> bool {
116 !self.output.is_empty()
117 }
118
119 #[must_use]
123 pub const fn is_finalized(&self) -> bool {
124 self.finalized
125 }
126
127 #[must_use]
135 pub const fn is_failed(&self) -> bool {
136 self.failed
137 }
138
139 #[must_use]
142 pub const fn can_into_inner(&self) -> bool {
143 !self.is_failed() && !self.has_pending_input() && !self.has_buffered_output()
144 }
145
146 #[must_use]
150 pub fn into_inner(mut self) -> W {
151 self.take_inner()
152 }
153
154 #[allow(clippy::result_large_err)]
160 pub fn try_into_inner(mut self) -> Result<W, Self> {
161 if !self.can_into_inner() {
162 return Err(self);
163 }
164 Ok(self.take_inner())
165 }
166
167 fn inner_ref(&self) -> &W {
168 match &self.inner {
169 Some(inner) => inner,
170 None => unreachable!("stream encoder inner writer was already taken"),
171 }
172 }
173
174 fn inner_mut(&mut self) -> &mut W {
175 match &mut self.inner {
176 Some(inner) => inner,
177 None => unreachable!("stream encoder inner writer was already taken"),
178 }
179 }
180
181 fn take_inner(&mut self) -> W {
182 match self.inner.take() {
183 Some(inner) => inner,
184 None => unreachable!("stream encoder inner writer was already taken"),
185 }
186 }
187
188 fn clear_pending(&mut self) {
189 self.driver.wipe();
190 }
191
192 fn clear_output(&mut self) {
193 self.output.clear_all();
194 }
195}
196
197impl<W, A, const PAD: bool> Drop for Encoder<W, A, PAD>
198where
199 A: Alphabet,
200{
201 fn drop(&mut self) {
202 self.clear_pending();
203 self.clear_output();
204 }
205}
206
207impl<W, A, const PAD: bool> core::fmt::Debug for Encoder<W, A, PAD>
208where
209 A: Alphabet,
210{
211 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
212 formatter
213 .debug_struct("Encoder")
214 .field("inner", &redacted_inner_state(self.inner.is_some()))
215 .field("engine", &self.engine)
216 .field("driver", &"<redacted>")
217 .field("pending", &"<redacted>")
218 .field("pending_len", &self.pending_len())
219 .field("pending_input_needed_len", &self.pending_input_needed_len())
220 .field("buffered_output_len", &self.output.len())
221 .field("buffered_output_capacity", &self.output.capacity())
222 .field(
223 "buffered_output_remaining_capacity",
224 &self.output.available_capacity(),
225 )
226 .field("can_into_inner", &self.can_into_inner())
227 .field("finalized", &self.finalized)
228 .field("failed", &self.failed)
229 .finish()
230 }
231}
232
233impl<W, A, const PAD: bool> Encoder<W, A, PAD>
234where
235 W: Write,
236 A: Alphabet,
237{
238 pub fn try_finish(&mut self) -> io::Result<()> {
248 if self.failed {
249 return Err(stream_encoder_failed_error());
250 }
251 if !self.finalized {
252 self.queue_pending_final()?;
253 self.finalized = true;
254 }
255 self.flush()
256 }
257
258 pub fn finish(mut self) -> io::Result<W> {
260 self.try_finish()?;
261 Ok(self.take_inner())
262 }
263
264 fn queue_pending_final(&mut self) -> io::Result<()> {
265 let mut encoded = [0u8; 4];
266 let step = match self.driver.finish(&mut encoded) {
267 Ok(step) => step,
268 Err(err) => {
269 crate::wipe_bytes(&mut encoded);
270 self.failed = true;
271 return Err(err);
272 }
273 };
274 let produced = step.progress().output_produced();
275 let result = self.output.push_slice(&encoded[..produced]);
276 crate::wipe_bytes(&mut encoded);
277 if result.is_err() {
278 self.failed = true;
279 }
280 result?;
281 Ok(())
282 }
283
284 fn drain_output(&mut self) -> io::Result<()> {
285 let mut chunk = [0u8; 1024];
286 while !self.output.is_empty() {
287 let pending = self.output.copy_front(&mut chunk);
288 let result = self.inner_mut().write(&chunk[..pending]);
289 crate::wipe_bytes(&mut chunk[..pending]);
290 match result {
291 Ok(0) => {
292 return Err(io::Error::new(
293 io::ErrorKind::WriteZero,
294 "base64 stream encoder could not drain buffered output",
295 ));
296 }
297 Ok(written) => {
298 if written > pending {
299 self.failed = true;
300 return Err(io::Error::new(
301 io::ErrorKind::InvalidData,
302 "wrapped writer reported more bytes than provided",
303 ));
304 }
305 self.output.discard_front(written);
306 }
307 Err(err) => return Err(err),
308 }
309 }
310
311 Ok(())
312 }
313}
314
315impl<W, A, const PAD: bool> Write for Encoder<W, A, PAD>
316where
317 W: Write,
318 A: Alphabet,
319{
320 fn write(&mut self, input: &[u8]) -> io::Result<usize> {
321 if self.failed {
322 return Err(stream_encoder_failed_error());
323 }
324 self.drain_output()?;
325 if self.finalized {
326 return Err(io::Error::new(
327 io::ErrorKind::InvalidInput,
328 "base64 stream encoder received input after finalization",
329 ));
330 }
331 if input.is_empty() {
332 return Ok(0);
333 }
334
335 let take = input.len().min(768);
336 let mut encoded = [0u8; 1024];
337 let step = match self.driver.update(&input[..take], &mut encoded) {
338 Ok(step) => step,
339 Err(err) => {
340 crate::wipe_bytes(&mut encoded);
341 self.failed = true;
342 return Err(err);
343 }
344 };
345 let progress = step.progress();
346 let result = self
347 .output
348 .push_slice(&encoded[..progress.output_produced()]);
349 crate::wipe_bytes(&mut encoded);
350 if result.is_err() {
351 self.failed = true;
352 }
353 result?;
354 Ok(progress.input_consumed())
355 }
356
357 fn flush(&mut self) -> io::Result<()> {
358 if self.failed {
359 return Err(stream_encoder_failed_error());
360 }
361 self.drain_output()?;
362 self.inner_mut().flush()
363 }
364}