use alloc::borrow::Cow;
use alloc::string::String;
use core::fmt;
use deser_core::State;
use deser_core::de::{Deserialize, OwnedSink, Sink, SinkHandle, Slot, default_atom};
use deser_core::ext::{ExtValue, Extension};
use deser_core::ser::{Describe, Emit, Serialize};
use deser_core::{Atom, ContainerShape, Error, Text};
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Global {
path: String,
split: usize,
}
impl Global {
pub fn new(module: &str, name: &str) -> Global {
let mut path = String::with_capacity(module.len() + name.len() + 1);
path.push_str(module);
path.push('.');
path.push_str(name);
Global {
path,
split: module.len(),
}
}
pub fn module(&self) -> &str {
&self.path[..self.split]
}
pub fn name(&self) -> &str {
&self.path[self.split + 1..]
}
pub fn path(&self) -> &str {
&self.path
}
}
impl fmt::Debug for Global {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Global({})", self.path)
}
}
impl fmt::Display for Global {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.path)
}
}
impl Extension for Global {
fn name(&self) -> &str {
"python global"
}
fn fallback(&self) -> Atom<'_> {
Atom::Str(Text::borrowed(&self.path))
}
}
impl Serialize for Global {
fn serialize<'a>(value: &'a Self, _state: &mut State) -> Result<Emit<'a>, Error> {
Ok(Emit::Atom(Atom::Ext(ExtValue::borrowed(value))))
}
}
impl<'de> Deserialize<'de> for Global {
fn deserialize_atom(slot: &mut Slot<Self>, atom: Atom, state: &mut State) -> Result<(), Error> {
match atom {
Atom::Ext(ref ext) => match ext.downcast_ref::<Global>() {
Some(value) => {
slot.set(value.clone());
Ok(())
}
None => default_atom(slot, atom, state),
},
other => default_atom(slot, other, state),
}
}
fn expecting() -> Cow<'static, str> {
Cow::Borrowed("python global")
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Reference {
id: u64,
}
impl Reference {
pub const fn new(id: u64) -> Reference {
Reference { id }
}
pub const fn id(self) -> u64 {
self.id
}
}
impl Extension for Reference {
fn name(&self) -> &str {
"pickle reference"
}
fn fallback(&self) -> Atom<'_> {
Atom::Null
}
}
impl Serialize for Reference {
fn serialize<'a>(value: &'a Self, _state: &mut State) -> Result<Emit<'a>, Error> {
Ok(Emit::Atom(Atom::Ext(ExtValue::borrowed(value))))
}
}
impl<'de> Deserialize<'de> for Reference {
fn deserialize_atom(slot: &mut Slot<Self>, atom: Atom, state: &mut State) -> Result<(), Error> {
match atom {
Atom::Ext(ref ext) => match ext.downcast_ref::<Reference>() {
Some(&value) => {
slot.set(value);
Ok(())
}
None => default_atom(slot, atom, state),
},
other => default_atom(slot, other, state),
}
}
fn expecting() -> Cow<'static, str> {
Cow::Borrowed("pickle reference")
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Kind {
Tuple,
Set,
FrozenSet,
ByteArray,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Form {
State,
Slots,
Items,
Arguments,
Argument,
}
#[derive(Debug, Default, Clone)]
pub(crate) struct ClassData(pub(crate) Option<Global>);
#[derive(Debug, Default, Clone)]
pub(crate) struct FormData(pub(crate) Option<Form>);
#[derive(Debug, Default, Clone)]
pub(crate) struct KindData(pub(crate) Option<Kind>);
#[derive(Debug, Default, Clone)]
pub(crate) struct SharedIdData(pub(crate) Option<u64>);
pub fn take_class(state: &mut State) -> Option<Global> {
state.take_event::<ClassData>().and_then(|class| class.0)
}
pub fn set_class(state: &mut State, class: Global) {
state.event_mut::<ClassData>().0 = Some(class);
}
pub fn take_form(state: &mut State) -> Option<Form> {
state.take_event::<FormData>().and_then(|form| form.0)
}
pub fn set_form(state: &mut State, form: Form) {
state.event_mut::<FormData>().0 = Some(form);
}
pub fn take_kind(state: &mut State) -> Option<Kind> {
state.take_event::<KindData>().and_then(|kind| kind.0)
}
pub fn set_kind(state: &mut State, kind: Kind) {
state.event_mut::<KindData>().0 = Some(kind);
}
pub fn take_shared_id(state: &mut State) -> Option<u64> {
state.take_event::<SharedIdData>().and_then(|id| id.0)
}
pub fn set_shared_id(state: &mut State, id: u64) {
state.event_mut::<SharedIdData>().0 = Some(id);
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Object<T> {
pub class: Option<Global>,
pub form: Option<Form>,
pub value: T,
}
impl<T> Object<T> {
pub fn new(class: Global, value: T) -> Object<T> {
Object {
class: Some(class),
form: None,
value,
}
}
pub fn with_form(class: Global, form: Form, value: T) -> Object<T> {
Object {
class: Some(class),
form: Some(form),
value,
}
}
pub fn into_inner(self) -> T {
self.value
}
}
impl<T: fmt::Debug> fmt::Debug for Object<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.class {
Some(ref class) => {
write!(f, "{} ", class)?;
fmt::Debug::fmt(&self.value, f)
}
None => fmt::Debug::fmt(&self.value, f),
}
}
}
impl<T: Serialize> Serialize for Object<T> {
fn serialize<'a>(this: &'a Self, state: &mut State) -> Result<Emit<'a>, Error> {
let emit = T::serialize(&this.value, state)?;
if let Some(ref class) = this.class {
set_class(state, class.clone());
if let Some(form) = this.form {
set_form(state, form);
}
}
Ok(emit)
}
fn finish(this: &Self, state: &mut State) -> Result<(), Error> {
T::finish(&this.value, state)
}
fn is_optional(this: &Self) -> bool {
T::is_optional(&this.value)
}
fn container_shape(this: &Self) -> ContainerShape {
T::container_shape(&this.value)
}
fn describe(this: &Self, d: &mut dyn Describe) {
T::describe(&this.value, d)
}
}
impl<'de, T: Deserialize<'de>> Deserialize<'de> for Object<T> {
fn deserialize_into<'out>(
out: &'out mut Option<Self>,
state: &mut State,
) -> SinkHandle<'out, 'de> {
SinkHandle::arena(
ObjectSink {
out,
slot: None,
compound: None,
class: None,
form: None,
},
state,
)
}
fn expecting() -> Cow<'static, str> {
T::expecting()
}
fn describe_type(d: &mut dyn Describe) {
T::describe_type(d)
}
}
struct ObjectSink<'a, 'de, T> {
out: &'a mut Option<Object<T>>,
slot: Option<T>,
compound: Option<OwnedSink<'de, T>>,
class: Option<Global>,
form: Option<Form>,
}
impl<'a, 'de, T: Deserialize<'de>> ObjectSink<'a, 'de, T> {
fn take(&mut self, state: &mut State) {
self.class = take_class(state);
self.form = take_form(state);
}
fn compound(&mut self, state: &mut State) -> &mut dyn Sink<'de> {
self.compound
.get_or_insert_with(|| OwnedSink::deserialize(state))
.get_mut()
}
}
impl<'a, 'de, T: Deserialize<'de>> Sink<'de> for ObjectSink<'a, 'de, T> {
fn atom(&mut self, atom: Atom, state: &mut State) -> Result<(), Error> {
self.take(state);
let mut sink = T::deserialize_into(&mut self.slot, state);
sink.atom(atom, state)?;
sink.finish(state)
}
fn borrowed_atom(&mut self, atom: Atom<'de>, state: &mut State) -> Result<(), Error> {
self.take(state);
let mut sink = T::deserialize_into(&mut self.slot, state);
sink.borrowed_atom(atom, state)?;
sink.finish(state)
}
fn map(&mut self, state: &mut State) -> Result<(), Error> {
self.take(state);
self.compound(state).map(state)
}
fn seq(&mut self, state: &mut State) -> Result<(), Error> {
self.take(state);
self.compound(state).seq(state)
}
fn next_key(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
self.compound(state).next_key(state)
}
fn next_value(&mut self, state: &mut State) -> Result<SinkHandle<'_, 'de>, Error> {
self.compound(state).next_value(state)
}
fn value_for_key(
&mut self,
key: &str,
state: &mut State,
) -> Result<Option<SinkHandle<'_, 'de>>, Error> {
self.compound(state).value_for_key(key, state)
}
fn recover(&mut self, err: Error, state: &mut State) -> Result<(), Error> {
match self.compound {
Some(ref mut compound) => compound.get_mut().recover(err, state),
None => Err(err),
}
}
fn finish(&mut self, state: &mut State) -> Result<(), Error> {
let value = match self.compound {
Some(ref mut compound) => {
compound.get_mut().finish(state)?;
compound.take()
}
None => self.slot.take(),
};
let class = self.class.take();
let form = self.form.take();
*self.out = value.map(|value| Object { class, form, value });
Ok(())
}
fn expecting(&self) -> Cow<'_, str> {
if let Some(ref compound) = self.compound {
return compound.get().expecting();
}
T::expecting()
}
}