Bincode deserialization UnexpectedEof

Hi, I'm quite new to rust so I may be doing some very stupid thing or using it in the wrong way.

I want to have a struct with its impl that can take a generic T that implements Serialize and Deserialize from serde.

I will use this to then being able sent this T to the network after serialization using bincode.

Everything seems fine but when I try to deserialize something that was serialized I get an UnexpectedEof error without any information.

Here the code:
lib.rs


#![feature(let_chains)]

extern crate bincode;
extern crate serde;
use thiserror::Error;
use std::fmt;

#[derive(Error, Debug)]
pub enum ZCError {
    ZConnectorError,
    TransitionNotAllowed,
    UnknownError(String),
}

impl fmt::Display for ZCError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ZCError::ZConnectorError => write!(f, "Connection Error"),
            ZCError::TransitionNotAllowed => write!(f, "Transition Not allowed"),
            ZCError::UnknownError(err) => write!(f, "Error {}", err)
        }
     }
}

pub type ZCResult<T> = Result<T, ZCError>;

//create a struct with a generic T that implements Serialize, Deserialize, Clone
pub struct InternalComponent<T> {
    state : Option<T>,
    raw_state : Vec<u8>,
}

impl<T> InternalComponent<T>
    where
    T : serde::Serialize+serde::de::DeserializeOwned+Clone {
    pub fn new() -> ZCResult<InternalComponent<T>> {

        let mut int = InternalComponent {
            state : None,
            raw_state : Vec::new(),
        };
        Ok(int)
    }

    pub fn put_state(&mut self, state : T) -> ZCResult<()> {
        self.state = Some(state);
        self.raw_state = bincode::serialize(&self.state).unwrap();
        println!("W: raw_state: {:?}", self.raw_state);
        Ok(())
    }

    pub fn get_state(&mut self) -> ZCResult<Option<T>> {
        println!("R: raw_state: {:?}", &self.raw_state);
        match self.raw_state.len() {
            0 => Ok(self.state.clone()),
            _ => {
                let res = bincode::deserialize(&self.raw_state);
                match res {
                    Err(why) => Err(ZCError::UnknownError(format!("Err {:?}", why))),
                    Ok(s) => {
                        self.state = Some(s);
                        Ok(self.state.clone())
                    },
                }
            },
        }
    }
}

main.rs

extern crate serde;
use serde::{Serialize, Deserialize};



#[derive(Serialize,Deserialize,Debug, Clone)]
pub struct MyState {
    pub one : String,
    pub two : u64,
    pub three : f64,
}

fn main() {

    let m_state = MyState {
        one : String::from("This is a string"),
        two : 123_000_000_456,
        three : 123.456
    };

    let mut myself = fos::InternalComponent::<MyState>::new().unwrap();

    myself.put_state(m_state.clone()).unwrap();

    println!("State: {:?}", myself.get_state().unwrap());
}

It seems quite simple but this is the output I get:

./target/debug/fos
W: raw_state: [1, 16, 0, 0, 0, 0, 0, 0, 0, 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 115, 116, 114, 105, 110, 103, 200, 15, 95, 163, 28, 0, 0, 0, 119, 190, 159, 26, 47, 221, 94, 64]
R: raw_state: [1, 16, 0, 0, 0, 0, 0, 0, 0, 84, 104, 105, 115, 32, 105, 115, 32, 97, 32, 115, 116, 114, 105, 110, 103, 200, 15, 95, 163, 28, 0, 0, 0, 119, 190, 159, 26, 47, 221, 94, 64]
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: UnknownError("Err Io(Custom { kind: UnexpectedEof, error: \"\" })")', src/main.rs:25:48
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Any suggestion?

It looks like you're serializing an Option<T> but deserializing a T. You should fix it so that serialize and deserialize are called with the same type. One way to fix it is to change self.state = Some(s); to self.state = s;. It would be helpful to specify the type explicitly, e.g. bincode::deserialize::<Option<T>>(...).

Note: InternalComponent looks somewhat strange. I'm not sure why you would need to put both the original object and its serialized data into the same struct. Usually the serialization should be visible in the types, e.g. some parts of your code work with T, then you serialize it and do something with Vec<u8> (e.g. send it over the network). But InternalComponent hides that distinction and makes it unclear which representation you are dealing with.

Indeed I was messing with the types, thanks.

Regarding the InternalComponet it is going to change. I had to keep both because I was not able to deal with lifetime when deserializing, because the Vec<u8> from where I was reading the T had a different lifetime.

Thanks again.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.