Skip to content

Commit

Permalink
Introduce WriterBackend trait, eliminating hard dep on std::io
Browse files Browse the repository at this point in the history
This replaces all public uses of the Writer trait with the new WriterBackend,
which defines only the interaction points which are actually used. It also
introduces the BytesWriter struct as a new implementation of WriterBackend that
will work in no_std, along with the serialize_into_slice convenience fn.

This is technically a breaking change, as it will require stubs to be
regenerated.
  • Loading branch information
mullr committed Sep 9, 2019
1 parent 30eb964 commit 8ca9750
Show file tree
Hide file tree
Showing 15 changed files with 397 additions and 134 deletions.
5 changes: 2 additions & 3 deletions pb-rs/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1158,7 +1158,7 @@ impl Message {
fn write_write_message<W: Write>(&self, w: &mut W, desc: &FileDescriptor) -> Result<()> {
writeln!(
w,
" fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {{"
" fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {{"
)?;
for f in self.fields.iter().filter(|f| !f.deprecated) {
f.write_write(w, desc)?;
Expand Down Expand Up @@ -2168,7 +2168,6 @@ impl FileDescriptor {
)?;
return Ok(());
}
writeln!(w, "use std::io::Write;")?;
if self
.messages
.iter()
Expand All @@ -2185,7 +2184,7 @@ impl FileDescriptor {
}
writeln!(
w,
"use quick_protobuf::{{MessageRead, MessageWrite, BytesReader, Writer, Result}};"
"use quick_protobuf::{{MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result}};"
)?;

if self.owned {
Expand Down
154 changes: 113 additions & 41 deletions perftest/src/perftest_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
#![cfg_attr(rustfmt, rustfmt_skip)]


use std::io::Write;
use std::borrow::Cow;
use quick_protobuf::{MessageRead, MessageWrite, BytesReader, Writer, Result};
use std::collections::HashMap;
use quick_protobuf::{MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
use quick_protobuf::sizeofs::*;
use super::*;

Expand Down Expand Up @@ -40,7 +40,7 @@ impl MessageWrite for Test1 {
+ self.value.as_ref().map_or(0, |m| 1 + sizeof_varint(*(m) as u64))
}

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
if let Some(ref s) = self.value { w.write_with_tag(8, |w| w.write_int32(*s))?; }
Ok(())
}
Expand Down Expand Up @@ -71,7 +71,7 @@ impl MessageWrite for TestRepeatedBool {
+ self.values.iter().map(|s| 1 + sizeof_varint(*(s) as u64)).sum::<usize>()
}

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
for s in &self.values { w.write_with_tag(8, |w| w.write_bool(*s))?; }
Ok(())
}
Expand Down Expand Up @@ -102,27 +102,58 @@ impl MessageWrite for TestRepeatedPackedInt32 {
+ if self.values.is_empty() { 0 } else { 1 + sizeof_len(self.values.iter().map(|s| sizeof_varint(*(s) as u64)).sum::<usize>()) }
}

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
w.write_packed_with_tag(10, &self.values, |w, m| w.write_int32(*m), &|m| sizeof_varint(*(m) as u64))?;
Ok(())
}
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestRepeatedPackedFloat<'a> {
pub values: Cow<'a, [f32]>,
}

impl<'a> MessageRead<'a> for TestRepeatedPackedFloat<'a> {
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
let mut msg = Self::default();
while !r.is_eof() {
match r.next_tag(bytes) {
Ok(10) => msg.values = r.read_packed_fixed(bytes)?.into(),
Ok(t) => { r.read_unknown(bytes, t)?; }
Err(e) => return Err(e),
}
}
Ok(msg)
}
}

