extern crate quick_protobuf;
use quick_protobuf::sizeofs::*;
use quick_protobuf::{deserialize_from_slice, serialize_into_slice, serialize_into_vec};
use quick_protobuf::{
BytesReader, MessageRead, MessageWrite, Reader, Result, Writer, WriterBackend,
};
use std::borrow::Cow;
use std::collections::HashMap;
macro_rules! write_read_primitive {
($name:ident, $read:ident, $write:ident) => {
write_read_primitive!($name, $read, $write, 145);
};
($name:ident, $read:ident, $write:ident, $def:expr) => {
#[test]
fn $name() {
let v = $def;
let mut buf = Vec::new();
{
let mut w = Writer::new(&mut buf);
w.$write(v).unwrap();
}
let mut r = BytesReader::from_bytes(&*buf);
assert_eq!(v, r.$read(&buf).unwrap());
}
};
}
write_read_primitive!(wr_u8, read_u8, write_u8);
write_read_primitive!(wr_int32, read_int32, write_int32);
write_read_primitive!(wr_int64, read_int64, write_int64);
write_read_primitive!(wr_uint32, read_uint32, write_uint32);
write_read_primitive!(wr_uint64, read_uint64, write_uint64);
write_read_primitive!(wr_sint32, read_sint32, write_sint32);
write_read_primitive!(wr_sint64, read_sint64, write_sint64);
write_read_primitive!(wr_bool, read_bool, write_bool, true);
write_read_primitive!(wr_fixed32, read_fixed32, write_fixed32);
write_read_primitive!(wr_fixed64, read_fixed64, write_fixed64);
write_read_primitive!(wr_sfixed32, read_sfixed32, write_sfixed32);
write_read_primitive!(wr_sfixed64, read_sfixed64, write_sfixed64);
write_read_primitive!(wr_float, read_float, write_float, 5.8);
write_read_primitive!(wr_double, read_double, write_double, 5.8);
#[test]
fn wr_bytes() {
let v = b"test_write_read";
let mut buf = Vec::new();
{
let mut w = Writer::new(&mut buf);
w.write_bytes(v).unwrap();
}
let mut r = BytesReader::from_bytes(&*buf);
assert_eq!(v, r.read_bytes(&buf).unwrap());
}
#[test]
fn wr_string() {
let v = "test_write_read";
let mut buf = Vec::new();
{
let mut w = Writer::new(&mut buf);
w.write_string(v).unwrap();
}
let mut r = BytesReader::from_bytes(&buf);
assert_eq!(v, r.read_string(&buf).unwrap());
}
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
enum TestEnum {
A = 0,
B = 1,
C = 2,
}
impl From<i32> for TestEnum {
fn from(v: i32) -> TestEnum {
match v {
0 => TestEnum::A,
1 => TestEnum::B,
2 => TestEnum::C,
_ => unreachable!(),
}
}
}
#[test]
fn wr_enum() {
let v = TestEnum::C;
let mut buf = Vec::new();
{
let mut w = Writer::new(&mut buf);
w.write_enum(v as i32).unwrap();
}
let mut r = BytesReader::from_bytes(&buf);
assert_eq!(v, r.read_enum(&buf).unwrap());
}
#[derive(PartialEq, Eq, Debug, Clone, Default)]
struct TestMessage {
id: Option<u32>,
val: Vec<i64>,
}
impl<'a> MessageRead<'a> for TestMessage {
fn from_reader(r: &mut BytesReader, bytes: &[u8]) -> Result<TestMessage> {
let mut msg = TestMessage::default();
while !r.is_eof() {
match r.next_tag(bytes) {
Ok(10) => msg.id = Some(r.read_uint32(bytes)?),
Ok(18) => msg.val.push(r.read_sint64(bytes)?),
Ok(t) => {
r.read_unknown(bytes, t)?;
}
Err(e) => return Err(e),
}
}
Ok(msg)
}
}
impl MessageWrite for TestMessage {
fn get_size(&self) -> usize {
self.id.as_ref().map_or(0, |m| 1 + sizeof_uint32(*m))
+ self
.val
.iter()
.map(|m| 1 + sizeof_sint64(*m))
.sum::<usize>()
}
fn write_message<W: WriterBackend>(&self, r: &mut Writer<W>) -> Result<()> {
if let Some(ref s) = self.id {
r.write_with_tag(10, |r| r.write_uint32(*s))?;
}
for s in &self.val {
r.write_with_tag(18, |r| r.write_sint64(*s))?;
}
Ok(())
}
}
#[test]
fn wr_message() {
let v = TestMessage {
id: Some(63),
val: vec![53, 5, 76, 743, 23, 753],
};
let buf = serialize_into_vec(&v).unwrap();
assert_eq!(v, deserialize_from_slice(&buf).unwrap());
assert_eq!(buf.len(), sizeof_varint(8) + v.get_size());
}
#[test]
fn wr_message_slice() {
let v = TestMessage {
id: Some(63),
val: vec![53, 5, 76, 743, 23, 753],
};
let mut buf = [0u8; 1024];
serialize_into_slice(&v, &mut buf).unwrap();
assert_eq!(v, deserialize_from_slice(&buf).unwrap());
}
#[derive(PartialEq, Eq, Debug, Clone, Default)]
struct TestMessageBorrow<'a> {
id: Option<u32>,
val: Vec<&'a str>,
}
impl<'a> MessageRead<'a> for TestMessageBorrow<'a> {
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<TestMessageBorrow<'a>> {
let mut msg = TestMessageBorrow::default();
while !r.is_eof() {
match r.next_tag(bytes) {
Ok(10) => msg.id = Some(r.read_uint32(bytes)?),
Ok(18) => msg.val.push(r.read_string(bytes)?),
Ok(t) => {
r.read_unknown(bytes, t)?;
}
Err(e) => return Err(e),
}
println!("{:?}", msg);
}
Ok(msg)
}
}
impl<'a> MessageWrite for TestMessageBorrow<'a> {
fn get_size(&self) -> usize {
self.id.as_ref().map_or(0, |m| 1 + sizeof_uint32(*m))
+ self
.val
.iter()
.map(|m| 1 + sizeof_len(m.len()))
.sum::<usize>()
}
fn write_message<W: WriterBackend>(&self, r: &mut Writer<W>) -> Result<()> {
if let Some(ref s) = self.id {
r.write_with_tag(10, |r| r.write_uint32(*s))?;
}
for s in &self.val {
r.write_with_tag(18, |r| r.write_string(*s))?;
}
Ok(())
}
}
#[test]
fn wr_message_length_prefixed() {
let test = "eajhawbdkjblncljbdskjbclas";
let v = TestMessageBorrow {
id: Some(63),
val: vec![&test[0..2], &test[3..7], &test[7..10]],
};
let buf = serialize_into_vec(&v).unwrap();
assert_eq!(v, deserialize_from_slice(&buf).unwrap());
assert_eq!(buf.len(), sizeof_varint(8) + v.get_size());
}
#[test]
fn wr_message_wo_prefix() {
let test = "eajhawbdkjblncljbdskjbclas";
let v = TestMessageBorrow {
id: Some(63),
val: vec![&test[0..2], &test[3..7], &test[7..10]],
};
let mut buf = Vec::new();
{
let mut writer = Writer::new(&mut buf);
v.write_message(&mut writer).unwrap();
}
let mut r = BytesReader::from_bytes(&buf);
assert_eq!(v, TestMessageBorrow::from_reader(&mut r, &buf).unwrap());
assert_eq!(buf.len(), v.get_size());
}
#[test]
fn wr_message_with_prefix_wrapper() {
let test = "eajhawbdkjblncljbdskjbclas";
let v = TestMessageBorrow {
id: Some(63),
val: vec![&test[0..2], &test[3..7], &test[7..10]],
};
let mut buf = Vec::new();
{
let mut writer = Writer::new(&mut buf);
writer.write_message(&v).unwrap();
}
let mut r = Reader::from_bytes(buf);
assert_eq!(
v,
r.read(|r, b| r.read_message::<TestMessageBorrow>(b))
.unwrap()
);
assert_eq!(r.buffer().len(), sizeof_varint(8) + v.get_size());
}
#[test]
fn wr_message_wo_prefix_wrapper() {
let test = "eajhawbdkjblncljbdskjbclas";
let v = TestMessageBorrow {
id: Some(63),
val: vec![&test[0..2], &test[3..7], &test[7..10]],
};
let mut buf = Vec::new();
{
let mut writer = Writer::new(&mut buf);
v.write_message(&mut writer).unwrap();
}
let mut r = Reader::from_bytes(buf);
assert_eq!(v, r.read(TestMessageBorrow::from_reader).unwrap());
assert_eq!(r.buffer().len(), v.get_size());
}
#[test]
fn wr_packed_uint32() {
let v = vec![43, 54, 64, 234, 6123, 643];
let mut buf = Vec::new();
{
let mut w = Writer::new(&mut buf);
w.write_packed(&v, |r, m| r.write_uint32(*m), &|m| sizeof_uint32(*m))
.unwrap();
}
let mut r = BytesReader::from_bytes(&buf);
assert_eq!(v, r.read_packed(&buf, |r, b| r.read_uint32(b)).unwrap());
}
#[test]
fn wr_packed_float() {
let v = vec![43, 54, 64, 234, 6123, 643];
let mut buf = Vec::new();
{
let mut w = Writer::new(&mut buf);
w.write_packed_fixed(&v).unwrap();
}
let mut r = BytesReader::from_bytes(&buf);
assert_eq!(v, r.read_packed_fixed(&buf).unwrap());
}
#[test]
fn wr_map() {
let v = {
let mut v = HashMap::new();
v.insert(Cow::Borrowed("foo"), 1i32);
v.insert(Cow::Borrowed("bar"), 2);
v
};
let mut buf = Vec::new();
{
let mut w = Writer::new(&mut buf);
for (k, v) in v.iter() {
w.write_map(
2 + sizeof_len(k.len()) + sizeof_varint(*v as u64),
10,
|w| w.write_string(&**k),
16,
|w| w.write_int32(*v),
)
.unwrap();
}
}
let mut r = BytesReader::from_bytes(&buf);
let mut read_back = HashMap::new();
while !r.is_eof() {
let (key, value) = r
.read_map(
&buf,
|r, bytes| r.read_string(bytes).map(Cow::Borrowed),
|r, bytes| r.read_int32(bytes),
)
.unwrap();
read_back.insert(key, value);
}
assert_eq!(v, read_back);
}