diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/buf_read_iter.rs | 4 | ||||
-rw-r--r-- | src/coded_input_stream.rs (renamed from src/stream.rs) | 801 | ||||
-rw-r--r-- | src/coded_output_stream.rs | 705 | ||||
-rw-r--r-- | src/descriptor.rs | 4 | ||||
-rw-r--r-- | src/lib.rs | 10 | ||||
-rw-r--r-- | src/message.rs | 10 | ||||
-rw-r--r-- | src/plugin.rs | 4 | ||||
-rw-r--r-- | src/rt.rs | 108 | ||||
-rw-r--r-- | src/rustproto.rs | 4 | ||||
-rw-r--r-- | src/types.rs | 4 | ||||
-rw-r--r-- | src/unknown.rs | 2 | ||||
-rw-r--r-- | src/well_known_types/any.rs | 4 | ||||
-rw-r--r-- | src/well_known_types/api.rs | 4 | ||||
-rw-r--r-- | src/well_known_types/duration.rs | 4 | ||||
-rw-r--r-- | src/well_known_types/empty.rs | 4 | ||||
-rw-r--r-- | src/well_known_types/field_mask.rs | 4 | ||||
-rw-r--r-- | src/well_known_types/source_context.rs | 4 | ||||
-rw-r--r-- | src/well_known_types/struct_pb.rs | 4 | ||||
-rw-r--r-- | src/well_known_types/timestamp.rs | 4 | ||||
-rw-r--r-- | src/well_known_types/type_pb.rs | 4 | ||||
-rw-r--r-- | src/well_known_types/wrappers.rs | 4 | ||||
-rw-r--r-- | src/wire_format.rs | 105 |
22 files changed, 904 insertions, 897 deletions
diff --git a/src/buf_read_iter.rs b/src/buf_read_iter.rs index cf36280..21f51a1 100644 --- a/src/buf_read_iter.rs +++ b/src/buf_read_iter.rs @@ -14,13 +14,11 @@ use bytes::Bytes; #[cfg(feature = "bytes")] use bytes::BytesMut; +use crate::coded_input_stream::READ_RAW_BYTES_MAX_ALLOC; use crate::error::WireError; -use crate::stream::READ_RAW_BYTES_MAX_ALLOC; use crate::ProtobufError; use crate::ProtobufResult; -use std::mem::MaybeUninit; - // If an input stream is constructed with a `Read`, we create a // `BufReader` with an internal buffer of this size. const INPUT_STREAM_BUFFER_SIZE: usize = 4096; diff --git a/src/stream.rs b/src/coded_input_stream.rs index 5ec7df2..52a13a6 100644 --- a/src/stream.rs +++ b/src/coded_input_stream.rs @@ -5,7 +5,6 @@ use std::io; use std::io::BufRead; use std::io::Read; -use std::io::Write; use std::mem; use std::slice; @@ -20,20 +19,10 @@ 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::wire_format; 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; @@ -41,113 +30,6 @@ 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>, @@ -848,47 +730,6 @@ impl<'a> BufRead for CodedInputStream<'a> { } } -#[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 { @@ -946,478 +787,6 @@ impl<'a> WithCodedInputStream for &'a Bytes { } } -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 { @@ -1425,17 +794,12 @@ mod test { 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) @@ -1637,167 +1001,4 @@ mod test { 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); - } - } } diff --git a/src/coded_output_stream.rs b/src/coded_output_stream.rs new file mode 100644 index 0000000..fb7e75c --- /dev/null +++ b/src/coded_output_stream.rs @@ -0,0 +1,705 @@ +use crate::misc::remaining_capacity_as_slice_mut; +use crate::misc::remove_lifetime_mut; +use crate::varint; +use crate::wire_format; +use crate::zigzag::encode_zig_zag_32; +use crate::zigzag::encode_zig_zag_64; +use crate::Message; +use crate::ProtobufEnum; +use crate::ProtobufResult; +use crate::UnknownFields; +use crate::UnknownValueRef; +use std::io; +use std::io::Write; +use std::mem; + +/// 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; + +#[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) +} + +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 crate::coded_output_stream::CodedOutputStream; + use crate::hex::decode_hex; + use crate::hex::encode_hex; + use crate::wire_format; + use crate::ProtobufResult; + use std::io::Write; + use std::iter; + + 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 = iter::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); + } + } +} diff --git a/src/descriptor.rs b/src/descriptor.rs index 3e76bee..8f3dd2f 100644 --- a/src/descriptor.rs +++ b/src/descriptor.rs @@ -1,4 +1,4 @@ -// This file is generated by rust-protobuf 2.22.0-pre. Do not edit +// This file is generated by rust-protobuf 2.22.0. Do not edit // @generated // https://github.com/rust-lang/rust-clippy/issues/702 @@ -6,7 +6,7 @@ #![allow(clippy::all)] #![allow(unused_attributes)] -#![rustfmt::skip] +#![cfg_attr(rustfmt, rustfmt::skip)] #![allow(box_pointers)] #![allow(dead_code)] @@ -14,6 +14,8 @@ pub use crate::cached_size::CachedSize; #[cfg(feature = "bytes")] pub use crate::chars::Chars; pub use crate::clear::Clear; +pub use crate::coded_input_stream::CodedInputStream; +pub use crate::coded_output_stream::CodedOutputStream; pub use crate::enums::ProtobufEnum; pub use crate::error::ProtobufError; pub use crate::error::ProtobufResult; @@ -34,9 +36,6 @@ pub use crate::message::Message; pub use crate::repeated::RepeatedField; pub use crate::singular::SingularField; pub use crate::singular::SingularPtrField; -pub use crate::stream::wire_format; -pub use crate::stream::CodedInputStream; -pub use crate::stream::CodedOutputStream; pub use crate::unknown::UnknownFields; pub use crate::unknown::UnknownFieldsIter; pub use crate::unknown::UnknownValue; @@ -49,7 +48,11 @@ pub mod descriptor; pub mod plugin; pub mod rustproto; +pub mod wire_format; + mod clear; +mod coded_input_stream; +mod coded_output_stream; pub mod compiler_plugin; mod enums; pub mod error; @@ -62,7 +65,6 @@ pub mod reflect; mod repeated; pub mod rt; mod singular; -pub mod stream; pub mod text_format; pub mod types; pub mod well_known_types; diff --git a/src/message.rs b/src/message.rs index b22ace2..e9d6b30 100644 --- a/src/message.rs +++ b/src/message.rs @@ -8,14 +8,14 @@ use std::io::Write; use bytes::Bytes; use crate::clear::Clear; +use crate::coded_input_stream::CodedInputStream; +use crate::coded_input_stream::WithCodedInputStream; +use crate::coded_output_stream::with_coded_output_stream_to_bytes; +use crate::coded_output_stream::CodedOutputStream; +use crate::coded_output_stream::WithCodedOutputStream; use crate::error::ProtobufError; use crate::error::ProtobufResult; use crate::reflect::MessageDescriptor; -use crate::stream::with_coded_output_stream_to_bytes; -use crate::stream::CodedInputStream; -use crate::stream::CodedOutputStream; -use crate::stream::WithCodedInputStream; -use crate::stream::WithCodedOutputStream; use crate::unknown::UnknownFields; /// Trait implemented for all generated structs for protobuf messages. diff --git a/src/plugin.rs b/src/plugin.rs index 007378f..77e1666 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -1,4 +1,4 @@ -// This file is generated by rust-protobuf 2.22.0-pre. Do not edit +// This file is generated by rust-protobuf 2.22.0. Do not edit // @generated // https://github.com/rust-lang/rust-clippy/issues/702 @@ -6,7 +6,7 @@ #![allow(clippy::all)] #![allow(unused_attributes)] -#![rustfmt::skip] +#![cfg_attr(rustfmt, rustfmt::skip)] #![allow(box_pointers)] #![allow(dead_code)] @@ -10,6 +10,8 @@ use crate::chars::Chars; #[cfg(feature = "bytes")] use bytes::Bytes; +use crate::coded_input_stream::CodedInputStream; +use crate::coded_output_stream::CodedOutputStream; use crate::enums::ProtobufEnum; use crate::error::ProtobufError; use crate::error::ProtobufResult; @@ -18,19 +20,13 @@ use crate::message::*; use crate::repeated::RepeatedField; use crate::singular::SingularField; use crate::singular::SingularPtrField; -use crate::stream::wire_format; -use crate::stream::wire_format::WireType; -use crate::stream::wire_format::WireTypeFixed32; -use crate::stream::wire_format::WireTypeFixed64; -use crate::stream::wire_format::WireTypeLengthDelimited; -use crate::stream::wire_format::WireTypeVarint; -use crate::stream::CodedInputStream; -use crate::stream::CodedOutputStream; use crate::types::*; use crate::zigzag::*; pub use crate::lazy_v2::LazyV2; use crate::unknown::UnknownFields; +use crate::wire_format; +use crate::wire_format::WireType; /// Given `u64` value compute varint encoded length. pub fn compute_raw_varint64_size(value: u64) -> u32 { @@ -184,16 +180,16 @@ pub fn vec_packed_enum_size<E: ProtobufEnum>(field_number: u32, vec: &[E]) -> u3 /// Compute tag size. Size of tag does not depend on wire type. pub fn tag_size(field_number: u32) -> u32 { - wire_format::Tag::make(field_number, WireTypeFixed64) + wire_format::Tag::make(field_number, WireType::WireTypeFixed64) .value() .len_varint() } fn value_size_no_tag<T: ProtobufVarint>(value: T, wt: WireType) -> u32 { match wt { - WireTypeFixed64 => 8, - WireTypeFixed32 => 4, - WireTypeVarint => value.len_varint(), + WireType::WireTypeFixed64 => 8, + WireType::WireTypeFixed32 => 4, + WireType::WireTypeVarint => value.len_varint(), _ => panic!(), } } @@ -267,8 +263,8 @@ pub fn read_repeated_int32_into( target: &mut Vec<i32>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_repeated_packed_int32_into(target), - WireTypeVarint => { + WireType::WireTypeLengthDelimited => is.read_repeated_packed_int32_into(target), + WireType::WireTypeVarint => { target.push(is.read_int32()?); Ok(()) } @@ -283,8 +279,8 @@ pub fn read_repeated_int64_into( target: &mut Vec<i64>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_repeated_packed_int64_into(target), - WireTypeVarint => { + WireType::WireTypeLengthDelimited => is.read_repeated_packed_int64_into(target), + WireType::WireTypeVarint => { target.push(is.read_int64()?); Ok(()) } @@ -299,8 +295,8 @@ pub fn read_repeated_uint32_into( target: &mut Vec<u32>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_repeated_packed_uint32_into(target), - WireTypeVarint => { + WireType::WireTypeLengthDelimited => is.read_repeated_packed_uint32_into(target), + WireType::WireTypeVarint => { target.push(is.read_uint32()?); Ok(()) } @@ -315,8 +311,8 @@ pub fn read_repeated_uint64_into( target: &mut Vec<u64>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_repeated_packed_uint64_into(target), - WireTypeVarint => { + WireType::WireTypeLengthDelimited => is.read_repeated_packed_uint64_into(target), + WireType::WireTypeVarint => { target.push(is.read_uint64()?); Ok(()) } @@ -331,8 +327,8 @@ pub fn read_repeated_sint32_into( target: &mut Vec<i32>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_repeated_packed_sint32_into(target), - WireTypeVarint => { + WireType::WireTypeLengthDelimited => is.read_repeated_packed_sint32_into(target), + WireType::WireTypeVarint => { target.push(is.read_sint32()?); Ok(()) } @@ -347,8 +343,8 @@ pub fn read_repeated_sint64_into( target: &mut Vec<i64>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_repeated_packed_sint64_into(target), - WireTypeVarint => { + WireType::WireTypeLengthDelimited => is.read_repeated_packed_sint64_into(target), + WireType::WireTypeVarint => { target.push(is.read_sint64()?); Ok(()) } @@ -363,8 +359,8 @@ pub fn read_repeated_fixed32_into( target: &mut Vec<u32>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_repeated_packed_fixed32_into(target), - WireTypeFixed32 => { + WireType::WireTypeLengthDelimited => is.read_repeated_packed_fixed32_into(target), + WireType::WireTypeFixed32 => { target.push(is.read_fixed32()?); Ok(()) } @@ -379,8 +375,8 @@ pub fn read_repeated_fixed64_into( target: &mut Vec<u64>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_repeated_packed_fixed64_into(target), - WireTypeFixed64 => { + WireType::WireTypeLengthDelimited => is.read_repeated_packed_fixed64_into(target), + WireType::WireTypeFixed64 => { target.push(is.read_fixed64()?); Ok(()) } @@ -395,8 +391,8 @@ pub fn read_repeated_sfixed32_into( target: &mut Vec<i32>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_repeated_packed_sfixed32_into(target), - WireTypeFixed32 => { + WireType::WireTypeLengthDelimited => is.read_repeated_packed_sfixed32_into(target), + WireType::WireTypeFixed32 => { target.push(is.read_sfixed32()?); Ok(()) } @@ -411,8 +407,8 @@ pub fn read_repeated_sfixed64_into( target: &mut Vec<i64>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_repeated_packed_sfixed64_into(target), - WireTypeFixed64 => { + WireType::WireTypeLengthDelimited => is.read_repeated_packed_sfixed64_into(target), + WireType::WireTypeFixed64 => { target.push(is.read_sfixed64()?); Ok(()) } @@ -427,8 +423,8 @@ pub fn read_repeated_double_into( target: &mut Vec<f64>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_repeated_packed_double_into(target), - WireTypeFixed64 => { + WireType::WireTypeLengthDelimited => is.read_repeated_packed_double_into(target), + WireType::WireTypeFixed64 => { target.push(is.read_double()?); Ok(()) } @@ -443,8 +439,8 @@ pub fn read_repeated_float_into( target: &mut Vec<f32>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_repeated_packed_float_into(target), - WireTypeFixed32 => { + WireType::WireTypeLengthDelimited => is.read_repeated_packed_float_into(target), + WireType::WireTypeFixed32 => { target.push(is.read_float()?); Ok(()) } @@ -459,8 +455,8 @@ pub fn read_repeated_bool_into( target: &mut Vec<bool>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_repeated_packed_bool_into(target), - WireTypeVarint => { + WireType::WireTypeLengthDelimited => is.read_repeated_packed_bool_into(target), + WireType::WireTypeVarint => { target.push(is.read_bool()?); Ok(()) } @@ -476,8 +472,8 @@ pub fn read_repeated_enum_into<E: ProtobufEnum>( target: &mut Vec<E>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_repeated_packed_enum_into(target), - WireTypeVarint => { + WireType::WireTypeLengthDelimited => is.read_repeated_packed_enum_into(target), + WireType::WireTypeVarint => { target.push(is.read_enum()?); Ok(()) } @@ -533,13 +529,13 @@ pub fn read_repeated_enum_with_unknown_fields_into<E: ProtobufEnum>( unknown_fields: &mut UnknownFields, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => read_repeated_packed_enum_with_unknown_fields_into( + WireType::WireTypeLengthDelimited => read_repeated_packed_enum_with_unknown_fields_into( is, target, field_number, unknown_fields, ), - WireTypeVarint => { + WireType::WireTypeVarint => { read_enum_with_unknown_fields_into(is, |e| target.push(e), field_number, unknown_fields) } _ => Err(unexpected_wire_type(wire_type)), @@ -593,7 +589,7 @@ pub fn read_repeated_string_into( target: &mut RepeatedField<String>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => { + WireType::WireTypeLengthDelimited => { let tmp = target.push_default(); is.read_string_into(tmp) } @@ -609,7 +605,7 @@ pub fn read_repeated_carllerche_string_into( target: &mut Vec<Chars>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => { + WireType::WireTypeLengthDelimited => { target.push(is.read_carllerche_chars()?); Ok(()) } @@ -624,7 +620,7 @@ pub fn read_singular_string_into( target: &mut SingularField<String>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => { + WireType::WireTypeLengthDelimited => { let tmp = target.set_default(); is.read_string_into(tmp) } @@ -640,7 +636,7 @@ pub fn read_singular_carllerche_string_into( target: &mut Option<Chars>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => { + WireType::WireTypeLengthDelimited => { *target = Some(is.read_carllerche_chars()?); Ok(()) } @@ -655,7 +651,7 @@ pub fn read_singular_proto3_string_into( target: &mut String, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_string_into(target), + WireType::WireTypeLengthDelimited => is.read_string_into(target), _ => Err(unexpected_wire_type(wire_type)), } } @@ -668,7 +664,7 @@ pub fn read_singular_proto3_carllerche_string_into( target: &mut Chars, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => { + WireType::WireTypeLengthDelimited => { *target = is.read_carllerche_chars()?; Ok(()) } @@ -683,7 +679,7 @@ pub fn read_repeated_bytes_into( target: &mut RepeatedField<Vec<u8>>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => { + WireType::WireTypeLengthDelimited => { let tmp = target.push_default(); is.read_bytes_into(tmp) } @@ -699,7 +695,7 @@ pub fn read_repeated_carllerche_bytes_into( target: &mut Vec<Bytes>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => { + WireType::WireTypeLengthDelimited => { target.push(is.read_carllerche_bytes()?); Ok(()) } @@ -714,7 +710,7 @@ pub fn read_singular_bytes_into( target: &mut SingularField<Vec<u8>>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => { + WireType::WireTypeLengthDelimited => { let tmp = target.set_default(); is.read_bytes_into(tmp) } @@ -730,7 +726,7 @@ pub fn read_singular_carllerche_bytes_into( target: &mut Option<Bytes>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => { + WireType::WireTypeLengthDelimited => { *target = Some(is.read_carllerche_bytes()?); Ok(()) } @@ -745,7 +741,7 @@ pub fn read_singular_proto3_bytes_into( target: &mut Vec<u8>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => is.read_bytes_into(target), + WireType::WireTypeLengthDelimited => is.read_bytes_into(target), _ => Err(unexpected_wire_type(wire_type)), } } @@ -758,7 +754,7 @@ pub fn read_singular_proto3_carllerche_bytes_into( target: &mut Bytes, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => { + WireType::WireTypeLengthDelimited => { *target = is.read_carllerche_bytes()?; Ok(()) } @@ -773,7 +769,7 @@ pub fn read_repeated_message_into<M: Message + Default>( target: &mut RepeatedField<M>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => { + WireType::WireTypeLengthDelimited => { is.incr_recursion()?; let tmp = target.push_default(); let res = is.merge_message(tmp); @@ -791,7 +787,7 @@ pub fn read_singular_message_into<M: Message + Default>( target: &mut SingularPtrField<M>, ) -> ProtobufResult<()> { match wire_type { - WireTypeLengthDelimited => { + WireType::WireTypeLengthDelimited => { is.incr_recursion()?; let tmp = target.set_default(); let res = is.merge_message(tmp); diff --git a/src/rustproto.rs b/src/rustproto.rs index d4284e7..83854e4 100644 --- a/src/rustproto.rs +++ b/src/rustproto.rs @@ -1,4 +1,4 @@ -// This file is generated by rust-protobuf 2.22.0-pre. Do not edit +// This file is generated by rust-protobuf 2.22.0. Do not edit // @generated // https://github.com/rust-lang/rust-clippy/issues/702 @@ -6,7 +6,7 @@ #![allow(clippy::all)] #![allow(unused_attributes)] -#![rustfmt::skip] +#![cfg_attr(rustfmt, rustfmt::skip)] #![allow(box_pointers)] #![allow(dead_code)] diff --git a/src/types.rs b/src/types.rs index bcfdd8f..d9bbb10 100644 --- a/src/types.rs +++ b/src/types.rs @@ -8,13 +8,13 @@ use crate::chars::Chars; #[cfg(feature = "bytes")] use bytes::Bytes; +use crate::coded_input_stream::CodedInputStream; +use crate::coded_output_stream::CodedOutputStream; use crate::enums::ProtobufEnum; use crate::error::ProtobufResult; use crate::message::Message; use crate::reflect::ProtobufValue; use crate::rt; -use crate::stream::CodedInputStream; -use crate::stream::CodedOutputStream; use crate::unknown::UnknownValues; use crate::wire_format::WireType; use crate::zigzag::decode_zig_zag_32; diff --git a/src/unknown.rs b/src/unknown.rs index 241fb3c..fb0cf45 100644 --- a/src/unknown.rs +++ b/src/unknown.rs @@ -1,5 +1,5 @@ use crate::clear::Clear; -use crate::stream::wire_format; +use crate::wire_format; use crate::zigzag::encode_zig_zag_32; use crate::zigzag::encode_zig_zag_64; use std::collections::hash_map; diff --git a/src/well_known_types/any.rs b/src/well_known_types/any.rs index 397f9db..f306202 100644 --- a/src/well_known_types/any.rs +++ b/src/well_known_types/any.rs @@ -1,4 +1,4 @@ -// This file is generated by rust-protobuf 2.22.0-pre. Do not edit +// This file is generated by rust-protobuf 2.22.0. Do not edit // @generated // https://github.com/rust-lang/rust-clippy/issues/702 @@ -6,7 +6,7 @@ #![allow(clippy::all)] #![allow(unused_attributes)] -#![rustfmt::skip] +#![cfg_attr(rustfmt, rustfmt::skip)] #![allow(box_pointers)] #![allow(dead_code)] diff --git a/src/well_known_types/api.rs b/src/well_known_types/api.rs index cb71f3b..34798b4 100644 --- a/src/well_known_types/api.rs +++ b/src/well_known_types/api.rs @@ -1,4 +1,4 @@ -// This file is generated by rust-protobuf 2.22.0-pre. Do not edit +// This file is generated by rust-protobuf 2.22.0. Do not edit // @generated // https://github.com/rust-lang/rust-clippy/issues/702 @@ -6,7 +6,7 @@ #![allow(clippy::all)] #![allow(unused_attributes)] -#![rustfmt::skip] +#![cfg_attr(rustfmt, rustfmt::skip)] #![allow(box_pointers)] #![allow(dead_code)] diff --git a/src/well_known_types/duration.rs b/src/well_known_types/duration.rs index d810b14..ec82f78 100644 --- a/src/well_known_types/duration.rs +++ b/src/well_known_types/duration.rs @@ -1,4 +1,4 @@ -// This file is generated by rust-protobuf 2.22.0-pre. Do not edit +// This file is generated by rust-protobuf 2.22.0. Do not edit // @generated // https://github.com/rust-lang/rust-clippy/issues/702 @@ -6,7 +6,7 @@ #![allow(clippy::all)] #![allow(unused_attributes)] -#![rustfmt::skip] +#![cfg_attr(rustfmt, rustfmt::skip)] #![allow(box_pointers)] #![allow(dead_code)] diff --git a/src/well_known_types/empty.rs b/src/well_known_types/empty.rs index 2464f43..5c69487 100644 --- a/src/well_known_types/empty.rs +++ b/src/well_known_types/empty.rs @@ -1,4 +1,4 @@ -// This file is generated by rust-protobuf 2.22.0-pre. Do not edit +// This file is generated by rust-protobuf 2.22.0. Do not edit // @generated // https://github.com/rust-lang/rust-clippy/issues/702 @@ -6,7 +6,7 @@ #![allow(clippy::all)] #![allow(unused_attributes)] -#![rustfmt::skip] +#![cfg_attr(rustfmt, rustfmt::skip)] #![allow(box_pointers)] #![allow(dead_code)] diff --git a/src/well_known_types/field_mask.rs b/src/well_known_types/field_mask.rs index dc0ed10..9d1f8f6 100644 --- a/src/well_known_types/field_mask.rs +++ b/src/well_known_types/field_mask.rs @@ -1,4 +1,4 @@ -// This file is generated by rust-protobuf 2.22.0-pre. Do not edit +// This file is generated by rust-protobuf 2.22.0. Do not edit // @generated // https://github.com/rust-lang/rust-clippy/issues/702 @@ -6,7 +6,7 @@ #![allow(clippy::all)] #![allow(unused_attributes)] -#![rustfmt::skip] +#![cfg_attr(rustfmt, rustfmt::skip)] #![allow(box_pointers)] #![allow(dead_code)] diff --git a/src/well_known_types/source_context.rs b/src/well_known_types/source_context.rs index 2086b35..55c1ab4 100644 --- a/src/well_known_types/source_context.rs +++ b/src/well_known_types/source_context.rs @@ -1,4 +1,4 @@ -// This file is generated by rust-protobuf 2.22.0-pre. Do not edit +// This file is generated by rust-protobuf 2.22.0. Do not edit // @generated // https://github.com/rust-lang/rust-clippy/issues/702 @@ -6,7 +6,7 @@ #![allow(clippy::all)] #![allow(unused_attributes)] -#![rustfmt::skip] +#![cfg_attr(rustfmt, rustfmt::skip)] #![allow(box_pointers)] #![allow(dead_code)] diff --git a/src/well_known_types/struct_pb.rs b/src/well_known_types/struct_pb.rs index 613fef3..222d712 100644 --- a/src/well_known_types/struct_pb.rs +++ b/src/well_known_types/struct_pb.rs @@ -1,4 +1,4 @@ -// This file is generated by rust-protobuf 2.22.0-pre. Do not edit +// This file is generated by rust-protobuf 2.22.0. Do not edit // @generated // https://github.com/rust-lang/rust-clippy/issues/702 @@ -6,7 +6,7 @@ #![allow(clippy::all)] #![allow(unused_attributes)] -#![rustfmt::skip] +#![cfg_attr(rustfmt, rustfmt::skip)] #![allow(box_pointers)] #![allow(dead_code)] diff --git a/src/well_known_types/timestamp.rs b/src/well_known_types/timestamp.rs index 0d48c7e..d0f7903 100644 --- a/src/well_known_types/timestamp.rs +++ b/src/well_known_types/timestamp.rs @@ -1,4 +1,4 @@ -// This file is generated by rust-protobuf 2.22.0-pre. Do not edit +// This file is generated by rust-protobuf 2.22.0. Do not edit // @generated // https://github.com/rust-lang/rust-clippy/issues/702 @@ -6,7 +6,7 @@ #![allow(clippy::all)] #![allow(unused_attributes)] -#![rustfmt::skip] +#![cfg_attr(rustfmt, rustfmt::skip)] #![allow(box_pointers)] #![allow(dead_code)] diff --git a/src/well_known_types/type_pb.rs b/src/well_known_types/type_pb.rs index 88744ae..d6c06cc 100644 --- a/src/well_known_types/type_pb.rs +++ b/src/well_known_types/type_pb.rs @@ -1,4 +1,4 @@ -// This file is generated by rust-protobuf 2.22.0-pre. Do not edit +// This file is generated by rust-protobuf 2.22.0. Do not edit // @generated // https://github.com/rust-lang/rust-clippy/issues/702 @@ -6,7 +6,7 @@ #![allow(clippy::all)] #![allow(unused_attributes)] -#![rustfmt::skip] +#![cfg_attr(rustfmt, rustfmt::skip)] #![allow(box_pointers)] #![allow(dead_code)] diff --git a/src/well_known_types/wrappers.rs b/src/well_known_types/wrappers.rs index 76392a2..11edf4c 100644 --- a/src/well_known_types/wrappers.rs +++ b/src/well_known_types/wrappers.rs @@ -1,4 +1,4 @@ -// This file is generated by rust-protobuf 2.22.0-pre. Do not edit +// This file is generated by rust-protobuf 2.22.0. Do not edit // @generated // https://github.com/rust-lang/rust-clippy/issues/702 @@ -6,7 +6,7 @@ #![allow(clippy::all)] #![allow(unused_attributes)] -#![rustfmt::skip] +#![cfg_attr(rustfmt, rustfmt::skip)] #![allow(box_pointers)] #![allow(dead_code)] diff --git a/src/wire_format.rs b/src/wire_format.rs new file mode 100644 index 0000000..9f54af3 --- /dev/null +++ b/src/wire_format.rs @@ -0,0 +1,105 @@ +//! Serialization constants. + +// 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 + } +} |