impl<'a> MessageWrite for TestRepeatedPackedFloat<'a> {
fn get_size(&self) -> usize {
0
+ if self.values.is_empty() { 0 } else { 1 + sizeof_len(self.values.len() * 4) }
}

fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
w.write_packed_fixed_with_tag(10, &self.values)?;
Ok(())
}
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestRepeatedMessages {
pub messages1: Vec<perftest_data::TestRepeatedMessages>,
pub messages2: Vec<perftest_data::TestRepeatedMessages>,
pub messages3: Vec<perftest_data::TestRepeatedMessages>,
pub messages1: Vec<TestRepeatedMessages>,
pub messages2: Vec<TestRepeatedMessages>,
pub messages3: Vec<TestRepeatedMessages>,
}

impl<'a> MessageRead<'a> for TestRepeatedMessages {
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
let mut msg = Self::default();
while !r.is_eof() {
match r.next_tag(bytes) {
Ok(10) => msg.messages1.push(r.read_message::<perftest_data::TestRepeatedMessages>(bytes)?),
Ok(18) => msg.messages2.push(r.read_message::<perftest_data::TestRepeatedMessages>(bytes)?),
Ok(26) => msg.messages3.push(r.read_message::<perftest_data::TestRepeatedMessages>(bytes)?),
Ok(10) => msg.messages1.push(r.read_message::<TestRepeatedMessages>(bytes)?),
Ok(18) => msg.messages2.push(r.read_message::<TestRepeatedMessages>(bytes)?),
Ok(26) => msg.messages3.push(r.read_message::<TestRepeatedMessages>(bytes)?),
Ok(t) => { r.read_unknown(bytes, t)?; }
Err(e) => return Err(e),
}
Expand All @@ -139,7 +170,7 @@ impl MessageWrite for TestRepeatedMessages {
+ self.messages3.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
}

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
for s in &self.messages1 { w.write_with_tag(10, |w| w.write_message(s))?; }
for s in &self.messages2 { w.write_with_tag(18, |w| w.write_message(s))?; }
for s in &self.messages3 { w.write_with_tag(26, |w| w.write_message(s))?; }
Expand All @@ -149,19 +180,19 @@ impl MessageWrite for TestRepeatedMessages {

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestOptionalMessages {
pub message1: Option<Box<perftest_data::TestOptionalMessages>>,
pub message2: Option<Box<perftest_data::TestOptionalMessages>>,
pub message3: Option<Box<perftest_data::TestOptionalMessages>>,
pub message1: Option<Box<TestOptionalMessages>>,
pub message2: Option<Box<TestOptionalMessages>>,
pub message3: Option<Box<TestOptionalMessages>>,
}

impl<'a> MessageRead<'a> for TestOptionalMessages {
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
let mut msg = Self::default();
while !r.is_eof() {
match r.next_tag(bytes) {
Ok(10) => msg.message1 = Some(Box::new(r.read_message::<perftest_data::TestOptionalMessages>(bytes)?)),
Ok(18) => msg.message2 = Some(Box::new(r.read_message::<perftest_data::TestOptionalMessages>(bytes)?)),
Ok(26) => msg.message3 = Some(Box::new(r.read_message::<perftest_data::TestOptionalMessages>(bytes)?)),
Ok(10) => msg.message1 = Some(Box::new(r.read_message::<TestOptionalMessages>(bytes)?)),
Ok(18) => msg.message2 = Some(Box::new(r.read_message::<TestOptionalMessages>(bytes)?)),
Ok(26) => msg.message3 = Some(Box::new(r.read_message::<TestOptionalMessages>(bytes)?)),
Ok(t) => { r.read_unknown(bytes, t)?; }
Err(e) => return Err(e),
}
Expand All @@ -178,7 +209,7 @@ impl MessageWrite for TestOptionalMessages {
+ self.message3.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
}

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
if let Some(ref s) = self.message1 { w.write_with_tag(10, |w| w.write_message(&**s))?; }
if let Some(ref s) = self.message2 { w.write_with_tag(18, |w| w.write_message(&**s))?; }
if let Some(ref s) = self.message3 { w.write_with_tag(26, |w| w.write_message(&**s))?; }
Expand Down Expand Up @@ -217,7 +248,7 @@ impl<'a> MessageWrite for TestStrings<'a> {
+ self.s3.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
}

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
if let Some(ref s) = self.s1 { w.write_with_tag(10, |w| w.write_string(&**s))?; }
if let Some(ref s) = self.s2 { w.write_with_tag(18, |w| w.write_string(&**s))?; }
if let Some(ref s) = self.s3 { w.write_with_tag(26, |w| w.write_string(&**s))?; }
Expand Down Expand Up @@ -250,37 +281,75 @@ impl<'a> MessageWrite for TestBytes<'a> {
+ self.b1.as_ref().map_or(0, |m| 1 + sizeof_len((m).len()))
}

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
if let Some(ref s) = self.b1 { w.write_with_tag(10, |w| w.write_bytes(&**s))?; }
Ok(())
}
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct TestMap<'a> {
pub value: HashMap<Cow<'a, str>, u32>,
}

impl<'a> MessageRead<'a> for TestMap<'a> {
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
let mut msg = Self::default();
while !r.is_eof() {
match r.next_tag(bytes) {
Ok(10) => {
let (key, value) = r.read_map(bytes, |r, bytes| Ok(r.read_string(bytes).map(Cow::Borrowed)?), |r, bytes| Ok(r.read_uint32(bytes)?))?;
msg.value.insert(key, value);
}
Ok(t) => { r.read_unknown(bytes, t)?; }
Err(e) => return Err(e),
}
}
Ok(msg)
}
}

impl<'a> MessageWrite for TestMap<'a> {
fn get_size(&self) -> usize {
0
+ self.value.iter().map(|(k, v)| 1 + sizeof_len(2 + sizeof_len((k).len()) + sizeof_varint(*(v) as u64))).sum::<usize>()
}

fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
for (k, v) in self.value.iter() { w.write_with_tag(10, |w| w.write_map(2 + sizeof_len((k).len()) + sizeof_varint(*(v) as u64), 10, |w| w.write_string(&**k), 16, |w| w.write_uint32(*v)))?; }
Ok(())
}
}

