birkenfeld / serde-pickle

Rust (de)serialization for the Python pickle format.
Apache License 2.0
185 stars 27 forks source link

Error: enums must be represented as dicts or tuples #12

Closed rconan closed 3 years ago

rconan commented 3 years ago

I have the following:

use serde::{Deserialize,Serialize};
use serde_json;
use serde_pickle;
use std::fs::File;

#[derive(Debug, Deserialize, Serialize)]
pub struct Data {
    id: String,
    method: String,
    params: i32,
}
#[derive(Debug, Deserialize, Serialize)]
enum Message {
    Request(Data),
    Response(i32),
}

fn main() {
    let s = r#" {"Request": {"id": "u", "method": "q", "params": 1}} "#;
    let m: Message = serde_json::from_str(s).unwrap();
    println!("{:#?}", m);

    let mut file = File::create("examples/msg.pkl").unwrap();
    serde_pickle::to_writer(&mut file, &m, true).unwrap();

    let file = File::open("examples/msg.pkl").unwrap();
    let d: Message = serde_pickle::from_reader(file).unwrap();
    println!("{:#?}", d);
}

that allows to Serialize and Deserialize enum Message. If I load the pickle file in Python, I got the following representation

('Request', {'id': 'u', 'method': 'q', 'params': 1})

now if I pickle the tuple in Python with:

msg = ('Request', {'id': 'u', 'method': 'q', 'params': 1}) 
with open("pymsg.pkl","wb") as f: 
    pickle.dump(msg,f) 

and then Deserialize in Rust with

    let file = File::open("examples/pymsg.pkl").unwrap();
    let d: Message = serde_pickle::from_reader(file).unwrap();
    println!("{:#?}", d);

I got the following error:

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Syntax(Structure("enums must be represented as dicts or tuples"))', examples/test_enum.rs:27:54
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Is it possible to Deserialize to a Rust enum from a Python pickled file?

rconan commented 3 years ago

I found out that if I Deserialize in 2 steps

    let v: serde_pickle::Value = serde_pickle::from_reader(file).unwrap();
    let d: Message = serde_pickle::from_value(v).unwrap();
    println!("{:#?}", d);

there are no errors

birkenfeld commented 3 years ago

Thanks for the report! I could reproduce the bug and found that the cause is a MemoRef in the pickle. I'll need to resolve that...

birkenfeld commented 3 years ago

This should be fixed now. I'll release a bugfix version shortly.