Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions bitcode_derive/src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ impl crate::shared::Derive<{ Item::COUNT }> for Decode {
#[allow(clippy::pedantic)]
const _: () = {
impl #impl_generics #private::Decode<#de> for #input_ty #where_clause {
#[cfg(debug_assertions)]
type Decoder = #private::BoxDecoder<#decoder_ty>;
#[cfg(not(debug_assertions))]
type Decoder = #decoder_ty;
}

Expand Down
3 changes: 3 additions & 0 deletions bitcode_derive/src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,9 @@ impl crate::shared::Derive<{ Item::COUNT }> for Encode {
#[allow(clippy::pedantic)]
const _: () = {
impl #impl_generics #private::Encode for #input_ty #where_clause {
#[cfg(debug_assertions)]
type Encoder = #private::BoxEncoder<#encoder_ty>;
#[cfg(not(debug_assertions))]
type Encoder = #encoder_ty;
}

Expand Down
88 changes: 88 additions & 0 deletions src/derive/debug_box.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
//! [`Box`] indirection for derived encoders/decoders, used only in debug mode
//! to avoid stack overflow.

use crate::coder::{Buffer, Decoder, Encoder, Result, View};
use crate::fast::{SliceImpl, Unaligned, VecImpl};
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::mem::MaybeUninit;
use core::num::NonZeroUsize;

/// Wraps a derived [`Encoder`] in a [`Box`] and delegates to it.
pub struct BoxEncoder<E>(Box<E>);

impl<E: Default> Default for BoxEncoder<E> {
#[inline(never)]
fn default() -> Self {
Self(Box::default())
}
}

impl<E: Buffer> Buffer for BoxEncoder<E> {
#[inline(never)]
fn collect_into(&mut self, out: &mut Vec<u8>) {
self.0.collect_into(out);
}

#[inline(never)]
fn reserve(&mut self, additional: NonZeroUsize) {
self.0.reserve(additional);
}
}

impl<T: ?Sized, E: Encoder<T>> Encoder<T> for BoxEncoder<E> {
#[inline(never)]
fn as_primitive(&mut self) -> Option<&mut VecImpl<T>>
where
T: Sized,
{
self.0.as_primitive()
}

#[inline(never)]
fn encode(&mut self, t: &T) {
self.0.encode(t);
}

#[inline(never)]
fn encode_vectored<'a>(&mut self, i: impl Iterator<Item = &'a T> + Clone)
where
T: 'a,
{
self.0.encode_vectored(i);
}
}

/// Wraps a derived [`Decoder`] in a [`Box`] and delegates to it.
pub struct BoxDecoder<D>(Box<D>);

impl<D: Default> Default for BoxDecoder<D> {
#[inline(never)]
fn default() -> Self {
Self(Box::default())
}
}

impl<'a, D: View<'a>> View<'a> for BoxDecoder<D> {
#[inline(never)]
fn populate(&mut self, input: &mut &'a [u8], length: usize) -> Result<()> {
self.0.populate(input, length)
}
}

impl<'a, T, D: Decoder<'a, T>> Decoder<'a, T> for BoxDecoder<D> {
#[inline(never)]
fn as_primitive(&mut self) -> Option<&mut SliceImpl<'_, Unaligned<T>>> {
self.0.as_primitive()
}

#[inline(never)]
fn decode(&mut self) -> T {
self.0.decode()
}

#[inline(never)]
fn decode_in_place(&mut self, out: &mut MaybeUninit<T>) {
self.0.decode_in_place(out);
}
}
3 changes: 3 additions & 0 deletions src/derive/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use core::num::NonZeroUsize;
mod array;
mod atomic;
pub(crate) mod convert;
#[cfg(feature = "derive")]
mod debug_box;
mod duration;
mod empty;
mod impls;
Expand All @@ -27,6 +29,7 @@ pub(crate) mod vec;
pub mod __private {
extern crate alloc;
pub use crate::coder::{uninit_field, Buffer, Decoder, Encoder, Result, View};
pub use crate::derive::debug_box::{BoxDecoder, BoxEncoder};
pub use crate::derive::variant::{VariantDecoder, VariantEncoder};
pub use crate::derive::{Decode, Encode};
pub fn invalid_enum_variant<T>() -> Result<T> {
Expand Down
Loading