#[derive(Debug, Default, PartialEq, Clone)]
pub struct PerftestData<'a> {
pub test1: Vec<perftest_data::Test1>,
pub test_repeated_bool: Vec<perftest_data::TestRepeatedBool>,
pub test_repeated_messages: Vec<perftest_data::TestRepeatedMessages>,
pub test_optional_messages: Vec<perftest_data::TestOptionalMessages>,
pub test_strings: Vec<perftest_data::TestStrings<'a>>,
pub test_repeated_packed_int32: Vec<perftest_data::TestRepeatedPackedInt32>,
pub test_small_bytearrays: Vec<perftest_data::TestBytes<'a>>,
pub test_large_bytearrays: Vec<perftest_data::TestBytes<'a>>,
pub test1: Vec<Test1>,
pub test_repeated_bool: Vec<TestRepeatedBool>,
pub test_repeated_messages: Vec<TestRepeatedMessages>,
pub test_optional_messages: Vec<TestOptionalMessages>,
pub test_strings: Vec<TestStrings<'a>>,
pub test_repeated_packed_int32: Vec<TestRepeatedPackedInt32>,
pub test_repeated_packed_float: Vec<TestRepeatedPackedFloat<'a>>,
pub test_small_bytearrays: Vec<TestBytes<'a>>,
pub test_large_bytearrays: Vec<TestBytes<'a>>,
pub test_map: Vec<TestMap<'a>>,
}

