nikoss
nikoss

Reputation: 3698

Rust protobuf serialization is all messed up

I am using rust-protobuf version 2.4 I have following code

let mut msg = vec![];
let mut str = protobuf::CodedOutputStream::vec(&mut msg);
let mut rmsg = user_manager::user::user_data::new();
rmsg.set_id("1234".into());
rmsg.set_nick("test".into());
str.write_message(1, &rmsg).unwrap();
str.flush().unwrap();
println!("{:?}", msg);
let test: register_msg = protobuf::parse_from_bytes(&msg[..]).unwrap();
println!("serialized: {:?}\noriginal: {:?}", test, rmsg);

and the relevant proto description is as follows

message user_data{
    string id           = 1; //required
    string nick         = 2;
    string theme        = 3;
    string admin_id     = 4;
    string lang         = 5;
    double credit       = 6; //required
    double bonus_credit = 7; //required
};

and what i get as a result is all messed up output

First of all, why do I need to enter a number if im serializing the entire message? that's a really weird design.

Secondly, the first field as you may see in the proto file is the id but output from serialization shows the protobuf package serialized everything into the nick field which is the second field.

Am I doing something wrong or might this be a bug in the library?

UPDATE 1:

I have changed write_msg to write_to_bytes this is how my code looks now.

let mut rmsg = user_manager::user::user_data::new();
rmsg.set_id("1234".into());
rmsg.set_nick("test".into());
let msg = rmsg.write_to_bytes().unwrap();
println!("{:?}", msg);
println!("{:?}", &msg[..]);
let test: register_msg = protobuf::parse_from_bytes(&msg).unwrap();
println!("serialized: {:?}\noriginal: {:?}", test, rmsg);

and still, the output is all messed up. out

Upvotes: 2

Views: 2097

Answers (2)

mbrubeck
mbrubeck

Reputation: 969

You can use Message::write_to_bytes to serialize a message that can be parsed with parse_from_bytes.

Also, make sure that you are deserializing the same type that you serialized.

Here's an example program that works correctly:

mod protos;
use protobuf::Message;
use protos::user_data::user_data;

fn main() {
    let mut rmsg = user_data::new();
    rmsg.set_id("1234".into());
    rmsg.set_nick("test".into());

    let msg = rmsg.write_to_bytes().unwrap();
    println!("{:?}", msg);

    let test: user_data = protobuf::parse_from_bytes(&msg).unwrap();
    println!("serialized: {:?}\noriginal: {:?}", test, rmsg);
}

Upvotes: 3

jpa
jpa

Reputation: 12176

This line:

str.write_message(1, &rmsg).unwrap();

writes the message rmsg as a submessage with field id 1. So the fields end up one nesting level deeper, as if your .proto was:

message wrappermsg {
    user_data msg = 1;
}

The correct method is:

rmsg.write_to(&mut str);

Upvotes: 1

Related Questions