Created
March 17, 2015 17:18
-
-
Save borntyping/ae4b2436b668ebc8e774 to your computer and use it in GitHub Desktop.
rust-protobuf failing to encode messages with numbers set
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[root] | |
name = "rust-protobuf-repro" | |
version = "0.0.1" | |
dependencies = [ | |
"protobuf 0.0.9 (git+https://github.com/stepancheg/rust-protobuf.git)", | |
] | |
[[package]] | |
name = "protobuf" | |
version = "0.0.9" | |
source = "git+https://github.com/stepancheg/rust-protobuf.git#1578f31740418e6844dbea3ac2bbef135f648a01" | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "rust-protobuf-repro" | |
version = "0.0.1" | |
[dependencies.protobuf] | |
git = "https://github.com/stepancheg/rust-protobuf.git" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Compiling rust-protobuf-repro v0.0.1 (file:///home/sam/Development/borntyping-sandbox/rust-protobuf-repro) | |
Running target/debug/rust-protobuf-repro-daf18ce99eb33b9f | |
running 1 test | |
test test_message_write ... FAILED | |
failures: | |
---- test_message_write stdout ---- | |
thread 'test_message_write' panicked at 'Result A {str: "hello world"} -> [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100] was the same as result B {num_int64: 64 str: "hello world"} -> [104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]', src/main.rs:72 | |
failures: | |
test_message_write | |
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured | |
thread '<main>' panicked at 'Some tests failed', /home/rustbuild/src/rust-buildbot/slave/nightly-dist-rustc-linux/build/src/libtest/lib.rs:262 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
message Example { | |
optional int64 num_int64 = 1; | |
optional sint64 num_sint64 = 2; | |
optional double num_double = 3; | |
optional float num_float = 4; | |
optional string str = 5; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This file is generated. Do not edit | |
#![allow(dead_code)] | |
#![allow(non_camel_case_types)] | |
#![allow(non_upper_case_globals)] | |
#![allow(unused_imports)] | |
use protobuf::Message as Message_imported_for_functions; | |
use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions; | |
#[derive(Clone,Default)] | |
pub struct Example { | |
// message fields | |
num_int64: ::std::option::Option<i64>, | |
num_sint64: ::std::option::Option<i64>, | |
num_double: ::std::option::Option<f64>, | |
num_float: ::std::option::Option<f32>, | |
str: ::protobuf::SingularField<::std::string::String>, | |
// special fields | |
unknown_fields: ::protobuf::UnknownFields, | |
cached_size: ::std::cell::Cell<u32>, | |
} | |
impl Example { | |
pub fn new() -> Example { | |
::std::default::Default::default() | |
} | |
pub fn default_instance() -> &'static Example { | |
static mut instance: ::protobuf::lazy::Lazy<Example> = ::protobuf::lazy::Lazy { | |
lock: ::protobuf::lazy::ONCE_INIT, | |
ptr: 0 as *const Example, | |
}; | |
unsafe { | |
instance.get(|| { | |
Example { | |
num_int64: ::std::option::Option::None, | |
num_sint64: ::std::option::Option::None, | |
num_double: ::std::option::Option::None, | |
num_float: ::std::option::Option::None, | |
str: ::protobuf::SingularField::none(), | |
unknown_fields: ::protobuf::UnknownFields::new(), | |
cached_size: ::std::cell::Cell::new(0), | |
} | |
}) | |
} | |
} | |
// optional int64 num_int64 = 1; | |
pub fn clear_num_int64(&mut self) { | |
self.num_int64 = ::std::option::Option::None; | |
} | |
pub fn has_num_int64(&self) -> bool { | |
self.num_int64.is_some() | |
} | |
// Param is passed by value, moved | |
pub fn set_num_int64(&mut self, v: i64) { | |
self.num_int64 = ::std::option::Option::Some(v); | |
} | |
pub fn get_num_int64<'a>(&self) -> i64 { | |
self.num_int64.unwrap_or(0) | |
} | |
// optional sint64 num_sint64 = 2; | |
pub fn clear_num_sint64(&mut self) { | |
self.num_sint64 = ::std::option::Option::None; | |
} | |
pub fn has_num_sint64(&self) -> bool { | |
self.num_sint64.is_some() | |
} | |
// Param is passed by value, moved | |
pub fn set_num_sint64(&mut self, v: i64) { | |
self.num_sint64 = ::std::option::Option::Some(v); | |
} | |
pub fn get_num_sint64<'a>(&self) -> i64 { | |
self.num_sint64.unwrap_or(0) | |
} | |
// optional double num_double = 3; | |
pub fn clear_num_double(&mut self) { | |
self.num_double = ::std::option::Option::None; | |
} | |
pub fn has_num_double(&self) -> bool { | |
self.num_double.is_some() | |
} | |
// Param is passed by value, moved | |
pub fn set_num_double(&mut self, v: f64) { | |
self.num_double = ::std::option::Option::Some(v); | |
} | |
pub fn get_num_double<'a>(&self) -> f64 { | |
self.num_double.unwrap_or(0.) | |
} | |
// optional float num_float = 4; | |
pub fn clear_num_float(&mut self) { | |
self.num_float = ::std::option::Option::None; | |
} | |
pub fn has_num_float(&self) -> bool { | |
self.num_float.is_some() | |
} | |
// Param is passed by value, moved | |
pub fn set_num_float(&mut self, v: f32) { | |
self.num_float = ::std::option::Option::Some(v); | |
} | |
pub fn get_num_float<'a>(&self) -> f32 { | |
self.num_float.unwrap_or(0.) | |
} | |
// optional string str = 5; | |
pub fn clear_str(&mut self) { | |
self.str.clear(); | |
} | |
pub fn has_str(&self) -> bool { | |
self.str.is_some() | |
} | |
// Param is passed by value, moved | |
pub fn set_str(&mut self, v: ::std::string::String) { | |
self.str = ::protobuf::SingularField::some(v); | |
} | |
// Mutable pointer to the field. | |
// If field is not initialized, it is initialized with default value first. | |
pub fn mut_str<'a>(&'a mut self) -> &'a mut ::std::string::String { | |
if self.str.is_none() { | |
self.str.set_default(); | |
}; | |
self.str.as_mut().unwrap() | |
} | |
// Take field | |
pub fn take_str(&mut self) -> ::std::string::String { | |
self.str.take().unwrap_or_else(|| ::std::string::String::new()) | |
} | |
pub fn get_str<'a>(&'a self) -> &'a str { | |
match self.str.as_ref() { | |
Some(v) => v.as_slice(), | |
None => "", | |
} | |
} | |
} | |
impl ::protobuf::Message for Example { | |
fn is_initialized(&self) -> bool { | |
true | |
} | |
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> { | |
while !try!(is.eof()) { | |
let (field_number, wire_type) = try!(is.read_tag_unpack()); | |
match field_number { | |
1 => { | |
if wire_type != ::protobuf::wire_format::WireTypeVarint { | |
return ::std::result::Result::Err(::protobuf::ProtobufError::WireError("unexpected wire type".to_string())); | |
}; | |
let tmp = try!(is.read_int64()); | |
self.num_int64 = ::std::option::Option::Some(tmp); | |
}, | |
2 => { | |
if wire_type != ::protobuf::wire_format::WireTypeVarint { | |
return ::std::result::Result::Err(::protobuf::ProtobufError::WireError("unexpected wire type".to_string())); | |
}; | |
let tmp = try!(is.read_sint64()); | |
self.num_sint64 = ::std::option::Option::Some(tmp); | |
}, | |
3 => { | |
if wire_type != ::protobuf::wire_format::WireTypeFixed64 { | |
return ::std::result::Result::Err(::protobuf::ProtobufError::WireError("unexpected wire type".to_string())); | |
}; | |
let tmp = try!(is.read_double()); | |
self.num_double = ::std::option::Option::Some(tmp); | |
}, | |
4 => { | |
if wire_type != ::protobuf::wire_format::WireTypeFixed32 { | |
return ::std::result::Result::Err(::protobuf::ProtobufError::WireError("unexpected wire type".to_string())); | |
}; | |
let tmp = try!(is.read_float()); | |
self.num_float = ::std::option::Option::Some(tmp); | |
}, | |
5 => { | |
if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited { | |
return ::std::result::Result::Err(::protobuf::ProtobufError::WireError("unexpected wire type".to_string())); | |
}; | |
let tmp = self.str.set_default(); | |
try!(is.read_string_into(tmp)) | |
}, | |
_ => { | |
let unknown = try!(is.read_unknown(wire_type)); | |
self.mut_unknown_fields().add_value(field_number, unknown); | |
}, | |
}; | |
} | |
::std::result::Result::Ok(()) | |
} | |
// Compute sizes of nested messages | |
fn compute_size(&self) -> u32 { | |
let mut my_size = 0; | |
for value in self.num_int64.iter() { | |
my_size += ::protobuf::rt::value_size(1, *value, ::protobuf::wire_format::WireTypeVarint); | |
}; | |
for value in self.num_sint64.iter() { | |
my_size += ::protobuf::rt::value_size(2, *value, ::protobuf::wire_format::WireTypeVarint); | |
}; | |
if self.num_double.is_some() { | |
my_size += 9; | |
}; | |
if self.num_float.is_some() { | |
my_size += 5; | |
}; | |
for value in self.str.iter() { | |
my_size += ::protobuf::rt::string_size(5, value.as_slice()); | |
}; | |
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); | |
self.cached_size.set(my_size); | |
my_size | |
} | |
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> { | |
if let Some(v) = self.num_int64 { | |
try!(os.write_int64(1, v)); | |
}; | |
if let Some(v) = self.num_sint64 { | |
try!(os.write_sint64(2, v)); | |
}; | |
if let Some(v) = self.num_double { | |
try!(os.write_double(3, v)); | |
}; | |
if let Some(v) = self.num_float { | |
try!(os.write_float(4, v)); | |
}; | |
if let Some(v) = self.str.as_ref() { | |
try!(os.write_string(5, v.as_slice())); | |
}; | |
try!(os.write_unknown_fields(self.get_unknown_fields())); | |
::std::result::Result::Ok(()) | |
} | |
fn get_cached_size(&self) -> u32 { | |
self.cached_size.get() | |
} | |
fn get_unknown_fields<'s>(&'s self) -> &'s ::protobuf::UnknownFields { | |
&self.unknown_fields | |
} | |
fn mut_unknown_fields<'s>(&'s mut self) -> &'s mut ::protobuf::UnknownFields { | |
&mut self.unknown_fields | |
} | |
fn type_id(&self) -> ::std::any::TypeId { | |
::std::any::TypeId::of::<Example>() | |
} | |
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { | |
::protobuf::MessageStatic::descriptor_static(None::<Self>) | |
} | |
} | |
impl ::protobuf::MessageStatic for Example { | |
fn new() -> Example { | |
Example::new() | |
} | |
#[allow(unused_unsafe,unused_mut)] | |
fn descriptor_static(_: ::std::option::Option<Example>) -> &'static ::protobuf::reflect::MessageDescriptor { | |
static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { | |
lock: ::protobuf::lazy::ONCE_INIT, | |
ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, | |
}; | |
unsafe { | |
descriptor.get(|| { | |
let mut fields = ::std::vec::Vec::new(); | |
fields.push(::protobuf::reflect::accessor::make_singular_i64_accessor( | |
"num_int64", | |
Example::has_num_int64, | |
Example::get_num_int64, | |
)); | |
fields.push(::protobuf::reflect::accessor::make_singular_i64_accessor( | |
"num_sint64", | |
Example::has_num_sint64, | |
Example::get_num_sint64, | |
)); | |
fields.push(::protobuf::reflect::accessor::make_singular_f64_accessor( | |
"num_double", | |
Example::has_num_double, | |
Example::get_num_double, | |
)); | |
fields.push(::protobuf::reflect::accessor::make_singular_f32_accessor( | |
"num_float", | |
Example::has_num_float, | |
Example::get_num_float, | |
)); | |
fields.push(::protobuf::reflect::accessor::make_singular_string_accessor( | |
"str", | |
Example::has_str, | |
Example::get_str, | |
)); | |
::protobuf::reflect::MessageDescriptor::new::<Example>( | |
"Example", | |
fields, | |
file_descriptor_proto() | |
) | |
}) | |
} | |
} | |
} | |
impl ::protobuf::Clear for Example { | |
fn clear(&mut self) { | |
self.clear_num_int64(); | |
self.clear_num_sint64(); | |
self.clear_num_double(); | |
self.clear_num_float(); | |
self.clear_str(); | |
self.unknown_fields.clear(); | |
} | |
} | |
impl ::std::cmp::PartialEq for Example { | |
fn eq(&self, other: &Example) -> bool { | |
self.num_int64 == other.num_int64 && | |
self.num_sint64 == other.num_sint64 && | |
self.num_double == other.num_double && | |
self.num_float == other.num_float && | |
self.str == other.str && | |
self.unknown_fields == other.unknown_fields | |
} | |
} | |
impl ::std::fmt::Debug for Example { | |
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { | |
::protobuf::text_format::fmt(self, f) | |
} | |
} | |
static file_descriptor_proto_data: &'static [u8] = &[ | |
0x0a, 0x11, 0x73, 0x72, 0x63, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, 0x72, | |
0x6f, 0x74, 0x6f, 0x22, 0x64, 0x0a, 0x07, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x12, 0x11, | |
0x0a, 0x09, 0x6e, 0x75, 0x6d, 0x5f, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, 0x01, 0x20, 0x01, 0x28, | |
0x03, 0x12, 0x12, 0x0a, 0x0a, 0x6e, 0x75, 0x6d, 0x5f, 0x73, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x18, | |
0x02, 0x20, 0x01, 0x28, 0x12, 0x12, 0x12, 0x0a, 0x0a, 0x6e, 0x75, 0x6d, 0x5f, 0x64, 0x6f, 0x75, | |
0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x12, 0x11, 0x0a, 0x09, 0x6e, 0x75, 0x6d, | |
0x5f, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x02, 0x12, 0x0b, 0x0a, 0x03, | |
0x73, 0x74, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x4a, 0xf9, 0x02, 0x0a, 0x06, 0x12, 0x04, | |
0x00, 0x00, 0x06, 0x01, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x00, 0x00, 0x06, 0x01, | |
0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x00, 0x08, 0x0f, 0x0a, 0x0b, 0x0a, 0x04, | |
0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x01, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, | |
0x00, 0x04, 0x12, 0x03, 0x01, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x05, | |
0x12, 0x03, 0x01, 0x0b, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, | |
0x01, 0x12, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x01, 0x1e, | |
0x1f, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x02, 0x02, 0x21, 0x0a, 0x0c, | |
0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x04, 0x12, 0x03, 0x02, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, | |
0x04, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x02, 0x0b, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, | |
0x02, 0x01, 0x01, 0x12, 0x03, 0x02, 0x12, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, | |
0x03, 0x12, 0x03, 0x02, 0x1f, 0x20, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, | |
0x03, 0x02, 0x21, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x04, 0x12, 0x03, 0x03, 0x02, | |
0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x03, 0x0b, 0x11, 0x0a, | |
0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x03, 0x12, 0x1c, 0x0a, 0x0c, 0x0a, | |
0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x03, 0x1f, 0x20, 0x0a, 0x0b, 0x0a, 0x04, 0x04, | |
0x00, 0x02, 0x03, 0x12, 0x03, 0x04, 0x02, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, | |
0x04, 0x12, 0x03, 0x04, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x05, 0x12, | |
0x03, 0x04, 0x0b, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x01, 0x12, 0x03, 0x04, | |
0x12, 0x1b, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x03, 0x03, 0x12, 0x03, 0x04, 0x1e, 0x1f, | |
0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x04, 0x12, 0x03, 0x05, 0x02, 0x1a, 0x0a, 0x0c, 0x0a, | |
0x05, 0x04, 0x00, 0x02, 0x04, 0x04, 0x12, 0x03, 0x05, 0x02, 0x0a, 0x0a, 0x0c, 0x0a, 0x05, 0x04, | |
0x00, 0x02, 0x04, 0x05, 0x12, 0x03, 0x05, 0x0b, 0x11, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, | |
0x04, 0x01, 0x12, 0x03, 0x05, 0x12, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x04, 0x03, | |
0x12, 0x03, 0x05, 0x18, 0x19, | |
]; | |
static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy { | |
lock: ::protobuf::lazy::ONCE_INIT, | |
ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto, | |
}; | |
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto { | |
::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap() | |
} | |
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { | |
unsafe { | |
file_descriptor_proto_lazy.get(|| { | |
parse_descriptor_proto() | |
}) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(core)] | |
#![feature(io)] | |
extern crate protobuf; | |
use std::io::Write; | |
use std::slice::SliceExt; | |
use protobuf::Message; | |
mod example; | |
struct FakeWriter { | |
vec: Vec<u8> | |
} | |
impl FakeWriter { | |
fn new() -> Self { | |
FakeWriter { vec: Vec::new() } | |
} | |
} | |
impl std::io::Write for FakeWriter { | |
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { | |
self.vec = buf.to_vec(); | |
Ok(buf.len()) | |
} | |
fn flush(&mut self) -> std::io::Result<()> { | |
Ok(()) | |
} | |
} | |
#[test] | |
fn test_message_write() { | |
let mut a = example::Example::new(); | |
a.set_str("hello world".to_string()); | |
let mut b = example::Example::new(); | |
b.set_num_int64(64); | |
// b.set_num_sint64(64); | |
// b.set_num_float(64.0); | |
// b.set_num_double(64); | |
b.set_str("hello world".to_string()); | |
let result_a = { | |
let mut stream = FakeWriter::new(); | |
{ | |
let mut output_stream = protobuf::CodedOutputStream::new(&mut stream); | |
a.compute_size(); | |
a.write_to_with_cached_sizes(&mut output_stream).unwrap(); | |
output_stream.flush().unwrap(); | |
} | |
stream.vec | |
}; | |
let result_b = { | |
let mut stream = FakeWriter::new(); | |
{ | |
let mut output_stream = protobuf::CodedOutputStream::new(&mut stream); | |
b.compute_size(); | |
b.write_to_with_cached_sizes(&mut output_stream).unwrap(); | |
output_stream.flush().unwrap(); | |
} | |
stream.vec | |
}; | |
assert!(result_a != result_b, | |
"Result A {{{:?}}} -> {:?} was the same as result B {{{:?}}} -> {:?}", | |
a, result_a, b, result_b); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment