blob: 5ec7df26b12b934e7a97989fcd8066e8116e051b [file] [log] [blame]
#![doc(hidden)]
//! `CodedInputStream` and `CodedOutputStream` implementations
use std::io;
use std::io::BufRead;
use std::io::Read;
use std::io::Write;
use std::mem;
use std::slice;
#[cfg(feature = "bytes")]
use crate::chars::Chars;
#[cfg(feature = "bytes")]
use bytes::Bytes;
use crate::buf_read_iter::BufReadIter;
use crate::enums::ProtobufEnum;
use crate::error::ProtobufError;
use crate::error::ProtobufResult;
use crate::error::WireError;
use crate::message::Message;
use crate::misc::remaining_capacity_as_slice_mut;
use crate::misc::remove_lifetime_mut;
use crate::unknown::UnknownFields;
use crate::unknown::UnknownValue;
use crate::unknown::UnknownValueRef;
use crate::varint;
use crate::zigzag::decode_zig_zag_32;
use crate::zigzag::decode_zig_zag_64;
use crate::zigzag::encode_zig_zag_32;
use crate::zigzag::encode_zig_zag_64;
/// Equal to the default buffer size of `BufWriter`, so when
/// `CodedOutputStream` wraps `BufWriter`, it often skips double buffering.
const OUTPUT_STREAM_BUFFER_SIZE: usize = 8 * 1024;
/// Default recursion level limit. 100 is the default value of C++'s implementation.
const DEFAULT_RECURSION_LIMIT: u32 = 100;
/// Max allocated vec when reading length-delimited from unknown input stream
pub(crate) const READ_RAW_BYTES_MAX_ALLOC: usize = 10_000_000;
/// Serialization constants.
pub mod wire_format {
// TODO: temporary
pub use self::WireType::*;
/// Tag occupies 3 bits
pub const TAG_TYPE_BITS: u32 = 3;
/// Tag mask
pub const TAG_TYPE_MASK: u32 = (1u32 << TAG_TYPE_BITS) - 1;
/// Max possible field number
pub const FIELD_NUMBER_MAX: u32 = 0x1fffffff;
/// One of six defined protobuf wire types
#[derive(PartialEq, Eq, Clone, Debug)]
pub enum WireType {
/// Varint (e. g. `int32` or `sint64`)
WireTypeVarint = 0,
/// Fixed size 64 bit (e. g. `fixed64` or `double`)
WireTypeFixed64 = 1,
/// Length-delimited (e. g. `message` or `string`)
WireTypeLengthDelimited = 2,
/// Groups are not supported by rust-protobuf
WireTypeStartGroup = 3,
/// Groups are not supported by rust-protobuf
WireTypeEndGroup = 4,
/// Fixed size 64 bit (e. g. `fixed32` or `float`)
WireTypeFixed32 = 5,
}
impl Copy for WireType {}
impl WireType {
/// Parse wire type
pub fn new(n: u32) -> Option<WireType> {
match n {
0 => Some(WireTypeVarint),
1 => Some(WireTypeFixed64),
2 => Some(WireTypeLengthDelimited),
3 => Some(WireTypeStartGroup),
4 => Some(WireTypeEndGroup),
5 => Some(WireTypeFixed32),
_ => None,
}
}
}
/// Parsed protobuf tag, which is a pair of field number and wire type
#[derive(Clone)]
pub struct Tag {
field_number: u32,
wire_type: WireType,
}
impl Copy for Tag {}
impl Tag {
/// Pack a tag to integer
pub fn value(self) -> u32 {
(self.field_number << TAG_TYPE_BITS) | (self.wire_type as u32)
}
/// Parse integer into `Tag` object
// TODO: should return Result instead of Option
pub fn new(value: u32) -> Option<Tag> {
let wire_type = WireType::new(value & TAG_TYPE_MASK);
if wire_type.is_none() {
return None;
}
let field_number = value >> TAG_TYPE_BITS;
if field_number == 0 {
return None;
}
Some(Tag {
field_number: field_number,
wire_type: wire_type.unwrap(),
})
}
/// Create a tag from a field number and wire type.
///
/// # Panics
///
/// If field number is outside of allowed range.
pub fn make(field_number: u32, wire_type: WireType) -> Tag {
assert!(field_number > 0 && field_number <= FIELD_NUMBER_MAX);
Tag {
field_number: field_number,
wire_type: wire_type,
}
}
/// Tag as pair of (field number, wire type)
pub fn unpack(self) -> (u32, WireType) {
(self.field_number(), self.wire_type())
}
fn wire_type(self) -> WireType {
self.wire_type
}
/// Protobuf field number
pub fn field_number(self) -> u32 {
self.field_number
}
}
}
/// Buffered read with handy utilities.
pub struct CodedInputStream<'a> {
source: BufReadIter<'a>,
recursion_level: u32,
recursion_limit: u32,
}
impl<'a> CodedInputStream<'a> {
/// Wrap a `Read`.
///
/// Note resulting `CodedInputStream` is buffered even if `Read` is not.
pub fn new(read: &'a mut dyn Read) -> CodedInputStream<'a> {
CodedInputStream::from_buf_read_iter(BufReadIter::from_read(read))
}
/// Create from `BufRead`.
///
/// `CodedInputStream` will utilize `BufRead` buffer.
pub fn from_buffered_reader(buf_read: &'a mut dyn BufRead) -> CodedInputStream<'a> {
CodedInputStream::from_buf_read_iter(BufReadIter::from_buf_read(buf_read))
}
/// Read from byte slice
pub fn from_bytes(bytes: &'a [u8]) -> CodedInputStream<'a> {
CodedInputStream::from_buf_read_iter(BufReadIter::from_byte_slice(bytes))
}
/// Read from `Bytes`.
///
/// `CodedInputStream` operations like
/// [`read_carllerche_bytes`](crate::CodedInputStream::read_carllerche_bytes)
/// will return a shared copy of this bytes object.
#[cfg(feature = "bytes")]
pub fn from_carllerche_bytes(bytes: &'a Bytes) -> CodedInputStream<'a> {
CodedInputStream::from_buf_read_iter(BufReadIter::from_bytes(bytes))
}
fn from_buf_read_iter(source: BufReadIter<'a>) -> CodedInputStream<'a> {
CodedInputStream {
source: source,
recursion_level: 0,
recursion_limit: DEFAULT_RECURSION_LIMIT,
}
}
/// Set the recursion limit.
pub fn set_recursion_limit(&mut self, limit: u32) {
self.recursion_limit = limit;
}
#[inline]
pub(crate) fn incr_recursion(&mut self) -> ProtobufResult<()> {
if self.recursion_level >= self.recursion_limit {
return Err(ProtobufError::WireError(WireError::OverRecursionLimit));
}
self.recursion_level += 1;
Ok(())
}
#[inline]
pub(crate) fn decr_recursion(&mut self) {
self.recursion_level -= 1;
}
/// How many bytes processed
pub fn pos(&self) -> u64 {
self.source.pos()
}
/// How many bytes until current limit
pub fn bytes_until_limit(&self) -> u64 {
self.source.bytes_until_limit()
}
/// Read bytes into given `buf`.
///
/// Return `0` on EOF.
// TODO: overload with `Read::read`
pub fn read(&mut self, buf: &mut [u8]) -> ProtobufResult<()> {
self.source.read_exact(buf)?;
Ok(())
}
/// Read exact number of bytes as `Bytes` object.
///
/// This operation returns a shared view if `CodedInputStream` is
/// constructed with `Bytes` parameter.
#[cfg(feature = "bytes")]
fn read_raw_callerche_bytes(&mut self, count: usize) -> ProtobufResult<Bytes> {
self.source.read_exact_bytes(count)
}
/// Read one byte
#[inline(always)]
pub fn read_raw_byte(&mut self) -> ProtobufResult<u8> {
self.source.read_byte()
}
/// Push new limit, return previous limit.
pub fn push_limit(&mut self, limit: u64) -> ProtobufResult<u64> {
self.source.push_limit(limit)
}
/// Restore previous limit.
pub fn pop_limit(&mut self, old_limit: u64) {
self.source.pop_limit(old_limit);
}
/// Are we at EOF?
#[inline(always)]
pub fn eof(&mut self) -> ProtobufResult<bool> {
self.source.eof()
}
/// Check we are at EOF.
///
/// Return error if we are not at EOF.
pub fn check_eof(&mut self) -> ProtobufResult<()> {
let eof = self.eof()?;
if !eof {
return Err(ProtobufError::WireError(WireError::UnexpectedEof));
}
Ok(())
}
fn read_raw_varint64_slow(&mut self) -> ProtobufResult<u64> {
let mut r: u64 = 0;
let mut i = 0;
loop {
if i == 10 {
return Err(ProtobufError::WireError(WireError::IncorrectVarint));
}
let b = self.read_raw_byte()?;
// TODO: may overflow if i == 9
r = r | (((b & 0x7f) as u64) << (i * 7));
i += 1;
if b < 0x80 {
return Ok(r);
}
}
}
/// Read varint
#[inline(always)]
pub fn read_raw_varint64(&mut self) -> ProtobufResult<u64> {
'slow: loop {
let ret;
let consume;
loop {
let rem = self.source.remaining_in_buf();
if rem.len() >= 1 {
// most varints are in practice fit in 1 byte
if rem[0] < 0x80 {
ret = rem[0] as u64;
consume = 1;
} else {
// handle case of two bytes too
if rem.len() >= 2 && rem[1] < 0x80 {
ret = (rem[0] & 0x7f) as u64 | (rem[1] as u64) << 7;
consume = 2;
} else if rem.len() >= 10 {
// Read from array when buf at at least 10 bytes,
// max len for varint.
let mut r: u64 = 0;
let mut i: usize = 0;
{
let rem = rem;
loop {
if i == 10 {
return Err(ProtobufError::WireError(
WireError::IncorrectVarint,
));
}
let b = if true {
// skip range check
unsafe { *rem.get_unchecked(i) }
} else {
rem[i]
};
// TODO: may overflow if i == 9
r = r | (((b & 0x7f) as u64) << (i * 7));
i += 1;
if b < 0x80 {
break;
}
}
}
consume = i;
ret = r;
} else {
break 'slow;
}
}
} else {
break 'slow;
}
break;
}
self.source.consume(consume);
return Ok(ret);
}
self.read_raw_varint64_slow()
}
/// Read varint
#[inline(always)]
pub fn read_raw_varint32(&mut self) -> ProtobufResult<u32> {
self.read_raw_varint64().map(|v| v as u32)
}
/// Read little-endian 32-bit integer
pub fn read_raw_little_endian32(&mut self) -> ProtobufResult<u32> {
let mut r = 0u32;
let bytes: &mut [u8] = unsafe {
let p: *mut u8 = mem::transmute(&mut r);
slice::from_raw_parts_mut(p, mem::size_of::<u32>())
};
self.read(bytes)?;
Ok(r.to_le())
}
/// Read little-endian 64-bit integer
pub fn read_raw_little_endian64(&mut self) -> ProtobufResult<u64> {
let mut r = 0u64;
let bytes: &mut [u8] = unsafe {
let p: *mut u8 = mem::transmute(&mut r);
slice::from_raw_parts_mut(p, mem::size_of::<u64>())
};
self.read(bytes)?;
Ok(r.to_le())
}
/// Read tag
#[inline]
pub fn read_tag(&mut self) -> ProtobufResult<wire_format::Tag> {
let v = self.read_raw_varint32()?;
match wire_format::Tag::new(v) {
Some(tag) => Ok(tag),
None => Err(ProtobufError::WireError(WireError::IncorrectTag(v))),
}
}
/// Read tag, return it is pair (field number, wire type)
#[inline]
pub fn read_tag_unpack(&mut self) -> ProtobufResult<(u32, wire_format::WireType)> {
self.read_tag().map(|t| t.unpack())
}
/// Read `double`
pub fn read_double(&mut self) -> ProtobufResult<f64> {
let bits = self.read_raw_little_endian64()?;
unsafe { Ok(mem::transmute::<u64, f64>(bits)) }
}
/// Read `float`
pub fn read_float(&mut self) -> ProtobufResult<f32> {
let bits = self.read_raw_little_endian32()?;
unsafe { Ok(mem::transmute::<u32, f32>(bits)) }
}
/// Read `int64`
pub fn read_int64(&mut self) -> ProtobufResult<i64> {
self.read_raw_varint64().map(|v| v as i64)
}
/// Read `int32`
pub fn read_int32(&mut self) -> ProtobufResult<i32> {
self.read_raw_varint32().map(|v| v as i32)
}
/// Read `uint64`
pub fn read_uint64(&mut self) -> ProtobufResult<u64> {
self.read_raw_varint64()
}
/// Read `uint32`
pub fn read_uint32(&mut self) -> ProtobufResult<u32> {
self.read_raw_varint32()
}
/// Read `sint64`
pub fn read_sint64(&mut self) -> ProtobufResult<i64> {
self.read_uint64().map(decode_zig_zag_64)
}
/// Read `sint32`
pub fn read_sint32(&mut self) -> ProtobufResult<i32> {
self.read_uint32().map(decode_zig_zag_32)
}
/// Read `fixed64`
pub fn read_fixed64(&mut self) -> ProtobufResult<u64> {
self.read_raw_little_endian64()
}
/// Read `fixed32`
pub fn read_fixed32(&mut self) -> ProtobufResult<u32> {
self.read_raw_little_endian32()
}
/// Read `sfixed64`
pub fn read_sfixed64(&mut self) -> ProtobufResult<i64> {
self.read_raw_little_endian64().map(|v| v as i64)
}
/// Read `sfixed32`
pub fn read_sfixed32(&mut self) -> ProtobufResult<i32> {
self.read_raw_little_endian32().map(|v| v as i32)
}
/// Read `bool`
pub fn read_bool(&mut self) -> ProtobufResult<bool> {
self.read_raw_varint32().map(|v| v != 0)
}
/// Read `enum` as `ProtobufEnum`
pub fn read_enum<E: ProtobufEnum>(&mut self) -> ProtobufResult<E> {
let i = self.read_int32()?;
match ProtobufEnum::from_i32(i) {
Some(e) => Ok(e),
None => Err(ProtobufError::WireError(WireError::InvalidEnumValue(i))),
}
}
/// Read `repeated` packed `double`
pub fn read_repeated_packed_double_into(
&mut self,
target: &mut Vec<f64>,
) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
target.reserve((len / 4) as usize);
let old_limit = self.push_limit(len)?;
while !self.eof()? {
target.push(self.read_double()?);
}
self.pop_limit(old_limit);
Ok(())
}
/// Read `repeated` packed `float`
pub fn read_repeated_packed_float_into(&mut self, target: &mut Vec<f32>) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
target.reserve((len / 4) as usize);
let old_limit = self.push_limit(len)?;
while !self.eof()? {
target.push(self.read_float()?);
}
self.pop_limit(old_limit);
Ok(())
}
/// Read `repeated` packed `int64`
pub fn read_repeated_packed_int64_into(&mut self, target: &mut Vec<i64>) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
let old_limit = self.push_limit(len as u64)?;
while !self.eof()? {
target.push(self.read_int64()?);
}
self.pop_limit(old_limit);
Ok(())
}
/// Read repeated packed `int32`
pub fn read_repeated_packed_int32_into(&mut self, target: &mut Vec<i32>) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
let old_limit = self.push_limit(len)?;
while !self.eof()? {
target.push(self.read_int32()?);
}
self.pop_limit(old_limit);
Ok(())
}
/// Read repeated packed `uint64`
pub fn read_repeated_packed_uint64_into(
&mut self,
target: &mut Vec<u64>,
) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
let old_limit = self.push_limit(len)?;
while !self.eof()? {
target.push(self.read_uint64()?);
}
self.pop_limit(old_limit);
Ok(())
}
/// Read repeated packed `uint32`
pub fn read_repeated_packed_uint32_into(
&mut self,
target: &mut Vec<u32>,
) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
let old_limit = self.push_limit(len)?;
while !self.eof()? {
target.push(self.read_uint32()?);
}
self.pop_limit(old_limit);
Ok(())
}
/// Read repeated packed `sint64`
pub fn read_repeated_packed_sint64_into(
&mut self,
target: &mut Vec<i64>,
) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
let old_limit = self.push_limit(len)?;
while !self.eof()? {
target.push(self.read_sint64()?);
}
self.pop_limit(old_limit);
Ok(())
}
/// Read repeated packed `sint32`
pub fn read_repeated_packed_sint32_into(
&mut self,
target: &mut Vec<i32>,
) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
let old_limit = self.push_limit(len)?;
while !self.eof()? {
target.push(self.read_sint32()?);
}
self.pop_limit(old_limit);
Ok(())
}
/// Read repeated packed `fixed64`
pub fn read_repeated_packed_fixed64_into(
&mut self,
target: &mut Vec<u64>,
) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
target.reserve((len / 8) as usize);
let old_limit = self.push_limit(len)?;
while !self.eof()? {
target.push(self.read_fixed64()?);
}
self.pop_limit(old_limit);
Ok(())
}
/// Read repeated packed `fixed32`
pub fn read_repeated_packed_fixed32_into(
&mut self,
target: &mut Vec<u32>,
) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
target.reserve((len / 4) as usize);
let old_limit = self.push_limit(len)?;
while !self.eof()? {
target.push(self.read_fixed32()?);
}
self.pop_limit(old_limit);
Ok(())
}
/// Read repeated packed `sfixed64`
pub fn read_repeated_packed_sfixed64_into(
&mut self,
target: &mut Vec<i64>,
) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
target.reserve((len / 8) as usize);
let old_limit = self.push_limit(len)?;
while !self.eof()? {
target.push(self.read_sfixed64()?);
}
self.pop_limit(old_limit);
Ok(())
}
/// Read repeated packed `sfixed32`
pub fn read_repeated_packed_sfixed32_into(
&mut self,
target: &mut Vec<i32>,
) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
target.reserve((len / 4) as usize);
let old_limit = self.push_limit(len)?;
while !self.eof()? {
target.push(self.read_sfixed32()?);
}
self.pop_limit(old_limit);
Ok(())
}
/// Read repeated packed `bool`
pub fn read_repeated_packed_bool_into(&mut self, target: &mut Vec<bool>) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
// regular bool value is 1-byte size
target.reserve(len as usize);
let old_limit = self.push_limit(len)?;
while !self.eof()? {
target.push(self.read_bool()?);
}
self.pop_limit(old_limit);
Ok(())
}
/// Read repeated packed `enum` into `ProtobufEnum`
pub fn read_repeated_packed_enum_into<E: ProtobufEnum>(
&mut self,
target: &mut Vec<E>,
) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
let old_limit = self.push_limit(len)?;
while !self.eof()? {
target.push(self.read_enum()?);
}
self.pop_limit(old_limit);
Ok(())
}
/// Read `UnknownValue`
pub fn read_unknown(
&mut self,
wire_type: wire_format::WireType,
) -> ProtobufResult<UnknownValue> {
match wire_type {
wire_format::WireTypeVarint => {
self.read_raw_varint64().map(|v| UnknownValue::Varint(v))
}
wire_format::WireTypeFixed64 => self.read_fixed64().map(|v| UnknownValue::Fixed64(v)),
wire_format::WireTypeFixed32 => self.read_fixed32().map(|v| UnknownValue::Fixed32(v)),
wire_format::WireTypeLengthDelimited => {
let len = self.read_raw_varint32()?;
self.read_raw_bytes(len)
.map(|v| UnknownValue::LengthDelimited(v))
}
_ => Err(ProtobufError::WireError(WireError::UnexpectedWireType(
wire_type,
))),
}
}
/// Skip field
pub fn skip_field(&mut self, wire_type: wire_format::WireType) -> ProtobufResult<()> {
self.read_unknown(wire_type).map(|_| ())
}
/// Read raw bytes into the supplied vector. The vector will be resized as needed and
/// overwritten.
pub fn read_raw_bytes_into(&mut self, count: u32, target: &mut Vec<u8>) -> ProtobufResult<()> {
if false {
// Master uses this version, but keep existing version for a while
// to avoid possible breakages.
return self.source.read_exact_to_vec(count as usize, target);
}
let count = count as usize;
// TODO: also do some limits when reading from unlimited source
if count as u64 > self.source.bytes_until_limit() {
return Err(ProtobufError::WireError(WireError::TruncatedMessage));
}
unsafe {
target.set_len(0);
}
if count >= READ_RAW_BYTES_MAX_ALLOC {
// avoid calling `reserve` on buf with very large buffer: could be a malformed message
let mut take = self.by_ref().take(count as u64);
take.read_to_end(target)?;
if target.len() != count {
return Err(ProtobufError::WireError(WireError::TruncatedMessage));
}
} else {
target.reserve(count);
unsafe {
target.set_len(count);
}
self.source.read_exact(target)?;
}
Ok(())
}
/// Read exact number of bytes
pub fn read_raw_bytes(&mut self, count: u32) -> ProtobufResult<Vec<u8>> {
let mut r = Vec::new();
self.read_raw_bytes_into(count, &mut r)?;
Ok(r)
}
/// Skip exact number of bytes
pub fn skip_raw_bytes(&mut self, count: u32) -> ProtobufResult<()> {
// TODO: make it more efficient
self.read_raw_bytes(count).map(|_| ())
}
/// Read `bytes` field, length delimited
pub fn read_bytes(&mut self) -> ProtobufResult<Vec<u8>> {
let mut r = Vec::new();
self.read_bytes_into(&mut r)?;
Ok(r)
}
/// Read `bytes` field, length delimited
#[cfg(feature = "bytes")]
pub fn read_carllerche_bytes(&mut self) -> ProtobufResult<Bytes> {
let len = self.read_raw_varint32()?;
self.read_raw_callerche_bytes(len as usize)
}
/// Read `string` field, length delimited
#[cfg(feature = "bytes")]
pub fn read_carllerche_chars(&mut self) -> ProtobufResult<Chars> {
let bytes = self.read_carllerche_bytes()?;
Ok(Chars::from_bytes(bytes)?)
}
/// Read `bytes` field, length delimited
pub fn read_bytes_into(&mut self, target: &mut Vec<u8>) -> ProtobufResult<()> {
let len = self.read_raw_varint32()?;
self.read_raw_bytes_into(len, target)?;
Ok(())
}
/// Read `string` field, length delimited
pub fn read_string(&mut self) -> ProtobufResult<String> {
let mut r = String::new();
self.read_string_into(&mut r)?;
Ok(r)
}
/// Read `string` field, length delimited
pub fn read_string_into(&mut self, target: &mut String) -> ProtobufResult<()> {
target.clear();
// take target's buffer
let mut vec = mem::replace(target, String::new()).into_bytes();
self.read_bytes_into(&mut vec)?;
let s = match String::from_utf8(vec) {
Ok(t) => t,
Err(_) => return Err(ProtobufError::WireError(WireError::Utf8Error)),
};
*target = s;
Ok(())
}
/// Read message, do not check if message is initialized
pub fn merge_message<M: Message>(&mut self, message: &mut M) -> ProtobufResult<()> {
let len = self.read_raw_varint64()?;
let old_limit = self.push_limit(len)?;
message.merge_from(self)?;
self.pop_limit(old_limit);
Ok(())
}
/// Read message
pub fn read_message<M: Message>(&mut self) -> ProtobufResult<M> {
let mut r: M = Message::new();
self.merge_message(&mut r)?;
r.check_initialized()?;
Ok(r)
}
}
impl<'a> Read for CodedInputStream<'a> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.source.read(buf).map_err(Into::into)
}
}
impl<'a> BufRead for CodedInputStream<'a> {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
self.source.fill_buf().map_err(Into::into)
}
fn consume(&mut self, amt: usize) {
self.source.consume(amt)
}
}
#[doc(hidden)]
pub trait WithCodedOutputStream {
fn with_coded_output_stream<T, F>(self, cb: F) -> ProtobufResult<T>
where
F: FnOnce(&mut CodedOutputStream) -> ProtobufResult<T>;
}
impl<'a> WithCodedOutputStream for &'a mut (dyn Write + 'a) {
fn with_coded_output_stream<T, F>(self, cb: F) -> ProtobufResult<T>
where
F: FnOnce(&mut CodedOutputStream) -> ProtobufResult<T>,
{
let mut os = CodedOutputStream::new(self);
let r = cb(&mut os)?;
os.flush()?;
Ok(r)
}
}
impl<'a> WithCodedOutputStream for &'a mut Vec<u8> {
fn with_coded_output_stream<T, F>(mut self, cb: F) -> ProtobufResult<T>
where
F: FnOnce(&mut CodedOutputStream) -> ProtobufResult<T>,
{
let mut os = CodedOutputStream::vec(&mut self);
let r = cb(&mut os)?;
os.flush()?;
Ok(r)
}
}
#[doc(hidden)]
pub fn with_coded_output_stream_to_bytes<F>(cb: F) -> ProtobufResult<Vec<u8>>
where
F: FnOnce(&mut CodedOutputStream) -> ProtobufResult<()>,
{
let mut v = Vec::new();
v.with_coded_output_stream(cb)?;
Ok(v)
}
/// Helper internal utility, should not be used directly
#[doc(hidden)]
pub trait WithCodedInputStream {
fn with_coded_input_stream<T, F>(self, cb: F) -> ProtobufResult<T>
where
F: FnOnce(&mut CodedInputStream) -> ProtobufResult<T>;
}
impl<'a> WithCodedInputStream for &'a mut (dyn Read + 'a) {
fn with_coded_input_stream<T, F>(self, cb: F) -> ProtobufResult<T>
where
F: FnOnce(&mut CodedInputStream) -> ProtobufResult<T>,
{
let mut is = CodedInputStream::new(self);
let r = cb(&mut is)?;
is.check_eof()?;
Ok(r)
}
}
impl<'a> WithCodedInputStream for &'a mut (dyn BufRead + 'a) {
fn with_coded_input_stream<T, F>(self, cb: F) -> ProtobufResult<T>
where
F: FnOnce(&mut CodedInputStream) -> ProtobufResult<T>,
{
let mut is = CodedInputStream::from_buffered_reader(self);
let r = cb(&mut is)?;
is.check_eof()?;
Ok(r)
}
}
impl<'a> WithCodedInputStream for &'a [u8] {
fn with_coded_input_stream<T, F>(self, cb: F) -> ProtobufResult<T>
where
F: FnOnce(&mut CodedInputStream) -> ProtobufResult<T>,
{
let mut is = CodedInputStream::from_bytes(self);
let r = cb(&mut is)?;
is.check_eof()?;
Ok(r)
}
}
#[cfg(feature = "bytes")]
impl<'a> WithCodedInputStream for &'a Bytes {
fn with_coded_input_stream<T, F>(self, cb: F) -> ProtobufResult<T>
where
F: FnOnce(&mut CodedInputStream) -> ProtobufResult<T>,
{
let mut is = CodedInputStream::from_carllerche_bytes(self);
let r = cb(&mut is)?;
is.check_eof()?;
Ok(r)
}
}
enum OutputTarget<'a> {
Write(&'a mut dyn Write, Vec<u8>),
Vec(&'a mut Vec<u8>),
Bytes,
}
/// Buffered write with handy utilities
pub struct CodedOutputStream<'a> {
target: OutputTarget<'a>,
// alias to buf from target
buffer: &'a mut [u8],
// within buffer
position: usize,
}
impl<'a> CodedOutputStream<'a> {
/// Construct from given `Write`.
///
/// `CodedOutputStream` is buffered even if `Write` is not
pub fn new(writer: &'a mut dyn Write) -> CodedOutputStream<'a> {
let buffer_len = OUTPUT_STREAM_BUFFER_SIZE;
let mut buffer_storage = Vec::with_capacity(buffer_len);
unsafe {
buffer_storage.set_len(buffer_len);
}
let buffer = unsafe { remove_lifetime_mut(&mut buffer_storage as &mut [u8]) };
CodedOutputStream {
target: OutputTarget::Write(writer, buffer_storage),
buffer: buffer,
position: 0,
}
}
/// `CodedOutputStream` which writes directly to bytes.
///
/// Attempt to write more than bytes capacity results in error.
pub fn bytes(bytes: &'a mut [u8]) -> CodedOutputStream<'a> {
CodedOutputStream {
target: OutputTarget::Bytes,
buffer: bytes,
position: 0,
}
}
/// `CodedOutputStream` which writes directly to `Vec<u8>`.
///
/// Caller should call `flush` at the end to guarantee vec contains
/// all written data.
pub fn vec(vec: &'a mut Vec<u8>) -> CodedOutputStream<'a> {
CodedOutputStream {
target: OutputTarget::Vec(vec),
buffer: &mut [],
position: 0,
}
}
/// Check if EOF is reached.
///
/// # Panics
///
/// If underlying write has no EOF
pub fn check_eof(&self) {
match self.target {
OutputTarget::Bytes => {
assert_eq!(self.buffer.len() as u64, self.position as u64);
}
OutputTarget::Write(..) | OutputTarget::Vec(..) => {
panic!("must not be called with Writer or Vec");
}
}
}
fn refresh_buffer(&mut self) -> ProtobufResult<()> {
match self.target {
OutputTarget::Write(ref mut write, _) => {
write.write_all(&self.buffer[0..self.position as usize])?;
self.position = 0;
}
OutputTarget::Vec(ref mut vec) => unsafe {
let vec_len = vec.len();
assert!(vec_len + self.position <= vec.capacity());
vec.set_len(vec_len + self.position);
vec.reserve(1);
self.buffer = remove_lifetime_mut(remaining_capacity_as_slice_mut(vec));
self.position = 0;
},
OutputTarget::Bytes => {
panic!("refresh_buffer must not be called on CodedOutputStream create from slice");
}
}
Ok(())
}
/// Flush the buffer to underlying write
pub fn flush(&mut self) -> ProtobufResult<()> {
match self.target {
OutputTarget::Bytes => Ok(()),
OutputTarget::Write(..) | OutputTarget::Vec(..) => {
// TODO: must not reserve additional in Vec
self.refresh_buffer()
}
}
}
/// Write a byte
pub fn write_raw_byte(&mut self, byte: u8) -> ProtobufResult<()> {
if self.position as usize == self.buffer.len() {
self.refresh_buffer()?;
}
self.buffer[self.position as usize] = byte;
self.position += 1;
Ok(())
}
/// Write bytes
pub fn write_raw_bytes(&mut self, bytes: &[u8]) -> ProtobufResult<()> {
if bytes.len() <= self.buffer.len() - self.position {
let bottom = self.position as usize;
let top = bottom + (bytes.len() as usize);
self.buffer[bottom..top].copy_from_slice(bytes);
self.position += bytes.len();
return Ok(());
}
self.refresh_buffer()?;
assert!(self.position == 0);
if self.position + bytes.len() < self.buffer.len() {
&mut self.buffer[self.position..self.position + bytes.len()].copy_from_slice(bytes);
self.position += bytes.len();
return Ok(());
}
match self.target {
OutputTarget::Bytes => {
unreachable!();
}
OutputTarget::Write(ref mut write, _) => {
write.write_all(bytes)?;
}
OutputTarget::Vec(ref mut vec) => {
vec.extend(bytes);
unsafe {
self.buffer = remove_lifetime_mut(remaining_capacity_as_slice_mut(vec));
}
}
}
Ok(())
}
/// Write a tag
pub fn write_tag(
&mut self,
field_number: u32,
wire_type: wire_format::WireType,
) -> ProtobufResult<()> {
self.write_raw_varint32(wire_format::Tag::make(field_number, wire_type).value())
}
/// Write varint
pub fn write_raw_varint32(&mut self, value: u32) -> ProtobufResult<()> {
if self.buffer.len() - self.position >= 5 {
// fast path
let len = varint::encode_varint32(value, &mut self.buffer[self.position..]);
self.position += len;
Ok(())
} else {
// slow path
let buf = &mut [0u8; 5];
let len = varint::encode_varint32(value, buf);
self.write_raw_bytes(&buf[..len])
}
}
/// Write varint
pub fn write_raw_varint64(&mut self, value: u64) -> ProtobufResult<()> {
if self.buffer.len() - self.position >= 10 {
// fast path
let len = varint::encode_varint64(value, &mut self.buffer[self.position..]);
self.position += len;
Ok(())
} else {
// slow path
let buf = &mut [0u8; 10];
let len = varint::encode_varint64(value, buf);
self.write_raw_bytes(&buf[..len])
}
}
/// Write 32-bit integer little endian
pub fn write_raw_little_endian32(&mut self, value: u32) -> ProtobufResult<()> {
let bytes = unsafe { mem::transmute::<_, [u8; 4]>(value.to_le()) };
self.write_raw_bytes(&bytes)
}
/// Write 64-bit integer little endian
pub fn write_raw_little_endian64(&mut self, value: u64) -> ProtobufResult<()> {
let bytes = unsafe { mem::transmute::<_, [u8; 8]>(value.to_le()) };
self.write_raw_bytes(&bytes)
}
/// Write `float`
pub fn write_float_no_tag(&mut self, value: f32) -> ProtobufResult<()> {
let bits = unsafe { mem::transmute::<f32, u32>(value) };
self.write_raw_little_endian32(bits)
}
/// Write `double`
pub fn write_double_no_tag(&mut self, value: f64) -> ProtobufResult<()> {
let bits = unsafe { mem::transmute::<f64, u64>(value) };
self.write_raw_little_endian64(bits)
}
/// Write `float` field
pub fn write_float(&mut self, field_number: u32, value: f32) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeFixed32)?;
self.write_float_no_tag(value)?;
Ok(())
}
/// Write `double` field
pub fn write_double(&mut self, field_number: u32, value: f64) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeFixed64)?;
self.write_double_no_tag(value)?;
Ok(())
}
/// Write varint
pub fn write_uint64_no_tag(&mut self, value: u64) -> ProtobufResult<()> {
self.write_raw_varint64(value)
}
/// Write varint
pub fn write_uint32_no_tag(&mut self, value: u32) -> ProtobufResult<()> {
self.write_raw_varint32(value)
}
/// Write varint
pub fn write_int64_no_tag(&mut self, value: i64) -> ProtobufResult<()> {
self.write_raw_varint64(value as u64)
}
/// Write varint
pub fn write_int32_no_tag(&mut self, value: i32) -> ProtobufResult<()> {
self.write_raw_varint64(value as u64)
}
/// Write zigzag varint
pub fn write_sint64_no_tag(&mut self, value: i64) -> ProtobufResult<()> {
self.write_uint64_no_tag(encode_zig_zag_64(value))
}
/// Write zigzag varint
pub fn write_sint32_no_tag(&mut self, value: i32) -> ProtobufResult<()> {
self.write_uint32_no_tag(encode_zig_zag_32(value))
}
/// Write `fixed64`
pub fn write_fixed64_no_tag(&mut self, value: u64) -> ProtobufResult<()> {
self.write_raw_little_endian64(value)
}
/// Write `fixed32`
pub fn write_fixed32_no_tag(&mut self, value: u32) -> ProtobufResult<()> {
self.write_raw_little_endian32(value)
}
/// Write `sfixed64`
pub fn write_sfixed64_no_tag(&mut self, value: i64) -> ProtobufResult<()> {
self.write_raw_little_endian64(value as u64)
}
/// Write `sfixed32`
pub fn write_sfixed32_no_tag(&mut self, value: i32) -> ProtobufResult<()> {
self.write_raw_little_endian32(value as u32)
}
/// Write `bool`
pub fn write_bool_no_tag(&mut self, value: bool) -> ProtobufResult<()> {
self.write_raw_varint32(if value { 1 } else { 0 })
}
/// Write `enum`
pub fn write_enum_no_tag(&mut self, value: i32) -> ProtobufResult<()> {
self.write_int32_no_tag(value)
}
/// Write `enum`
pub fn write_enum_obj_no_tag<E>(&mut self, value: E) -> ProtobufResult<()>
where
E: ProtobufEnum,
{
self.write_enum_no_tag(value.value())
}
/// Write unknown value
pub fn write_unknown_no_tag(&mut self, unknown: UnknownValueRef) -> ProtobufResult<()> {
match unknown {
UnknownValueRef::Fixed64(fixed64) => self.write_raw_little_endian64(fixed64),
UnknownValueRef::Fixed32(fixed32) => self.write_raw_little_endian32(fixed32),
UnknownValueRef::Varint(varint) => self.write_raw_varint64(varint),
UnknownValueRef::LengthDelimited(bytes) => self.write_bytes_no_tag(bytes),
}
}
/// Write `uint64` field
pub fn write_uint64(&mut self, field_number: u32, value: u64) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeVarint)?;
self.write_uint64_no_tag(value)?;
Ok(())
}
/// Write `uint32` field
pub fn write_uint32(&mut self, field_number: u32, value: u32) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeVarint)?;
self.write_uint32_no_tag(value)?;
Ok(())
}
/// Write `int64` field
pub fn write_int64(&mut self, field_number: u32, value: i64) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeVarint)?;
self.write_int64_no_tag(value)?;
Ok(())
}
/// Write `int32` field
pub fn write_int32(&mut self, field_number: u32, value: i32) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeVarint)?;
self.write_int32_no_tag(value)?;
Ok(())
}
/// Write `sint64` field
pub fn write_sint64(&mut self, field_number: u32, value: i64) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeVarint)?;
self.write_sint64_no_tag(value)?;
Ok(())
}
/// Write `sint32` field
pub fn write_sint32(&mut self, field_number: u32, value: i32) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeVarint)?;
self.write_sint32_no_tag(value)?;
Ok(())
}
/// Write `fixed64` field
pub fn write_fixed64(&mut self, field_number: u32, value: u64) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeFixed64)?;
self.write_fixed64_no_tag(value)?;
Ok(())
}
/// Write `fixed32` field
pub fn write_fixed32(&mut self, field_number: u32, value: u32) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeFixed32)?;
self.write_fixed32_no_tag(value)?;
Ok(())
}
/// Write `sfixed64` field
pub fn write_sfixed64(&mut self, field_number: u32, value: i64) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeFixed64)?;
self.write_sfixed64_no_tag(value)?;
Ok(())
}
/// Write `sfixed32` field
pub fn write_sfixed32(&mut self, field_number: u32, value: i32) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeFixed32)?;
self.write_sfixed32_no_tag(value)?;
Ok(())
}
/// Write `bool` field
pub fn write_bool(&mut self, field_number: u32, value: bool) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeVarint)?;
self.write_bool_no_tag(value)?;
Ok(())
}
/// Write `enum` field
pub fn write_enum(&mut self, field_number: u32, value: i32) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeVarint)?;
self.write_enum_no_tag(value)?;
Ok(())
}
/// Write `enum` field
pub fn write_enum_obj<E>(&mut self, field_number: u32, value: E) -> ProtobufResult<()>
where
E: ProtobufEnum,
{
self.write_enum(field_number, value.value())
}
/// Write unknown field
pub fn write_unknown(
&mut self,
field_number: u32,
value: UnknownValueRef,
) -> ProtobufResult<()> {
self.write_tag(field_number, value.wire_type())?;
self.write_unknown_no_tag(value)?;
Ok(())
}
/// Write unknown fields
pub fn write_unknown_fields(&mut self, fields: &UnknownFields) -> ProtobufResult<()> {
for (number, values) in fields {
for value in values {
self.write_unknown(number, value)?;
}
}
Ok(())
}
/// Write bytes
pub fn write_bytes_no_tag(&mut self, bytes: &[u8]) -> ProtobufResult<()> {
self.write_raw_varint32(bytes.len() as u32)?;
self.write_raw_bytes(bytes)?;
Ok(())
}
/// Write string
pub fn write_string_no_tag(&mut self, s: &str) -> ProtobufResult<()> {
self.write_bytes_no_tag(s.as_bytes())
}
/// Write message
pub fn write_message_no_tag<M: Message>(&mut self, msg: &M) -> ProtobufResult<()> {
msg.write_length_delimited_to(self)
}
/// Write `bytes` field
pub fn write_bytes(&mut self, field_number: u32, bytes: &[u8]) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeLengthDelimited)?;
self.write_bytes_no_tag(bytes)?;
Ok(())
}
/// Write `string` field
pub fn write_string(&mut self, field_number: u32, s: &str) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeLengthDelimited)?;
self.write_string_no_tag(s)?;
Ok(())
}
/// Write `message` field
pub fn write_message<M: Message>(&mut self, field_number: u32, msg: &M) -> ProtobufResult<()> {
self.write_tag(field_number, wire_format::WireTypeLengthDelimited)?;
self.write_message_no_tag(msg)?;
Ok(())
}
}
impl<'a> Write for CodedOutputStream<'a> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.write_raw_bytes(buf)?;
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
CodedOutputStream::flush(self).map_err(Into::into)
}
}
#[cfg(test)]
mod test {
use std::fmt::Debug;
use std::io;
use std::io::BufRead;
use std::io::Read;
use std::io::Write;
use std::iter::repeat;
use crate::error::ProtobufError;
use crate::error::ProtobufResult;
use crate::hex::decode_hex;
use crate::hex::encode_hex;
use super::wire_format;
use super::CodedInputStream;
use super::CodedOutputStream;
use super::READ_RAW_BYTES_MAX_ALLOC;
fn test_read_partial<F>(hex: &str, mut callback: F)
where
F: FnMut(&mut CodedInputStream),
{
let d = decode_hex(hex);
let mut reader = io::Cursor::new(d);
let mut is = CodedInputStream::from_buffered_reader(&mut reader as &mut dyn BufRead);
assert_eq!(0, is.pos());
callback(&mut is);
}
fn test_read<F>(hex: &str, mut callback: F)
where
F: FnMut(&mut CodedInputStream),
{
let len = decode_hex(hex).len();
test_read_partial(hex, |reader| {
callback(reader);
assert!(reader.eof().expect("eof"));
assert_eq!(len as u64, reader.pos());
});
}
fn test_read_v<F, V>(hex: &str, v: V, mut callback: F)
where
F: FnMut(&mut CodedInputStream) -> ProtobufResult<V>,
V: PartialEq + Debug,
{
test_read(hex, |reader| {
assert_eq!(v, callback(reader).unwrap());
});
}
#[test]
fn test_input_stream_read_raw_byte() {
test_read("17", |is| {
assert_eq!(23, is.read_raw_byte().unwrap());
});
}
#[test]
fn test_input_stream_read_raw_varint() {
test_read_v("07", 7, |reader| reader.read_raw_varint32());
test_read_v("07", 7, |reader| reader.read_raw_varint64());
test_read_v("96 01", 150, |reader| reader.read_raw_varint32());
test_read_v("96 01", 150, |reader| reader.read_raw_varint64());
test_read_v(
"ff ff ff ff ff ff ff ff ff 01",
0xffffffffffffffff,
|reader| reader.read_raw_varint64(),
);
test_read_v("ff ff ff ff 0f", 0xffffffff, |reader| {
reader.read_raw_varint32()
});
test_read_v("ff ff ff ff 0f", 0xffffffff, |reader| {
reader.read_raw_varint64()
});
}
#[test]
fn test_input_stream_read_raw_vaint_malformed() {
// varint cannot have length > 10
test_read_partial("ff ff ff ff ff ff ff ff ff ff 01", |reader| {
let result = reader.read_raw_varint64();
match result {
// TODO: make an enum variant
Err(ProtobufError::WireError(..)) => (),
_ => panic!(),
}
});
test_read_partial("ff ff ff ff ff ff ff ff ff ff 01", |reader| {
let result = reader.read_raw_varint32();
match result {
// TODO: make an enum variant
Err(ProtobufError::WireError(..)) => (),
_ => panic!(),
}
});
}
#[test]
fn test_input_stream_read_raw_varint_unexpected_eof() {
test_read_partial("96 97", |reader| {
let result = reader.read_raw_varint32();
match result {
Err(ProtobufError::WireError(..)) => (),
_ => panic!(),
}
});
}
#[test]
fn test_input_stream_read_raw_varint_pos() {
test_read_partial("95 01 98", |reader| {
assert_eq!(149, reader.read_raw_varint32().unwrap());
assert_eq!(2, reader.pos());
});
}
#[test]
fn test_input_stream_read_int32() {
test_read_v("02", 2, |reader| reader.read_int32());
}
#[test]
fn test_input_stream_read_float() {
test_read_v("95 73 13 61", 17e19, |is| is.read_float());
}
#[test]
fn test_input_stream_read_double() {
test_read_v("40 d5 ab 68 b3 07 3d 46", 23e29, |is| is.read_double());
}
#[test]
fn test_input_stream_skip_raw_bytes() {
test_read("", |reader| {
reader.skip_raw_bytes(0).unwrap();
});
test_read("aa bb", |reader| {
reader.skip_raw_bytes(2).unwrap();
});
test_read("aa bb cc dd ee ff", |reader| {
reader.skip_raw_bytes(6).unwrap();
});
}
#[test]
fn test_input_stream_read_raw_bytes() {
test_read("", |reader| {
assert_eq!(
Vec::from(&b""[..]),
reader.read_raw_bytes(0).expect("read_raw_bytes")
);
})
}
#[test]
fn test_input_stream_limits() {
test_read("aa bb cc", |is| {
let old_limit = is.push_limit(1).unwrap();
assert_eq!(1, is.bytes_until_limit());
let r1 = is.read_raw_bytes(1).unwrap();
assert_eq!(&[0xaa as u8], &r1[..]);
is.pop_limit(old_limit);
let r2 = is.read_raw_bytes(2).unwrap();
assert_eq!(&[0xbb as u8, 0xcc], &r2[..]);
});
}
#[test]
fn test_input_stream_io_read() {
test_read("aa bb cc", |is| {
let mut buf = [0; 3];
assert_eq!(Read::read(is, &mut buf).expect("io::Read"), 3);
assert_eq!(buf, [0xaa, 0xbb, 0xcc]);
});
}
#[test]
fn test_input_stream_io_bufread() {
test_read("aa bb cc", |is| {
assert_eq!(
BufRead::fill_buf(is).expect("io::BufRead::fill_buf"),
&[0xaa, 0xbb, 0xcc]
);
BufRead::consume(is, 3);
});
}
#[test]
fn test_input_stream_read_raw_bytes_into_huge() {
let mut v = Vec::new();
for i in 0..READ_RAW_BYTES_MAX_ALLOC + 1000 {
v.push((i % 10) as u8);
}
let mut slice: &[u8] = v.as_slice();
let mut is = CodedInputStream::new(&mut slice);
let mut buf = Vec::new();
is.read_raw_bytes_into(READ_RAW_BYTES_MAX_ALLOC as u32 + 10, &mut buf)
.expect("read");
assert_eq!(READ_RAW_BYTES_MAX_ALLOC + 10, buf.len());
buf.clear();
is.read_raw_bytes_into(1000 - 10, &mut buf).expect("read");
assert_eq!(1000 - 10, buf.len());
assert!(is.eof().expect("eof"));
}
fn test_write<F>(expected: &str, mut gen: F)
where
F: FnMut(&mut CodedOutputStream) -> ProtobufResult<()>,
{
let expected_bytes = decode_hex(expected);
// write to Write
{
let mut v = Vec::new();
{
let mut os = CodedOutputStream::new(&mut v as &mut dyn Write);
gen(&mut os).unwrap();
os.flush().unwrap();
}
assert_eq!(encode_hex(&expected_bytes), encode_hex(&v));
}
// write to &[u8]
{
let mut r = Vec::with_capacity(expected_bytes.len());
r.resize(expected_bytes.len(), 0);
{
let mut os = CodedOutputStream::bytes(&mut r);
gen(&mut os).unwrap();
os.check_eof();
}
assert_eq!(encode_hex(&expected_bytes), encode_hex(&r));
}
// write to Vec<u8>
{
let mut r = Vec::new();
r.extend(&[11, 22, 33, 44, 55, 66, 77]);
{
let mut os = CodedOutputStream::vec(&mut r);
gen(&mut os).unwrap();
os.flush().unwrap();
}
r.drain(..7);
assert_eq!(encode_hex(&expected_bytes), encode_hex(&r));
}
}
#[test]
fn test_output_stream_write_raw_byte() {
test_write("a1", |os| os.write_raw_byte(0xa1));
}
#[test]
fn test_output_stream_write_tag() {
test_write("08", |os| os.write_tag(1, wire_format::WireTypeVarint));
}
#[test]
fn test_output_stream_write_raw_bytes() {
test_write("00 ab", |os| os.write_raw_bytes(&[0x00, 0xab]));
let expected = repeat("01 02 03 04")
.take(2048)
.collect::<Vec<_>>()
.join(" ");
test_write(&expected, |os| {
for _ in 0..2048 {
os.write_raw_bytes(&[0x01, 0x02, 0x03, 0x04])?;
}
Ok(())
});
}
#[test]
fn test_output_stream_write_raw_varint32() {
test_write("96 01", |os| os.write_raw_varint32(150));
test_write("ff ff ff ff 0f", |os| os.write_raw_varint32(0xffffffff));
}
#[test]
fn test_output_stream_write_raw_varint64() {
test_write("96 01", |os| os.write_raw_varint64(150));
test_write("ff ff ff ff ff ff ff ff ff 01", |os| {
os.write_raw_varint64(0xffffffffffffffff)
});
}
#[test]
fn test_output_stream_write_int32_no_tag() {
test_write("ff ff ff ff ff ff ff ff ff 01", |os| {
os.write_int32_no_tag(-1)
});
}
#[test]
fn test_output_stream_write_int64_no_tag() {
test_write("ff ff ff ff ff ff ff ff ff 01", |os| {
os.write_int64_no_tag(-1)
});
}
#[test]
fn test_output_stream_write_raw_little_endian32() {
test_write("f1 e2 d3 c4", |os| os.write_raw_little_endian32(0xc4d3e2f1));
}
#[test]
fn test_output_stream_write_float_no_tag() {
test_write("95 73 13 61", |os| os.write_float_no_tag(17e19));
}
#[test]
fn test_output_stream_write_double_no_tag() {
test_write("40 d5 ab 68 b3 07 3d 46", |os| {
os.write_double_no_tag(23e29)
});
}
#[test]
fn test_output_stream_write_raw_little_endian64() {
test_write("f1 e2 d3 c4 b5 a6 07 f8", |os| {
os.write_raw_little_endian64(0xf807a6b5c4d3e2f1)
});
}
#[test]
fn test_output_stream_io_write() {
let expected = [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77];
// write to Write
{
let mut v = Vec::new();
{
let mut os = CodedOutputStream::new(&mut v as &mut dyn Write);
Write::write(&mut os, &expected).expect("io::Write::write");
Write::flush(&mut os).expect("io::Write::flush");
}
assert_eq!(expected, *v);
}
// write to &[u8]
{
let mut v = Vec::with_capacity(expected.len());
v.resize(expected.len(), 0);
{
let mut os = CodedOutputStream::bytes(&mut v);
Write::write(&mut os, &expected).expect("io::Write::write");
Write::flush(&mut os).expect("io::Write::flush");
os.check_eof();
}
assert_eq!(expected, *v);
}
// write to Vec<u8>
{
let mut v = Vec::new();
{
let mut os = CodedOutputStream::vec(&mut v);
Write::write(&mut os, &expected).expect("io::Write::write");
Write::flush(&mut os).expect("io::Write::flush");
}
assert_eq!(expected, *v);
}
}
}