Skip to content

Commit 62f8701

Browse files
committed
Add with_ctx to allow attaching context to decoder in the middle of decoding
1 parent 6d86dc2 commit 62f8701

File tree

4 files changed

+75
-5
lines changed

4 files changed

+75
-5
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ unty = "0.0.3"
3737

3838
# Used for tests
3939
[dev-dependencies]
40+
ouroboros = "0.18.3"
4041
serde_derive = "1.0"
4142
serde_json = { version = "1.0", default-features = false }
4243
tempfile = "3.2"

src/de/decoder.rs

+42
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,45 @@ impl<R: Reader, C: Config, Ctx> Decoder for DecoderImpl<R, C, Ctx> {
9595
&mut self.ctx
9696
}
9797
}
98+
99+
pub struct WithContext<'a, D: ?Sized, C> {
100+
pub(crate) decoder: &'a mut D,
101+
pub(crate) ctx: &'a mut C,
102+
}
103+
104+
impl<'a, C, D: Decoder + ?Sized> Sealed for WithContext<'a, D, C> {}
105+
106+
impl<'a, Ctx, D: Decoder + ?Sized> Decoder for WithContext<'a, D, Ctx> {
107+
type R = D::R;
108+
109+
type C = D::C;
110+
111+
type Ctx = Ctx;
112+
113+
fn ctx(&mut self) -> &mut Self::Ctx {
114+
&mut self.ctx
115+
}
116+
117+
fn reader(&mut self) -> &mut Self::R {
118+
self.decoder.reader()
119+
}
120+
121+
fn config(&self) -> &Self::C {
122+
self.decoder.config()
123+
}
124+
125+
fn claim_bytes_read(&mut self, n: usize) -> Result<(), DecodeError> {
126+
self.decoder.claim_bytes_read(n)
127+
}
128+
129+
fn unclaim_bytes_read(&mut self, n: usize) {
130+
self.decoder.unclaim_bytes_read(n)
131+
}
132+
}
133+
134+
impl<'de, 'a, C, D: BorrowDecoder<'de>> BorrowDecoder<'de> for WithContext<'a, D, C> {
135+
type BR = D::BR;
136+
fn borrow_reader(&mut self) -> &mut Self::BR {
137+
self.decoder.borrow_reader()
138+
}
139+
}

src/de/mod.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ mod impl_core;
55
mod impl_tuples;
66
mod impls;
77

8-
use self::read::{BorrowReader, Reader};
8+
use self::{
9+
decoder::WithContext,
10+
read::{BorrowReader, Reader},
11+
};
912
use crate::{
1013
config::{Config, InternalLimitConfig},
1114
error::DecodeError,
@@ -138,6 +141,10 @@ pub trait Decoder: Sealed {
138141

139142
fn ctx(&mut self) -> &mut Self::Ctx;
140143

144+
fn with_ctx<'a, C>(&'a mut self, ctx: &'a mut C) -> WithContext<'a, Self, C> {
145+
WithContext { decoder: self, ctx }
146+
}
147+
141148
/// Returns a mutable reference to the reader
142149
fn reader(&mut self) -> &mut Self::R;
143150

tests/ctx.rs

+24-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use bincode::{
2-
config, de::BorrowDecoder, decode_from_slice_with_ctx, encode_to_vec, error::DecodeError,
3-
BorrowDecode, Decode, Encode,
2+
config, de::BorrowDecoder, decode_from_slice, decode_from_slice_with_ctx, encode_to_vec,
3+
error::DecodeError, BorrowDecode, Decode, Encode,
44
};
55
use bumpalo::{collections::Vec, vec, Bump};
66

@@ -66,16 +66,36 @@ enum _EnumContainer<'bump> {
6666
Vec(CodableVec<'bump, u32>),
6767
}
6868

69+
#[ouroboros::self_referencing]
70+
struct SelfReferencing {
71+
bump: Bump,
72+
#[borrows(bump)]
73+
#[not_covariant]
74+
container: Container<'this>,
75+
}
76+
77+
impl<C> Decode<C> for SelfReferencing {
78+
fn decode<D: bincode::de::Decoder<Ctx = C>>(decoder: &mut D) -> Result<Self, DecodeError> {
79+
SelfReferencing::try_new(Bump::new(), |mut bump| {
80+
Container::decode(&mut decoder.with_ctx(&mut bump))
81+
})
82+
}
83+
}
84+
6985
#[test]
7086
fn decode_with_context() {
87+
let config = config::standard();
7188
let bump = Bump::new();
7289
let container = Container {
7390
vec: CodableVec(vec![in &bump; 1, 2, 3]),
7491
};
7592

76-
let bytes = encode_to_vec(&container, config::standard()).unwrap();
93+
let bytes = encode_to_vec(&container, config).unwrap();
7794
let (decoded_container, _) =
78-
decode_from_slice_with_ctx::<_, Container, _>(&bytes, config::standard(), &bump).unwrap();
95+
decode_from_slice_with_ctx::<_, Container, _>(&bytes, config, &bump).unwrap();
7996

8097
assert_eq!(container, decoded_container);
98+
99+
let self_referencing: SelfReferencing = decode_from_slice(&bytes, config).unwrap().0;
100+
self_referencing.with_container(|c| assert_eq!(&container, c))
81101
}

0 commit comments

Comments
 (0)