use alloc::boxed::Box;
use alloc::vec::Vec;
use core::marker::PhantomData;
use crate::Text;
use crate::arena::Buffer;
use crate::de::layer::{Layer, LayerEvent, Next};
use crate::de::lexical::ContentKey;
use crate::de::limits::{Limits, LimitsLayer};
use crate::de::{Deserialize, InlineEvent, Sink, SinkHandle};
use crate::error::{Error, ErrorKind};
use crate::event::{Atom, ContainerShape, Event};
use crate::unwind::pop_all;
use crate::{Context, State};
pub struct DeserializeDriver<'a, 'de: 'a> {
core: DriverCore<'de>,
layers: Vec<Box<dyn Layer>>,
emit_layered: Option<EmitLayered<'de>>,
has_limits: bool,
_marker: PhantomData<&'a mut ()>,
}
type EmitLayered<'de> =
fn(&mut Vec<Box<dyn Layer>>, &mut DriverCore<'de>, LayerEvent<'_, 'de>) -> Result<(), Error>;
pub(crate) struct DriverCore<'de> {
pub(crate) state: State,
root: Option<SinkHandle<'de, 'de>>,
sink_stack: Vec<(SinkHandle<'de, 'de>, Container)>,
transient: usize,
}
const STACK_CAPACITY: usize = 128;
const _: () = {
const fn assert_send<T: Send>() {}
assert_send::<DeserializeDriver<'static, 'static>>();
};
#[derive(Copy, Clone)]
enum Container {
Map(bool, bool),
Seq(bool),
Inline(u32),
Content(bool, bool, bool),
SkipValue,
Empty(bool),
}
impl Container {
fn new(is_map: bool) -> Container {
if is_map {
Container::Map(true, false)
} else {
Container::Seq(false)
}
}
#[inline(always)]
fn is_multimap(&self) -> bool {
matches!(self, Container::Map(_, true))
}
}
unsafe fn erase_lifetime<'de>(handle: SinkHandle<'_, 'de>) -> SinkHandle<'de, 'de> {
unsafe { core::mem::transmute::<SinkHandle<'_, 'de>, SinkHandle<'de, 'de>>(handle) }
}
struct Lent<'a, 'de> {
driver: *mut DeserializeDriver<'a, 'de>,
id: usize,
outer: usize,
}
impl Drop for Lent<'_, '_> {
fn drop(&mut self) {
let driver = unsafe { &mut *self.driver };
if driver.core.transient == self.id {
driver.core.transient = self.outer;
return;
}
let replacement = core::mem::replace(
&mut driver.core,
DriverCore {
state: State::new(),
root: None,
sink_stack: Vec::new(),
transient: 0,
},
);
drop(replacement);
}
}
fn shorten<'r, 'a, 'de, 'f>(
driver: &'r mut DeserializeDriver<'a, 'de>,
) -> &'r mut DeserializeDriver<'r, 'f>
where
'de: 'f,
'f: 'r,
{
unsafe { &mut *(driver as *mut DeserializeDriver<'a, 'de>).cast::<DeserializeDriver<'r, 'f>>() }
}
impl<'a, 'de> DeserializeDriver<'a, 'de> {
pub fn new<T: Deserialize<'de>>(out: &'a mut Option<T>) -> DeserializeDriver<'a, 'de> {
DeserializeDriver::from_fn(|state| {
state.raw_requested = T::__private_raw();
T::deserialize_into(out, state)
})
}
pub fn multimap_value<T: Deserialize<'de>>(
out: &'a mut Option<T>,
) -> DeserializeDriver<'a, 'de> {
if T::__private_collects() {
DeserializeDriver::from_fn(|state| T::__private_collect_into(out, state))
} else {
DeserializeDriver::new(out)
}
}
pub fn update<T: Deserialize<'de>>(value: &'a mut T) -> DeserializeDriver<'a, 'de> {
DeserializeDriver::from_fn(|state| T::deserialize_update(value, state))
}
pub fn from_fn(
make: impl FnOnce(&mut State) -> SinkHandle<'a, 'de>,
) -> DeserializeDriver<'a, 'de> {
let mut state = State::new();
let sink = make(&mut state);
DeserializeDriver::from_state(state, sink)
}
pub(crate) fn from_state(
state: State,
sink: SinkHandle<'a, 'de>,
) -> DeserializeDriver<'a, 'de> {
DeserializeDriver::with_state(state, sink, STACK_CAPACITY)
}
pub(crate) fn nested<R>(
state: &mut State,
sink: SinkHandle<'_, 'de>,
is_map_key: bool,
f: impl FnOnce(&mut DeserializeDriver<'_, 'de>) -> R,
) -> R {
let depth = state.depth;
let outer_is_map_key = state.is_map_key;
let outer_is_multimap = state.is_multimap;
let outer_raw_format = state.raw_format.take();
let mut driver = DeserializeDriver::with_state(state.take(), sink, 0);
driver.core.state.is_map_key = is_map_key;
let rv = f(&mut driver);
driver.core.release();
*state = driver.core.state.take();
drop(driver);
state.depth = depth;
state.is_map_key = outer_is_map_key;
state.is_multimap = outer_is_multimap;
state.raw_format = outer_raw_format;
rv
}
fn with_state(
mut state: State,
sink: SinkHandle<'a, 'de>,
capacity: usize,
) -> DeserializeDriver<'a, 'de> {
let sink_stack = state
.arena
.take_vec(Buffer::SinkStack)
.unwrap_or_else(|| Vec::with_capacity(capacity));
DeserializeDriver {
core: DriverCore {
state,
sink_stack,
root: Some(unsafe { erase_lifetime(sink) }),
transient: 0,
},
layers: Vec::new(),
emit_layered: None,
has_limits: false,
_marker: PhantomData,
}
}
pub fn state(&self) -> &State {
&self.core.state
}
pub fn state_mut(&mut self) -> &mut State {
&mut self.core.state
}
pub fn set_context(&mut self, context: Context) {
if core::mem::take(&mut self.has_limits) {
self.layers.pop();
}
if let Some(limits) = context.get::<Limits>()
&& !limits.is_unlimited()
{
self.layers.push(Box::new(LimitsLayer::new(*limits)));
self.emit_layered = Some(emit_layered);
self.has_limits = true;
}
self.core.state.set_context(context);
}
#[inline(never)]
pub fn set_default_context(&mut self, context: Context) {
let mut merged = self.core.state.context().clone();
if merged.fill_from(&context) {
self.set_context(merged);
}
}
pub fn context(&self) -> &Context {
self.core.state.context()
}
pub fn push_layer<L: Layer + 'static>(&mut self, layer: L) {
let idx = self.layers.len() - usize::from(self.has_limits);
self.layers.insert(idx, Box::new(layer));
self.emit_layered = Some(emit_layered);
}
pub fn wrap_sink<F>(&mut self, f: F)
where
F: for<'x> FnOnce(SinkHandle<'x, 'de>, &mut State) -> SinkHandle<'x, 'de>,
{
assert!(
self.core.sink_stack.is_empty(),
"sinks can only be wrapped before events are emitted"
);
assert!(
self.core.transient == 0,
"sinks cannot be wrapped in a transient driver"
);
let root = self.core.root.take().expect("no active sink");
self.core.root = Some(f(root, &mut self.core.state));
}
#[inline]
pub fn emit<'e, E: Into<Event<'e>>>(&mut self, event: E) -> Result<(), Error> {
match event.into() {
Event::Atom(atom) => self.atom_event(atom),
Event::MapStart(shape) => self.start_event(true, shape),
Event::SeqStart(shape) => self.start_event(false, shape),
Event::MapEnd => self.end_event(true),
Event::SeqEnd => self.end_event(false),
}
}
#[inline]
pub fn emit_borrowed<E: Into<Event<'de>>>(&mut self, event: E) -> Result<(), Error> {
match event.into() {
Event::Atom(atom) => self.borrowed_atom_event(atom),
Event::MapStart(shape) => self.start_event(true, shape),
Event::SeqStart(shape) => self.start_event(false, shape),
Event::MapEnd => self.end_event(true),
Event::SeqEnd => self.end_event(false),
}
}
pub fn transient<'f, R>(&mut self, f: impl FnOnce(&mut DeserializeDriver<'_, 'f>) -> R) -> R
where
'de: 'f,
{
let marker = 0u8;
let id = &marker as *const u8 as usize;
let outer = core::mem::replace(&mut self.core.transient, id);
let driver: *mut DeserializeDriver<'a, 'de> = self;
let lent = Lent { driver, id, outer };
let rv = f(shorten(unsafe { &mut *driver }));
let replaced = unsafe { (*driver).core.transient != id };
drop(lent);
assert!(!replaced, "the driver was replaced while it was lent out");
rv
}
#[inline(never)]
fn atom_event(&mut self, atom: Atom) -> Result<(), Error> {
if !self.layers.is_empty() {
return self.emit_layered(LayerEvent::new(Event::Atom(atom)));
}
let rv = self.core.deliver_atom(atom);
self.core.finish_event(rv)
}
#[inline(never)]
fn borrowed_atom_event(&mut self, atom: Atom<'de>) -> Result<(), Error> {
if !self.layers.is_empty() {
return self.emit_layered(LayerEvent::borrowed(Event::Atom(atom)));
}
let rv = self.core.deliver_borrowed_atom(atom);
self.core.finish_event(rv)
}
#[inline(never)]
fn start_event(&mut self, is_map: bool, shape: ContainerShape) -> Result<(), Error> {
if !self.layers.is_empty() {
let event = if is_map {
Event::MapStart(shape)
} else {
Event::SeqStart(shape)
};
return self.emit_layered(LayerEvent::new(event));
}
let rv = self.core.deliver_start(is_map, shape);
self.core.finish_event(rv)
}
#[inline(never)]
fn end_event(&mut self, is_map: bool) -> Result<(), Error> {
if !self.layers.is_empty() {
let event = if is_map { Event::MapEnd } else { Event::SeqEnd };
return self.emit_layered(LayerEvent::new(event));
}
let rv = self.core.deliver_end(is_map);
self.core.finish_event(rv)
}
#[cold]
#[inline(never)]
fn emit_layered(&mut self, event: LayerEvent<'_, 'de>) -> Result<(), Error> {
let emit = self.emit_layered.expect("layers without push_layer");
let rv = emit(&mut self.layers, &mut self.core, event);
self.core.finish_event(rv)
}
}
fn emit_layered<'de>(
layers: &mut Vec<Box<dyn Layer>>,
core: &mut DriverCore<'de>,
event: LayerEvent<'_, 'de>,
) -> Result<(), Error> {
Next::new(layers, core).emit(event)
}
impl<'de> DriverCore<'de> {
#[inline(always)]
fn finish_event(&mut self, rv: Result<(), Error>) -> Result<(), Error> {
let rv = match rv {
Ok(()) => Ok(()),
Err(err) if err.is_raw_request() => Err(err),
Err(err) if self.state.discards_errors => Err(err),
Err(err) => Err(self.state.error_in_context(err)),
};
self.state.clear_event();
rv
}
#[inline]
pub(crate) fn update_position(&mut self, event: &Event<'_>) {
self.state.is_map_key = match event {
Event::MapEnd | Event::SeqEnd => false,
_ => matches!(self.sink_stack.last(), Some((_, Container::Map(true, _)))),
};
}
#[inline(always)]
pub(crate) fn dispatch(&mut self, event: Event<'_>) -> Result<(), Error> {
match event {
Event::Atom(atom) => self.deliver_atom(atom),
Event::MapStart(shape) => self.deliver_start(true, shape),
Event::SeqStart(shape) => self.deliver_start(false, shape),
Event::MapEnd => self.deliver_end(true),
Event::SeqEnd => self.deliver_end(false),
}
}
#[inline(always)]
pub(crate) fn dispatch_borrowed(&mut self, event: Event<'de>) -> Result<(), Error> {
match event {
Event::Atom(atom) => self.deliver_borrowed_atom(atom),
Event::MapStart(shape) => self.deliver_start(true, shape),
Event::SeqStart(shape) => self.deliver_start(false, shape),
Event::MapEnd => self.deliver_end(true),
Event::SeqEnd => self.deliver_end(false),
}
}
#[inline(always)]
fn deliver_atom(&mut self, atom: Atom) -> Result<(), Error> {
match self.emit_atom(atom) {
Ok(()) => Ok(()),
Err(err) => self.recover(err, None),
}
}
#[inline(always)]
fn deliver_borrowed_atom(&mut self, atom: Atom<'de>) -> Result<(), Error> {
if self.transient != 0 {
return self.deliver_atom(atom);
}
match self.emit_borrowed_atom(atom) {
Ok(()) => Ok(()),
Err(err) => self.recover(err, None),
}
}
#[inline(always)]
fn deliver_start(&mut self, is_map: bool, shape: ContainerShape) -> Result<(), Error> {
match self.emit_start(is_map, shape) {
Ok(()) => Ok(()),
Err(err) => self.recover(err, Some(is_map)),
}
}
#[inline(always)]
fn deliver_end(&mut self, is_map: bool) -> Result<(), Error> {
match self.emit_end(is_map) {
Ok(()) => Ok(()),
Err(err) => self.recover(err, None),
}
}
#[cold]
#[inline(never)]
fn recover(&mut self, err: Error, opened: Option<bool>) -> Result<(), Error> {
if err.is_raw_request() {
return Err(err);
}
let mut err = if self.state.discards_errors {
err
} else {
self.state.error_in_context(err)
};
if let Some((_, container @ Container::Inline(_))) = self.sink_stack.last_mut() {
*container = Container::Seq(true);
self.sink_stack
.push((SinkHandle::null(), Container::Seq(false)));
}
for idx in (0..self.sink_stack.len()).rev() {
let (sink, container) = &mut self.sink_stack[idx];
err = match sink.recover(err, &mut self.state) {
Ok(()) => {
if let Container::Map(is_key @ false, _) = container {
*is_key = true;
self.sink_stack
.insert(idx + 1, (SinkHandle::null(), Container::SkipValue));
}
if let Some(is_map) = opened {
self.state.depth += 1;
self.sink_stack
.push((SinkHandle::null(), Container::new(is_map)));
}
return Ok(());
}
Err(err) => err,
};
*sink = SinkHandle::null();
*container = match *container {
Container::Seq(_) => Container::Seq(false),
other => other,
};
}
self.sink_stack.clear();
Err(err)
}
#[cold]
#[inline(never)]
fn skip_value(&mut self) {
self.state.is_map_key = false;
self.sink_stack.pop();
}
#[inline(always)]
fn emit_borrowed_atom(&mut self, atom: Atom<'de>) -> Result<(), Error> {
match self.sink_stack.last_mut() {
Some((sink, Container::Map(is_key, _))) => {
let key = *is_key;
*is_key = !key;
self.state.is_map_key = key;
if key {
sink.__private_borrowed_key_atom(atom, &mut self.state)
} else {
sink.__private_borrowed_value_atom(atom, &mut self.state)
}
}
Some((sink, Container::Seq(_))) => {
self.state.is_map_key = false;
sink.__private_borrowed_value_atom(atom, &mut self.state)
}
Some((sink, Container::Inline(index))) => {
let item = *index;
*index = item.saturating_add(1);
self.state.is_map_key = false;
sink.__private_inline_atom(item as usize, atom, &mut self.state)
}
Some((sink, Container::Content(is_key, take, found))) => {
match content_atom(&self.state, is_key, take, found, &atom)? {
true => sink.borrowed_atom(atom, &mut self.state),
false => Ok(()),
}
}
Some((_, Container::SkipValue)) => {
self.skip_value();
Ok(())
}
Some((_, Container::Empty(_))) => Err(not_empty_error()),
None => {
let sink = self.root.as_mut().expect("no active sink");
sink.borrowed_atom(atom, &mut self.state)?;
sink.finish(&mut self.state)
}
}
}
#[inline(always)]
fn emit_atom(&mut self, atom: Atom) -> Result<(), Error> {
match self.sink_stack.last_mut() {
Some((sink, Container::Map(is_key, _))) => {
let key = *is_key;
*is_key = !key;
self.state.is_map_key = key;
if key {
sink.__private_key_atom(atom, &mut self.state)
} else {
sink.__private_value_atom(atom, &mut self.state)
}
}
Some((sink, Container::Seq(_))) => {
self.state.is_map_key = false;
sink.__private_value_atom(atom, &mut self.state)
}
Some((sink, Container::Inline(index))) => {
let item = *index;
*index = item.saturating_add(1);
self.state.is_map_key = false;
sink.__private_inline_atom(item as usize, atom, &mut self.state)
}
Some((sink, Container::Content(is_key, take, found))) => {
match content_atom(&self.state, is_key, take, found, &atom)? {
true => sink.atom(atom, &mut self.state),
false => Ok(()),
}
}
Some((_, Container::SkipValue)) => {
self.skip_value();
Ok(())
}
Some((_, Container::Empty(_))) => Err(not_empty_error()),
None => {
let sink = self.root.as_mut().expect("no active sink");
sink.atom(atom, &mut self.state)?;
sink.finish(&mut self.state)
}
}
}
#[inline(always)]
fn emit_start(&mut self, is_map: bool, shape: ContainerShape) -> Result<(), Error> {
let mut sink = match self.sink_stack.last_mut() {
Some((parent, Container::Map(is_key, _))) => {
let key = *is_key;
*is_key = !key;
self.state.is_map_key = key;
let sink = if key {
parent.next_key(&mut self.state)?
} else {
parent.next_value(&mut self.state)?
};
unsafe { erase_lifetime(sink) }
}
Some((parent, container @ Container::Seq(_))) => {
self.state.is_map_key = false;
if let (Container::Seq(true), false) = (*container, is_map) {
self.state.container_shape = shape;
parent.__private_inline_event(InlineEvent::Start, &mut self.state)?;
*container = Container::Inline(0);
self.state.is_multimap = false;
self.state.depth += 1;
return Ok(());
}
let sink = parent.next_value(&mut self.state)?;
unsafe { erase_lifetime(sink) }
}
Some((parent, Container::Inline(index))) => {
let item = *index;
*index = item.saturating_add(1);
self.state.is_map_key = false;
self.state.container_shape = shape;
let event = InlineEvent::Container(item as usize, is_map);
return parent.__private_inline_event(event, &mut self.state);
}
Some((_, Container::Content(is_key, take, _))) => {
if *is_key || *take {
return Err(content_container_error(*is_key));
}
*is_key = true;
self.state.is_map_key = false;
self.state.depth += 1;
self.sink_stack
.push((SinkHandle::null(), Container::new(is_map)));
return Ok(());
}
Some((_, Container::Empty(_))) => return Err(not_empty_error()),
Some((_, container @ Container::SkipValue)) => {
self.state.is_map_key = false;
*container = Container::new(is_map);
self.state.depth += 1;
return Ok(());
}
None => self.root.take().expect("no active sink"),
};
self.state.container_shape = shape;
let container = if is_map {
match sink.map(&mut self.state) {
Ok(()) => Container::Map(true, shape.is_multimap()),
Err(err) if err.kind().is_rejection() && shape.is_ambiguous_empty() => {
empty_as_seq(&mut sink, err, &mut self.state)?
}
Err(err) if err.kind().is_rejection() && ContentKey::of(&self.state).is_some() => {
Container::Content(true, false, false)
}
Err(err) => return Err(err),
}
} else {
match sink.__private_seq(&mut self.state) {
Ok(inline) => Container::Seq(inline),
Err(err) if err.is_raw_request() => {
return self.start_raw_seq(sink, err);
}
Err(err) if err.kind().is_rejection() && shape.is_ambiguous_empty() => {
empty_as_map(&mut sink, err, &mut self.state)?
}
Err(err) => return Err(err),
}
};
self.state.is_multimap = container.is_multimap();
self.state.depth += 1;
self.sink_stack.push((sink, container));
Ok(())
}
#[inline(always)]
fn emit_end(&mut self, is_map: bool) -> Result<(), Error> {
match self.sink_stack.last() {
Some((_, Container::Map(..) | Container::Content(..))) if is_map => {}
Some((_, Container::Empty(map_in_input))) if *map_in_input == is_map => {}
Some((_, Container::Seq(_))) if !is_map => {}
Some((_, Container::Inline(_))) if !is_map => return self.end_inline(),
_ => panic!("not inside a {}", if is_map { "map" } else { "sequence" }),
}
let (mut sink, container) = self.sink_stack.pop().unwrap();
self.state.is_multimap = container.is_multimap();
let mut rv = Ok(());
if let Container::Content(_, _, false) = container {
self.state.is_map_key = false;
rv = sink
.atom(Atom::Lexical(Text::borrowed("")), &mut self.state)
.map_err(|err| {
if err.kind().is_rejection() {
super::default_container(&mut sink, "map", &self.state).unwrap_err()
} else {
err
}
});
}
let rv = rv.and_then(|()| sink.finish(&mut self.state));
self.state.depth -= 1;
self.state.is_multimap = self
.sink_stack
.last()
.is_some_and(|(_, container)| container.is_multimap());
if self.sink_stack.is_empty() {
self.root = Some(sink);
} else {
sink.release(&mut self.state);
}
rv
}
#[cold]
#[inline(never)]
fn start_raw_seq(&mut self, sink: SinkHandle<'de, 'de>, request: Error) -> Result<(), Error> {
self.state.is_multimap = false;
self.state.depth += 1;
self.sink_stack.push((sink, Container::Seq(false)));
Err(request)
}
#[inline(always)]
fn end_inline(&mut self) -> Result<(), Error> {
let (sink, container) = self.sink_stack.last_mut().unwrap();
let Container::Inline(len) = *container else {
unreachable!()
};
*container = Container::Seq(true);
self.state.is_multimap = false;
let rv = sink.__private_inline_event(InlineEvent::End(len as usize), &mut self.state);
self.state.depth -= 1;
rv
}
}
#[cold]
#[inline(never)]
fn content_atom(
state: &State,
is_key: &mut bool,
take: &mut bool,
found: &mut bool,
atom: &Atom<'_>,
) -> Result<bool, Error> {
let was_key = *is_key;
*is_key = !was_key;
if was_key {
*take = match atom {
Atom::Str(key) | Atom::Lexical(key) => ContentKey::of(state) == Some(&**key),
_ => false,
};
return Ok(false);
}
if !core::mem::take(take) {
return Ok(false);
}
if core::mem::replace(found, true) {
return Err(Error::new(
ErrorKind::InvalidType,
"unexpected map with more than one content, expected a single value",
));
}
Ok(true)
}
#[cold]
#[inline(never)]
fn empty_as_map(
sink: &mut SinkHandle<'_, '_>,
err: Error,
state: &mut State,
) -> Result<Container, Error> {
match sink.map(state) {
Ok(()) => Ok(Container::Empty(false)),
Err(_) => Err(err),
}
}
#[cold]
#[inline(never)]
fn empty_as_seq(
sink: &mut SinkHandle<'_, '_>,
err: Error,
state: &mut State,
) -> Result<Container, Error> {
match sink.__private_seq(state) {
Ok(_) => Ok(Container::Empty(true)),
Err(request) if request.is_raw_request() => {
state.raw_requested = None;
Ok(Container::Empty(true))
}
Err(_) => Err(err),
}
}
#[cold]
#[inline(never)]
fn not_empty_error() -> Error {
Error::new(
ErrorKind::InvalidState,
"item in a container that was announced as empty",
)
}
#[cold]
fn content_container_error(is_key: bool) -> Error {
Error::new(
ErrorKind::InvalidType,
if is_key {
"unexpected map with a key that is not a single value, expected a single value"
} else {
"unexpected map whose content is not a single value, expected a single value"
},
)
}
impl<'de> DriverCore<'de> {
fn release(&mut self) {
let state = &mut self.state;
pop_all(&mut self.sink_stack, |(sink, _)| sink.release(state));
if let Some(root) = self.root.take() {
root.release(&mut self.state);
}
let stack = core::mem::take(&mut self.sink_stack);
self.state.arena.put_vec(Buffer::SinkStack, stack);
}
}
impl<'de> Drop for DriverCore<'de> {
fn drop(&mut self) {
self.release();
}
}
#[test]
fn test_arena_is_not_orphaned() {
use crate::arena::ORPHANED;
use crate::de::Recording;
use alloc::collections::BTreeMap;
use alloc::string::String;
let orphaned = ORPHANED.with(|x| x.get());
let mut out = None::<Vec<BTreeMap<String, Vec<u32>>>>;
let mut driver = DeserializeDriver::new(&mut out);
for event in [
Event::seq_start(),
Event::map_start(),
"a".into(),
Event::seq_start(),
1u64.into(),
Event::SeqEnd,
Event::MapEnd,
Event::SeqEnd,
] {
driver.emit(event).unwrap();
}
drop(driver);
assert_eq!(out.unwrap()[0]["a"], [1]);
let mut recording = Recording::new();
let mut driver = DeserializeDriver::from_fn(|state| recording.recorder(state));
for event in [Event::seq_start(), 1u64.into(), 2u64.into(), Event::SeqEnd] {
driver.emit(event).unwrap();
}
drop(driver);
let mut driver_out = None::<()>;
let mut driver = DeserializeDriver::new(&mut driver_out);
let mut out = None::<Vec<u32>>;
let state = driver.state_mut();
recording
.replay(Vec::<u32>::deserialize_into(&mut out, state), state)
.unwrap();
drop(driver);
assert_eq!(out.unwrap(), [1, 2]);
let mut out = None::<Vec<Vec<u32>>>;
let mut driver = DeserializeDriver::new(&mut out);
driver.emit(Event::seq_start()).unwrap();
driver.emit(Event::seq_start()).unwrap();
assert!(driver.emit("not a number").is_err());
drop(driver);
assert_eq!(ORPHANED.with(|x| x.get()), orphaned);
}
#[test]
fn test_sink_outlives_state() {
use crate::arena::ORPHANED;
use crate::de::OwnedSink;
use alloc::collections::BTreeMap;
use alloc::string::String;
let orphaned = ORPHANED.with(|x| x.get());
let mut out = None::<Vec<BTreeMap<String, u32>>>;
let mut driver = DeserializeDriver::from_fn(|_| {
Vec::<BTreeMap<String, u32>>::deserialize_into(&mut out, &mut State::new())
});
assert_eq!(ORPHANED.with(|x| x.get()), orphaned + 1);
for event in [
Event::seq_start(),
Event::map_start(),
"a".into(),
1u64.into(),
Event::MapEnd,
Event::SeqEnd,
] {
driver.emit(event).unwrap();
}
drop(driver);
assert_eq!(out.unwrap()[0]["a"], 1);
let mut driver_out = None::<()>;
let mut driver = DeserializeDriver::new(&mut driver_out);
let mut owned = OwnedSink::<Vec<u32>>::deserialize(driver.state_mut());
drop(driver);
assert_eq!(ORPHANED.with(|x| x.get()), orphaned + 2);
let mut driver = DeserializeDriver::from_fn(|_| SinkHandle::to(owned.get_mut()));
for event in [Event::seq_start(), 1u64.into(), 2u64.into(), Event::SeqEnd] {
driver.emit(event).unwrap();
}
drop(driver);
assert_eq!(owned.take().unwrap(), [1, 2]);
std::thread::spawn(move || drop(owned)).join().unwrap();
}
#[test]
fn test_driver() {
let mut out: Option<alloc::collections::BTreeMap<u32, String>> = None;
{
let mut driver = DeserializeDriver::new(&mut out);
driver.emit(Event::map_start()).unwrap();
driver.emit(1u64).unwrap();
driver.emit("Hello").unwrap();
driver.emit(2u64).unwrap();
driver.emit("World").unwrap();
driver.emit(Event::MapEnd).unwrap();
}
let map = out.unwrap();
assert_eq!(map[&1], "Hello");
assert_eq!(map[&2], "World");
}