impl<'a> MessageRead<'a> for PerftestData<'a> {
fn from_reader(r: &mut BytesReader, bytes: &'a [u8]) -> Result<Self> {
let mut msg = Self::default();
while !r.is_eof() {
match r.next_tag(bytes) {
Ok(10) => msg.test1.push(r.read_message::<perftest_data::Test1>(bytes)?),
Ok(18) => msg.test_repeated_bool.push(r.read_message::<perftest_data::TestRepeatedBool>(bytes)?),
Ok(26) => msg.test_repeated_messages.push(r.read_message::<perftest_data::TestRepeatedMessages>(bytes)?),
Ok(34) => msg.test_optional_messages.push(r.read_message::<perftest_data::TestOptionalMessages>(bytes)?),
Ok(42) => msg.test_strings.push(r.read_message::<perftest_data::TestStrings>(bytes)?),
Ok(50) => msg.test_repeated_packed_int32.push(r.read_message::<perftest_data::TestRepeatedPackedInt32>(bytes)?),
Ok(58) => msg.test_small_bytearrays.push(r.read_message::<perftest_data::TestBytes>(bytes)?),
Ok(66) => msg.test_large_bytearrays.push(r.read_message::<perftest_data::TestBytes>(bytes)?),
Ok(10) => msg.test1.push(r.read_message::<Test1>(bytes)?),
Ok(18) => msg.test_repeated_bool.push(r.read_message::<TestRepeatedBool>(bytes)?),
Ok(26) => msg.test_repeated_messages.push(r.read_message::<TestRepeatedMessages>(bytes)?),
Ok(34) => msg.test_optional_messages.push(r.read_message::<TestOptionalMessages>(bytes)?),
Ok(42) => msg.test_strings.push(r.read_message::<TestStrings>(bytes)?),
Ok(50) => msg.test_repeated_packed_int32.push(r.read_message::<TestRepeatedPackedInt32>(bytes)?),
Ok(58) => msg.test_repeated_packed_float.push(r.read_message::<TestRepeatedPackedFloat>(bytes)?),
Ok(66) => msg.test_small_bytearrays.push(r.read_message::<TestBytes>(bytes)?),
Ok(74) => msg.test_large_bytearrays.push(r.read_message::<TestBytes>(bytes)?),
Ok(82) => msg.test_map.push(r.read_message::<TestMap>(bytes)?),
Ok(t) => { r.read_unknown(bytes, t)?; }
Err(e) => return Err(e),
}
Expand All @@ -298,21 +367,24 @@ impl<'a> MessageWrite for PerftestData<'a> {
+ self.test_optional_messages.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
+ self.test_strings.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
+ self.test_repeated_packed_int32.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
+ self.test_repeated_packed_float.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
+ self.test_small_bytearrays.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
+ self.test_large_bytearrays.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
+ self.test_map.iter().map(|s| 1 + sizeof_len((s).get_size())).sum::<usize>()
}

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
for s in &self.test1 { w.write_with_tag(10, |w| w.write_message(s))?; }
for s in &self.test_repeated_bool { w.write_with_tag(18, |w| w.write_message(s))?; }
for s in &self.test_repeated_messages { w.write_with_tag(26, |w| w.write_message(s))?; }
for s in &self.test_optional_messages { w.write_with_tag(34, |w| w.write_message(s))?; }
for s in &self.test_strings { w.write_with_tag(42, |w| w.write_message(s))?; }
for s in &self.test_repeated_packed_int32 { w.write_with_tag(50, |w| w.write_message(s))?; }
for s in &self.test_small_bytearrays { w.write_with_tag(58, |w| w.write_message(s))?; }
for s in &self.test_large_bytearrays { w.write_with_tag(66, |w| w.write_message(s))?; }
for s in &self.test_repeated_packed_float { w.write_with_tag(58, |w| w.write_message(s))?; }
for s in &self.test_small_bytearrays { w.write_with_tag(66, |w| w.write_message(s))?; }
for s in &self.test_large_bytearrays { w.write_with_tag(74, |w| w.write_message(s))?; }
for s in &self.test_map { w.write_with_tag(82, |w| w.write_message(s))?; }
Ok(())
}
}


5 changes: 2 additions & 3 deletions quick-protobuf/examples/pb_rs/a/b.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
#![cfg_attr(rustfmt, rustfmt_skip)]


