1use super::{
13 buffered_convert_hooks::BufferedConvertHooks,
14 buffered_decode_engine::BufferedDecodeEngine,
15 buffered_encode_engine::BufferedEncodeEngine,
16 convert_error_of::{
17 ConvertErrorOf,
18 ConvertProgressResult,
19 },
20 convert_state::ConvertState,
21 convert_step_result::ConvertStepResult,
22 encode_context::EncodeContext,
23 encode_step::EncodeStep,
24 finish_error::FinishError,
25 pending_encode_step::PendingEncodeStep,
26 pending_value::PendingValue,
27 pending_value_slot::PendingValueSlot,
28};
29use crate::{
30 CapacityError,
31 Codec,
32 codec::assert_unit_bounds,
33};
34
35#[derive(Clone, Debug, Eq, Hash, PartialEq)]
55pub struct BufferedConvertEngine<D, E, H>
56where
57 D: Codec,
58 E: Codec<Value = D::Value>,
59 H: BufferedConvertHooks<D, E>,
60{
61 decode_engine: BufferedDecodeEngine<D, H::DecodeHooks>,
63 encode_engine: BufferedEncodeEngine<E, H::EncodeHooks>,
65 hooks: H,
67 pending: PendingValueSlot<D::Value>,
69}
70
71impl<D, E, H> BufferedConvertEngine<D, E, H>
72where
73 D: Codec,
74 E: Codec<Value = D::Value>,
75 H: BufferedConvertHooks<D, E>,
76{
77 #[must_use]
94 #[inline]
95 pub fn new(decoder: D, encoder: E, hooks: H) -> Self {
96 let decode_hooks = hooks.create_decode_hooks(&decoder, &encoder);
97 let encode_hooks = hooks.create_encode_hooks(&decoder, &encoder);
98 Self::from_parts(decoder, encoder, hooks, decode_hooks, encode_hooks)
99 }
100
101 #[inline(always)]
121 const fn from_parts(
122 decoder: D,
123 encoder: E,
124 hooks: H,
125 decode_hooks: H::DecodeHooks,
126 encode_hooks: H::EncodeHooks,
127 ) -> Self {
128 Self {
129 decode_engine: BufferedDecodeEngine::new(decoder, decode_hooks),
130 encode_engine: BufferedEncodeEngine::new(encoder, encode_hooks),
131 hooks,
132 pending: PendingValueSlot::empty(),
133 }
134 }
135
136 #[must_use]
142 #[inline(always)]
143 fn decode_codec(&self) -> &D {
144 &self.decode_engine.codec
145 }
146
147 #[must_use]
153 #[inline(always)]
154 fn encode_codec(&self) -> &E {
155 &self.encode_engine.codec
156 }
157
158 #[must_use = "capacity planning can fail on overflow"]
160 pub fn max_output_len(&self, input_len: usize) -> Result<usize, CapacityError> {
161 let pending_units = self.pending_output_len()?;
162 let decoded_values = self.decode_engine.max_output_len(input_len)?;
163 let converted_units = self.encode_engine.max_output_len(decoded_values)?;
164 pending_units
165 .checked_add(converted_units)
166 .ok_or(CapacityError::OutputLengthOverflow)
167 }
168
169 #[must_use = "capacity planning can fail on overflow"]
171 pub fn max_finish_output_len(&self) -> Result<usize, CapacityError> {
172 let pending_units = self.pending_output_len()?;
173 let decoder_finish_values = self.decode_engine.max_finish_output_len();
174 let decoder_finish_units = self.encode_engine.max_output_len(decoder_finish_values)?;
175 let encoder_finish_units = self.encode_engine.max_finish_output_len();
176 let pending_and_decoder = pending_units
177 .checked_add(decoder_finish_units)
178 .ok_or(CapacityError::OutputLengthOverflow)?;
179 pending_and_decoder
180 .checked_add(encoder_finish_units)
181 .ok_or(CapacityError::OutputLengthOverflow)
182 }
183
184 pub fn transcode(
202 &mut self,
203 input: &[D::Unit],
204 input_index: usize,
205 output: &mut [E::Unit],
206 output_index: usize,
207 ) -> ConvertProgressResult<D, E, H> {
208 if input_index > input.len() {
209 return Err(self
210 .hooks
211 .invalid_input_index(self.decode_codec(), input_index, input.len()));
212 }
213 if output_index > output.len() {
214 let error = self.encode_engine.invalid_output_index(output_index, output.len());
215 return Err(self.hooks.map_encode_error(error));
216 }
217 assert_unit_bounds::<D>(self.decode_codec());
218 assert_unit_bounds::<E>(self.encode_codec());
219
220 let mut state = ConvertState::new(input, input_index, output, output_index);
221
222 if let Some(progress) = self.drain_pending(&mut state)? {
225 return Ok(progress);
226 }
227
228 while state.has_input() {
229 let previous_read = state.read();
230 if let Some(progress) = self.convert_next(&mut state)? {
233 return Ok(progress);
234 }
235 debug_assert!(
236 state.read() > previous_read,
237 "BufferedConvertEngine conversion step must consume input or stop",
238 );
239 }
240
241 Ok(state.complete_progress())
242 }
243
244 pub fn finish(
267 &mut self,
268 output: &mut [E::Unit],
269 output_index: usize,
270 ) -> Result<usize, FinishError<ConvertErrorOf<D, E, H>>>
271 where
272 D::Value: Default,
273 {
274 assert_unit_bounds::<D>(self.decode_codec());
275 assert_unit_bounds::<E>(self.encode_codec());
276 let required = self.max_finish_output_len().map_err(FinishError::capacity)?;
277 FinishError::ensure_output_capacity(output.len(), output_index, required)?;
278
279 let empty_input: &[D::Unit] = &[];
280 let mut state = ConvertState::new(empty_input, 0, output, output_index);
281 if self.drain_pending(&mut state).map_err(FinishError::source)?.is_some() {
284 unreachable!("converter finish bound must reserve space for pending values");
285 }
286
287 self.drain_decoder_finish(&mut state)?;
290
291 let output_cursor = state.output_cursor();
292 let written = self
293 .encode_engine
294 .finish(state.output_mut(), output_cursor)
295 .map_err(|error| error.map_source(|error| self.hooks.map_encode_error(error)))?;
296 state.advance_output(written);
297 Ok(state.written())
298 }
299
300 #[inline(always)]
310 pub fn reset(&mut self) {
311 self.pending.clear();
312 self.decode_engine.reset();
313 self.encode_engine.reset();
314 self.hooks.reset();
315 }
316
317 #[inline]
319 fn convert_next(&mut self, state: &mut ConvertState<'_, D::Unit, E::Unit>) -> ConvertStepResult<D, E, H> {
320 let step = self
321 .decode_engine
322 .decode_step(state.input(), state.decode_context())
323 .map_err(|error| self.hooks.map_decode_error(error))?;
324 step.apply_to_convert_state(state, |pending, state| self.encode_pending(pending, state))
325 }
326
327 #[inline(always)]
329 fn pending_output_len(&self) -> Result<usize, CapacityError> {
330 self.pending.max_output_len(&self.encode_engine)
331 }
332
333 #[inline]
335 fn drain_pending(&mut self, state: &mut ConvertState<'_, D::Unit, E::Unit>) -> ConvertStepResult<D, E, H> {
336 let Some(pending) = self.pending.take() else {
337 return Ok(None);
338 };
339 self.encode_pending(pending, state)
340 }
341
342 fn drain_decoder_finish(
344 &mut self,
345 state: &mut ConvertState<'_, D::Unit, E::Unit>,
346 ) -> Result<(), FinishError<ConvertErrorOf<D, E, H>>>
347 where
348 D::Value: Default,
349 {
350 let value_count = self.decode_engine.max_finish_output_len();
351 let mut decoded: Vec<D::Value> = (0..value_count).map(|_| D::Value::default()).collect();
352 let written = self
353 .decode_engine
354 .finish(&mut decoded, 0)
355 .map_err(|error| error.map_source(|error| self.hooks.map_decode_error(error)))?;
356 for value in decoded.into_iter().take(written) {
357 let pending = PendingValue::new(value, 0);
358 if self
359 .encode_pending(pending, state)
360 .map_err(FinishError::source)?
361 .is_some()
362 {
363 unreachable!("converter finish bound must reserve space for decode finish values");
364 }
365 }
366 Ok(())
367 }
368
369 #[inline]
371 fn encode_pending(
372 &mut self,
373 pending: PendingValue<D::Value>,
374 state: &mut ConvertState<'_, D::Unit, E::Unit>,
375 ) -> ConvertStepResult<D, E, H> {
376 let input_index = pending.input_index();
377 let output_index = state.output_cursor();
378 let context = EncodeContext {
379 input_value: pending.value(),
380 input_index,
381 output: state.output_mut(),
382 output_index,
383 };
384 let step = self
385 .encode_engine
386 .encode_step(context)
387 .map_err(|error| self.hooks.map_encode_error(error))?;
388 let step = match step {
389 EncodeStep::Written { written } => PendingEncodeStep::written(written),
390 EncodeStep::NeedOutput { additional, available } => {
391 PendingEncodeStep::need_output(pending, additional, available)
392 }
393 };
394 Ok(self.pending.apply_pending_encode_step(step, state))
395 }
396}
397
398impl<D, E, H> Default for BufferedConvertEngine<D, E, H>
399where
400 D: Codec + Default,
401 E: Codec<Value = D::Value> + Default,
402 H: BufferedConvertHooks<D, E> + Default,
403{
404 #[inline(always)]
410 fn default() -> Self {
411 Self::new(D::default(), E::default(), H::default())
412 }
413}