use std::borrow::Cow;
use std::mem::ManuallyDrop;
use std::ops::Deref;
use crate::error::Error;
use crate::extensions::Extensions;
use crate::ser::{Chunk, SerializerState};
use crate::{Descriptor, Event, Serialize};
use super::{MapEmitter, SeqEmitter, SerializeHandle, StructEmitter};
pub struct SerializeDriver<'a> {
state: SerializerState<'static>,
state_stack: Vec<DriverState>,
serializable_stack: ManuallyDrop<Vec<SerializableOnStack>>,
emitter_stack: ManuallyDrop<Vec<Emitter>>,
next_event: Option<(Event<'a>, &'a dyn Descriptor)>,
}
enum SerializableOnStack {
Handle(SerializeHandle<'static>),
StrCow(Cow<'static, str>),
}
impl Deref for SerializableOnStack {
type Target = dyn Serialize;
fn deref(&self) -> &Self::Target {
match self {
SerializableOnStack::Handle(handle) => &**handle,
SerializableOnStack::StrCow(cow) => &*cow,
}
}
}
enum DriverState {
SeqEmitterAdvance,
MapEmitterNextKey,
MapEmitterNextValue,
StructEmitterAdvance,
Serialize,
PopEmitter,
FinishSerialize,
}
enum Emitter {
Seq(Box<dyn SeqEmitter>),
Map(Box<dyn MapEmitter>),
Struct(Box<dyn StructEmitter>),
}
impl<'a> Drop for SerializeDriver<'a> {
fn drop(&mut self) {
self.next_event.take();
while let Some(_emitter) = self.emitter_stack.pop() {
}
while let Some(_emitter) = self.serializable_stack.pop() {
}
unsafe {
ManuallyDrop::drop(&mut self.serializable_stack);
ManuallyDrop::drop(&mut self.emitter_stack);
}
}
}
const STACK_CAPACITY: usize = 128;
impl<'a> SerializeDriver<'a> {
pub fn new(serializable: &'a dyn Serialize) -> SerializeDriver<'a> {
let serializable =
unsafe { extend_lifetime!(SerializeHandle::Borrowed(serializable), SerializeHandle) };
SerializeDriver {
state: SerializerState {
extensions: Extensions::default(),
descriptor_stack: Vec::with_capacity(STACK_CAPACITY),
},
emitter_stack: ManuallyDrop::new(Vec::with_capacity(STACK_CAPACITY)),
serializable_stack: ManuallyDrop::new({
let mut vec = Vec::with_capacity(STACK_CAPACITY);
vec.push(SerializableOnStack::Handle(serializable));
vec
}),
state_stack: {
let mut vec = Vec::with_capacity(STACK_CAPACITY);
vec.push(DriverState::Serialize);
vec
},
next_event: None,
}
}
pub fn state(&self) -> &SerializerState {
&self.state
}
#[allow(clippy::should_implement_trait)]
pub fn next(&mut self) -> Result<Option<(Event, &dyn Descriptor, &SerializerState)>, Error> {
self.advance()?;
Ok(self
.next_event
.take()
.map(|(event, descriptor)| (event, descriptor, &self.state)))
}
fn advance(&mut self) -> Result<(), Error> {
macro_rules! top_emitter {
($ty:ident) => {
match self.emitter_stack.last_mut() {
Some(Emitter::$ty(emitter)) => emitter,
_ => unreachable!(),
}
};
}
while let Some(state) = self.state_stack.last_mut() {
match state {
DriverState::SeqEmitterAdvance => {
let emitter = top_emitter!(Seq);
match unsafe {
extend_lifetime!(emitter.next(&self.state)?, Option<SerializeHandle>)
} {
Some(item_serializable) => {
*state = DriverState::SeqEmitterAdvance;
self.serializable_stack
.push(SerializableOnStack::Handle(item_serializable));
self.state_stack.push(DriverState::Serialize);
}
None => {
*state = DriverState::PopEmitter;
}
}
}
DriverState::MapEmitterNextKey => {
let emitter = top_emitter!(Map);
match unsafe {
extend_lifetime!(emitter.next_key(&self.state)?, Option<SerializeHandle>)
} {
Some(key_serializable) => {
*state = DriverState::MapEmitterNextValue;
self.serializable_stack
.push(SerializableOnStack::Handle(key_serializable));
self.state_stack.push(DriverState::Serialize);
}
None => {
*state = DriverState::PopEmitter;
}
}
}
DriverState::MapEmitterNextValue => {
let emitter = top_emitter!(Map);
let value_serializable = unsafe {
extend_lifetime!(emitter.next_value(&self.state)?, SerializeHandle)
};
*state = DriverState::MapEmitterNextKey;
self.serializable_stack
.push(SerializableOnStack::Handle(value_serializable));
self.state_stack.push(DriverState::Serialize);
}
DriverState::StructEmitterAdvance => {
let emitter = top_emitter!(Struct);
match unsafe {
extend_lifetime!(
emitter.next(&self.state)?,
Option<(Cow<'_, str>, SerializeHandle)>
)
} {
Some((key, value_serializable)) => {
self.serializable_stack
.push(SerializableOnStack::Handle(value_serializable));
self.state_stack.push(DriverState::Serialize);
self.serializable_stack
.push(SerializableOnStack::StrCow(key));
self.state_stack.push(DriverState::Serialize);
}
None => {
*state = DriverState::PopEmitter;
}
}
}
DriverState::Serialize => {
let serializable = self.serializable_stack.last().unwrap();
match unsafe { extend_lifetime!(serializable.serialize(&self.state)?, Chunk) } {
Chunk::Atom(atom) => {
self.next_event = Some((Event::Atom(atom), unsafe {
extend_lifetime!(serializable.descriptor(), &dyn Descriptor)
}));
*state = DriverState::FinishSerialize;
return Ok(());
}
Chunk::Struct(emitter) => {
let descriptor = unsafe {
extend_lifetime!(serializable.descriptor(), &dyn Descriptor)
};
self.next_event = Some((Event::MapStart, descriptor));
self.emitter_stack.push(Emitter::Struct(emitter));
*state = DriverState::StructEmitterAdvance;
self.state.descriptor_stack.push(descriptor);
return Ok(());
}
Chunk::Map(emitter) => {
let descriptor = unsafe {
extend_lifetime!(serializable.descriptor(), &dyn Descriptor)
};
self.next_event = Some((Event::MapStart, descriptor));
self.emitter_stack.push(Emitter::Map(emitter));
*state = DriverState::MapEmitterNextKey;
self.state.descriptor_stack.push(descriptor);
return Ok(());
}
Chunk::Seq(emitter) => {
let descriptor = unsafe {
extend_lifetime!(serializable.descriptor(), &dyn Descriptor)
};
self.next_event = Some((Event::SeqStart, descriptor));
self.emitter_stack.push(Emitter::Seq(emitter));
*state = DriverState::SeqEmitterAdvance;
self.state.descriptor_stack.push(descriptor);
return Ok(());
}
}
}
DriverState::PopEmitter => {
let descriptor = self.state.descriptor_stack.pop().unwrap();
*state = DriverState::FinishSerialize;
self.next_event = Some((
match self.emitter_stack.pop().unwrap() {
Emitter::Seq(_) => Event::SeqEnd,
Emitter::Map(_) | Emitter::Struct(_) => Event::MapEnd,
},
descriptor,
));
return Ok(());
}
DriverState::FinishSerialize => {
self.state_stack.pop();
let serializable = self.serializable_stack.pop().unwrap();
serializable.finish(&self.state)?;
}
}
}
Ok(())
}
}
#[test]
fn test_seq_emitting() {
let vec = vec![vec![1u64, 2], vec![3, 4]];
let mut driver = SerializeDriver::new(&vec);
let mut events = Vec::new();
while let Some((event, _, _)) = driver.next().unwrap() {
events.push(event.to_static());
}
assert_eq!(
events,
vec![
Event::SeqStart,
Event::SeqStart,
1u64.into(),
2u64.into(),
Event::SeqEnd,
Event::SeqStart,
3u64.into(),
4u64.into(),
Event::SeqEnd,
Event::SeqEnd,
],
);
}
#[test]
fn test_map_emitting() {
let mut map = std::collections::BTreeMap::new();
map.insert((1u32, 2u32), "first");
map.insert((2, 3), "second");
let mut driver = SerializeDriver::new(&map);
let mut events = Vec::new();
while let Some((event, _, _)) = driver.next().unwrap() {
events.push(event.to_static());
}
assert_eq!(
events,
vec![
Event::MapStart,
Event::SeqStart,
1u64.into(),
2u64.into(),
Event::SeqEnd,
"first".into(),
Event::SeqStart,
2u64.into(),
3u64.into(),
Event::SeqEnd,
"second".into(),
Event::MapEnd
]
);
}