use std::io::Write;
use quick_protobuf::{MessageRead, MessageWrite, BytesReader, Writer, Result};
use quick_protobuf::{MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
use quick_protobuf::sizeofs::*;
use super::super::*;

Expand Down Expand Up @@ -39,7 +38,7 @@ impl MessageWrite for ImportedMessage {
+ self.i.as_ref().map_or(0, |m| 1 + sizeof_varint(*(m) as u64))
}

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
if let Some(ref s) = self.i { w.write_with_tag(8, |w| w.write_bool(*s))?; }
Ok(())
}
Expand Down
13 changes: 6 additions & 7 deletions quick-protobuf/examples/pb_rs/data_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,9 @@
#![cfg_attr(rustfmt, rustfmt_skip)]


use std::io::Write;
use std::borrow::Cow;
use std::collections::HashMap;
use quick_protobuf::{MessageRead, MessageWrite, BytesReader, Writer, Result};
use quick_protobuf::{MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
use quick_protobuf::sizeofs::*;
use super::*;

Expand Down Expand Up @@ -73,7 +72,7 @@ impl MessageWrite for BarMessage {
+ 1 + sizeof_varint(*(&self.b_required_int32) as u64)
}

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
w.write_with_tag(8, |w| w.write_int32(*&self.b_required_int32))?;
Ok(())
}
Expand Down Expand Up @@ -195,7 +194,7 @@ impl<'a> MessageWrite for FooMessage<'a> {
mod_FooMessage::OneOftest_oneof::None => 0,
} }

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
if let Some(ref s) = self.f_int32 { w.write_with_tag(8, |w| w.write_int32(*s))?; }
if let Some(ref s) = self.f_int64 { w.write_with_tag(16, |w| w.write_int64(*s))?; }
if let Some(ref s) = self.f_uint32 { w.write_with_tag(24, |w| w.write_uint32(*s))?; }
Expand Down Expand Up @@ -275,7 +274,7 @@ impl MessageWrite for BazMessage {
+ self.nested.as_ref().map_or(0, |m| 1 + sizeof_len((m).get_size()))
}

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
if let Some(ref s) = self.nested { w.write_with_tag(10, |w| w.write_message(s))?; }
Ok(())
}
Expand Down Expand Up @@ -310,7 +309,7 @@ impl MessageWrite for Nested {
+ 1 + sizeof_len((&self.f_nested).get_size())
}

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
w.write_with_tag(10, |w| w.write_message(&self.f_nested))?;
Ok(())
}
Expand Down Expand Up @@ -345,7 +344,7 @@ impl MessageWrite for NestedMessage {
+ 1 + sizeof_varint(*(&self.f_nested) as u64)
}

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
w.write_with_tag(8, |w| w.write_int32(*&self.f_nested))?;
Ok(())
}
Expand Down
5 changes: 2 additions & 3 deletions quick-protobuf/examples/pb_rs_v3/a/b.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
#![cfg_attr(rustfmt, rustfmt_skip)]


use std::io::Write;
use quick_protobuf::{MessageRead, MessageWrite, BytesReader, Writer, Result};
use quick_protobuf::{MessageRead, MessageWrite, BytesReader, Writer, WriterBackend, Result};
use quick_protobuf::sizeofs::*;
use super::super::*;

Expand Down Expand Up @@ -39,7 +38,7 @@ impl MessageWrite for ImportedMessage {
+ if self.i == false { 0 } else { 1 + sizeof_varint(*(&self.i) as u64) }
}

fn write_message<W: Write>(&self, w: &mut Writer<W>) -> Result<()> {
fn write_message<W: WriterBackend>(&self, w: &mut Writer<W>) -> Result<()> {
if self.i != false { w.write_with_tag(8, |w| w.write_bool(*&self.i))?; }
Ok(())
}
Expand Down
Loading

0 comments on commit 8ca9750

Please sign in to comment.