#![cfg(all(feature = "alloc", feature = "derive"))] use bincode::{ config, de::BorrowDecoder, decode_from_slice, decode_from_slice_with_context, encode_to_vec, error::DecodeError, BorrowDecode, Decode, Encode, }; use bumpalo::{collections::Vec, vec, Bump}; #[derive(PartialEq, Eq, Debug)] struct CodableVec<'bump, T: 'bump>(Vec<'bump, T>); impl<'bump, T: Encode> Encode for CodableVec<'bump, T> { fn encode( &self, encoder: &mut E, ) -> Result<(), bincode::error::EncodeError> { self.0.as_slice().encode(encoder) } } impl<'bump, T: Decode<&'bump Bump>> Decode<&'bump Bump> for CodableVec<'bump, T> { fn decode>( decoder: &mut D, ) -> Result { let len = u64::decode(decoder)?; let len = usize::try_from(len).map_err(|_| DecodeError::OutsideUsizeRange(len))?; decoder.claim_container_read::(len)?; let mut vec = Vec::with_capacity_in(len, decoder.context()); for _ in 0..len { decoder.unclaim_bytes_read(core::mem::size_of::()); vec.push(T::decode(decoder)?); } Ok(Self(vec)) } } impl<'de, 'bump, T: BorrowDecode<'de, &'bump Bump>> BorrowDecode<'de, &'bump Bump> for CodableVec<'bump, T> { fn borrow_decode>( decoder: &mut D, ) -> Result { let len = u64::decode(decoder)?; let len = usize::try_from(len).map_err(|_| DecodeError::OutsideUsizeRange(len))?; decoder.claim_container_read::(len)?; let mut vec = Vec::with_capacity_in(len, decoder.context()); for _ in 0..len { // See the documentation on `unclaim_bytes_read` as to why we're doing this here decoder.unclaim_bytes_read(core::mem::size_of::()); vec.push(T::borrow_decode(decoder)?); } Ok(Self(vec)) } } #[derive(Encode, Decode, PartialEq, Eq, Debug)] #[bincode(decode_context = "&'bump Bump")] struct Container<'bump> { vec: CodableVec<'bump, u32>, } #[derive(Encode, Decode, PartialEq, Eq, Debug)] #[bincode(decode_context = "&'bump Bump")] enum _EnumContainer<'bump> { Vec(CodableVec<'bump, u32>), } #[ouroboros::self_referencing] struct SelfReferencing { bump: Bump, #[borrows(bump)] #[not_covariant] container: Container<'this>, } impl Decode for SelfReferencing { fn decode>( decoder: &mut D, ) -> Result { SelfReferencing::try_new(Bump::new(), |bump| { Container::decode(&mut decoder.with_context(bump)) }) } } #[test] fn decode_with_context() { let config = config::standard(); let bump = Bump::new(); let container = Container { vec: CodableVec(vec![in ≎ 1, 2, 3]), }; let bytes = encode_to_vec(&container, config).unwrap(); let (decoded_container, _) = decode_from_slice_with_context::<_, Container, _>(&bytes, config, &bump).unwrap(); assert_eq!(container, decoded_container); let self_referencing: SelfReferencing = decode_from_slice(&bytes, config).unwrap().0; self_referencing.with_container(|c| assert_eq!(&container, c)) }