use crate::field::{Field, FieldValue};
use crate::tag::Tag;
use crate::varint::{DecodeOutcome, Varint};
use crate::wire_format::WireType;
use crate::{ProtobufError, Result};
use ::std::convert::AsRef;
use ::std::io::Read;
pub(crate) trait FieldValueReader<L> {
fn read_tag(&mut self) -> Result<Option<Tag>> {
match self.read_varint()? {
Some(varint) => Tag::from_encoded(varint).map(Some),
None => Ok(None),
}
}
fn read_varint(&mut self) -> Result<Option<Varint>>;
fn read_fixed<const N: usize>(&mut self) -> Result<[u8; N]>;
fn read_length_delimited(&mut self, length: usize) -> Result<L>;
}
pub(crate) fn parse_field<L, R>(reader: &mut R) -> Result<Option<Field<L>>>
where
R: FieldValueReader<L>,
{
let Some(tag) = reader.read_tag()? else {
return Ok(None);
};
let value = match tag.wire_type {
WireType::Varint => {
let varint = reader.read_varint()?.ok_or(ProtobufError::UnexpectedEof)?;
FieldValue::Varint(varint)
}
WireType::Int32 => {
let bytes = reader.read_fixed::<4>()?;
FieldValue::I32(bytes)
}
WireType::Int64 => {
let bytes = reader.read_fixed::<8>()?;
FieldValue::I64(bytes)
}
WireType::Len => {
let length_varint = reader.read_varint()?.ok_or(ProtobufError::UnexpectedEof)?;
let length = length_varint.try_to_uint32()? as usize;
let data = reader.read_length_delimited(length)?;
FieldValue::Len(data)
}
_ => {
return Err(ProtobufError::InvalidWireType {
value: tag.wire_type as u8,
});
}
};
Ok(Some(Field {
field_number: tag.field_number,
value,
}))
}
struct IteratorReader<'a, I>(&'a mut I)
where
I: Iterator<Item = u8>;
impl<'a, I> FieldValueReader<Vec<u8>> for IteratorReader<'a, I>
where
I: Iterator<Item = u8>,
{
fn read_varint(&mut self) -> Result<Option<Varint>> {
use crate::varint::IteratorExtVarint;
match self.0.read_varint_partial()? {
DecodeOutcome::Complete(v) => Ok(Some(v)),
DecodeOutcome::Empty => Ok(None),
DecodeOutcome::Incomplete(_) => Err(ProtobufError::UnexpectedEof),
}
}
fn read_fixed<const N: usize>(&mut self) -> Result<[u8; N]> {
let mut bytes = [0u8; N];
for byte in bytes.iter_mut() {
*byte = self.0.next().ok_or(ProtobufError::UnexpectedEof)?;
}
Ok(bytes)
}
fn read_length_delimited(&mut self, length: usize) -> Result<Vec<u8>> {
let mut data = Vec::with_capacity(length);
for _ in 0..length {
data.push(self.0.next().ok_or(ProtobufError::UnexpectedEof)?);
}
Ok(data)
}
}
pub struct ProtobufFieldIteratorFromBytes<I> {
iter: I,
}
impl<I> Iterator for ProtobufFieldIteratorFromBytes<I>
where
I: Iterator<Item = u8>,
{
type Item = Result<Field<Vec<u8>>>;
fn next(&mut self) -> Option<Self::Item> {
let mut reader = IteratorReader(&mut self.iter);
match parse_field(&mut reader) {
Ok(Some(field)) => Some(Ok(field)),
Ok(None) => None,
Err(err) => Some(Err(err)),
}
}
}
pub trait IteratorExtProtobuf {
fn protobuf_fields(self) -> ProtobufFieldIteratorFromBytes<Self>
where
Self: Sized;
}
impl<I> IteratorExtProtobuf for I
where
I: Iterator<Item = u8>,
{
fn protobuf_fields(self) -> ProtobufFieldIteratorFromBytes<Self>
where
Self: Sized,
{
ProtobufFieldIteratorFromBytes { iter: self }
}
}
struct TryIteratorReader<'a, I, E>(&'a mut I)
where
I: Iterator<Item = ::std::result::Result<u8, E>>,
E: Into<ProtobufError>;
impl<'a, I, E> FieldValueReader<Vec<u8>> for TryIteratorReader<'a, I, E>
where
I: Iterator<Item = ::std::result::Result<u8, E>>,
E: Into<ProtobufError>,
{
fn read_varint(&mut self) -> Result<Option<Varint>> {
use crate::varint::TryIteratorExtVarint;
match self.0.read_varint_partial()? {
DecodeOutcome::Complete(v) => Ok(Some(v)),
DecodeOutcome::Empty => Ok(None),
DecodeOutcome::Incomplete(_) => Err(ProtobufError::UnexpectedEof),
}
}
fn read_fixed<const N: usize>(&mut self) -> Result<[u8; N]> {
let mut bytes = [0u8; N];
for byte in bytes.iter_mut() {
*byte = self
.0
.next()
.ok_or(ProtobufError::UnexpectedEof)?
.map_err(Into::into)?;
}
Ok(bytes)
}
fn read_length_delimited(&mut self, length: usize) -> Result<Vec<u8>> {
let mut data = Vec::with_capacity(length);
for _ in 0..length {
data.push(
self.0
.next()
.ok_or(ProtobufError::UnexpectedEof)?
.map_err(Into::into)?,
);
}
Ok(data)
}
}
pub struct ProtobufFieldIteratorFromTryBytes<I> {
iter: I,
}
impl<I, E> Iterator for ProtobufFieldIteratorFromTryBytes<I>
where
I: Iterator<Item = ::std::result::Result<u8, E>>,
E: Into<ProtobufError>,
{
type Item = Result<Field<Vec<u8>>>;
fn next(&mut self) -> Option<Self::Item> {
let mut reader = TryIteratorReader(&mut self.iter);
match parse_field(&mut reader) {
Ok(Some(field)) => Some(Ok(field)),
Ok(None) => None,
Err(err) => Some(Err(err)),
}
}
}
pub trait TryIteratorExtProtobuf {
fn protobuf_fields(self) -> ProtobufFieldIteratorFromTryBytes<Self>
where
Self: Sized;
}
impl<I, E> TryIteratorExtProtobuf for I
where
I: Iterator<Item = ::std::result::Result<u8, E>>,
E: Into<ProtobufError>,
{
fn protobuf_fields(self) -> ProtobufFieldIteratorFromTryBytes<Self>
where
Self: Sized,
{
ProtobufFieldIteratorFromTryBytes { iter: self }
}
}
struct ReadReader<'a, R>(&'a mut R)
where
R: Read;
impl<'a, R> FieldValueReader<Vec<u8>> for ReadReader<'a, R>
where
R: Read,
{
fn read_varint(&mut self) -> Result<Option<Varint>> {
use crate::varint::ReadExtVarint;
self.0.read_varint()
}
fn read_fixed<const N: usize>(&mut self) -> Result<[u8; N]> {
let mut bytes = [0u8; N];
self.0.read_exact(&mut bytes)?;
Ok(bytes)
}
fn read_length_delimited(&mut self, length: usize) -> Result<Vec<u8>> {
let mut data = vec![0u8; length];
self.0.read_exact(&mut data)?;
Ok(data)
}
}
pub struct ProtobufFieldIterator<R> {
reader: R,
}
impl<R> Iterator for ProtobufFieldIterator<R>
where
R: Read,
{
type Item = Result<Field<Vec<u8>>>;
fn next(&mut self) -> Option<Self::Item> {
let mut reader = ReadReader(&mut self.reader);
match parse_field(&mut reader) {
Ok(Some(field)) => Some(Ok(field)),
Ok(None) => None,
Err(err) => Some(Err(err)),
}
}
}
pub trait ReadExtProtobuf {
fn read_protobuf_fields(self) -> ProtobufFieldIterator<Self>
where
Self: Sized;
}
impl<R> ReadExtProtobuf for R
where
R: Read,
{
fn read_protobuf_fields(self) -> ProtobufFieldIterator<Self>
where
Self: Sized,
{
ProtobufFieldIterator { reader: self }
}
}
pub(crate) struct SliceReader<'a, 'b> {
pub(crate) slice: &'b mut &'a [u8],
}
impl<'a, 'b> FieldValueReader<&'a [u8]> for SliceReader<'a, 'b> {
fn read_varint(&mut self) -> Result<Option<Varint>> {
use crate::varint::ReadExtVarint;
self.slice.read_varint()
}
fn read_fixed<const N: usize>(&mut self) -> Result<[u8; N]> {
let (bytes, remaining) = self
.slice
.split_first_chunk::<N>()
.ok_or(ProtobufError::UnexpectedEof)?;
*self.slice = remaining;
Ok(*bytes)
}
fn read_length_delimited(&mut self, length: usize) -> Result<&'a [u8]> {
let (value_slice, remaining) = self
.slice
.split_at_checked(length)
.ok_or(ProtobufError::UnexpectedEof)?;
*self.slice = remaining;
Ok(value_slice)
}
}
pub struct ProtobufFieldSliceIterator<'a> {
slice: &'a [u8],
}
impl<'a> Iterator for ProtobufFieldSliceIterator<'a> {
type Item = Result<Field<&'a [u8]>>;
fn next(&mut self) -> Option<Self::Item> {
let mut reader = SliceReader {
slice: &mut self.slice,
};
parse_field(&mut reader).transpose()
}
}
pub trait AsRefExtProtobuf: AsRef<[u8]> {
fn read_protobuf_fields(&self) -> ProtobufFieldSliceIterator<'_> {
ProtobufFieldSliceIterator {
slice: self.as_ref(),
}
}
}
impl<T> AsRefExtProtobuf for T where T: AsRef<[u8]> + ?Sized {}
#[cfg(test)]
mod tests {
use crate::field::FieldValue;
#[test]
fn test_as_ref_ext_read_varint_field() {
use super::AsRefExtProtobuf;
let reader = &[0x08, 0x96, 0x01][..];
let fields: Vec<_> = reader
.read_protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].field_number.as_u32(), 1);
match &fields[0].value {
FieldValue::Varint(varint) => {
assert_eq!(varint.to_uint64(), 150);
}
_ => panic!("Expected Varint field"),
}
}
#[test]
fn test_as_ref_ext_read_len_field() {
use super::AsRefExtProtobuf;
let reader = &[0x12, 0x03, 0x48, 0x65, 0x6c][..];
let fields: Vec<_> = reader
.read_protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
let field = &fields[0];
assert_eq!(field.field_number.as_u32(), 2);
match &field.value {
FieldValue::Len(data) => {
assert_eq!(&data[..], b"Hel");
}
_ => panic!("Expected Len field"),
}
}
#[test]
fn test_as_ref_ext_read_i32_field() {
use super::AsRefExtProtobuf;
let reader = &[0x15, 0x78, 0x56, 0x34, 0x12][..];
let fields: Vec<_> = reader
.read_protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
let field = &fields[0];
assert_eq!(field.field_number.as_u32(), 2);
match &field.value {
FieldValue::I32(bytes) => {
assert_eq!(*bytes, [0x78, 0x56, 0x34, 0x12]);
}
_ => panic!("Expected I32 field"),
}
}
#[test]
fn test_as_ref_ext_read_i64_field() {
use super::AsRefExtProtobuf;
let reader = &[0x19, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12][..];
let fields: Vec<_> = reader
.read_protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
let field = &fields[0];
assert_eq!(field.field_number.as_u32(), 3);
match &field.value {
FieldValue::I64(bytes) => {
assert_eq!(*bytes, [0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12]);
}
_ => panic!("Expected I64 field"),
}
}
#[test]
fn test_as_ref_ext_read_multiple_fields() {
use super::AsRefExtProtobuf;
let reader = &[
0x08, 0x96, 0x01, 0x12, 0x03, 0x48, 0x65, 0x6c, ][..];
let fields: Vec<_> = reader
.read_protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 2);
let field = &fields[0];
assert_eq!(field.field_number.as_u32(), 1);
match &field.value {
FieldValue::Varint(varint) => {
assert_eq!(varint.to_uint64(), 150);
}
_ => panic!("Expected Varint field"),
}
let field = &fields[1];
assert_eq!(field.field_number.as_u32(), 2);
match &field.value {
FieldValue::Len(data) => {
assert_eq!(&data[..], b"Hel");
}
_ => panic!("Expected Len field"),
}
}
#[test]
fn test_as_ref_ext_read_empty_stream() {
use super::AsRefExtProtobuf;
let reader = &[][..];
let fields: Vec<_> = reader
.read_protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 0);
}
#[test]
fn test_as_ref_ext_works_with_unsized_type() {
use super::AsRefExtProtobuf;
fn accepts_unsized<T: AsRefExtProtobuf + ?Sized>(x: &T) {
let _ = x.read_protobuf_fields();
}
let data = [0x08, 0x96, 0x01]; accepts_unsized(&data[..]);
let slice: &[u8] = &[0x08, 0x96, 0x01];
let fields: Vec<_> = slice
.read_protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].field_number.as_u32(), 1);
}
#[test]
fn test_read_ext_read_varint_field() {
use super::ReadExtProtobuf;
use ::std::io::Cursor;
let data = vec![0x08, 0x96, 0x01]; let reader = Cursor::new(data);
let fields: Vec<_> = reader
.read_protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].field_number.as_u32(), 1);
match &fields[0].value {
FieldValue::Varint(varint) => {
assert_eq!(varint.to_uint64(), 150);
}
_ => panic!("Expected Varint field"),
}
}
#[test]
fn test_read_ext_read_multiple_fields() {
use super::ReadExtProtobuf;
use ::std::io::Cursor;
let data = vec![
0x08, 0x96, 0x01, 0x12, 0x03, 0x48, 0x65, 0x6c, ];
let reader = Cursor::new(data);
let fields: Vec<_> = reader
.read_protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 2);
assert_eq!(fields[0].field_number.as_u32(), 1);
match &fields[0].value {
FieldValue::Varint(varint) => {
assert_eq!(varint.to_uint64(), 150);
}
_ => panic!("Expected Varint field"),
}
assert_eq!(fields[1].field_number.as_u32(), 2);
match &fields[1].value {
FieldValue::Len(data) => {
assert_eq!(&data[..], b"Hel");
}
_ => panic!("Expected Len field"),
}
}
#[test]
fn test_read_ext_read_i32_field() {
use super::ReadExtProtobuf;
use ::std::io::Cursor;
let data = vec![0x15, 0x78, 0x56, 0x34, 0x12]; let reader = Cursor::new(data);
let fields: Vec<_> = reader
.read_protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].field_number.as_u32(), 2);
match &fields[0].value {
FieldValue::I32(bytes) => {
assert_eq!(*bytes, [0x78, 0x56, 0x34, 0x12]);
}
_ => panic!("Expected I32 field"),
}
}
#[test]
fn test_read_ext_read_len_field() {
use super::ReadExtProtobuf;
use ::std::io::Cursor;
let data = vec![0x12, 0x03, 0x48, 0x65, 0x6c]; let reader = Cursor::new(data);
let fields: Vec<_> = reader
.read_protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].field_number.as_u32(), 2);
match &fields[0].value {
FieldValue::Len(data) => {
assert_eq!(&data[..], b"Hel");
}
_ => panic!("Expected Len field"),
}
}
#[test]
fn test_read_ext_read_i64_field() {
use super::ReadExtProtobuf;
use ::std::io::Cursor;
let data = vec![0x19, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12]; let reader = Cursor::new(data);
let fields: Vec<_> = reader
.read_protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].field_number.as_u32(), 3);
match &fields[0].value {
FieldValue::I64(bytes) => {
assert_eq!(*bytes, [0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12]);
}
_ => panic!("Expected I64 field"),
}
}
#[test]
fn test_read_ext_read_empty_stream() {
use super::ReadExtProtobuf;
use ::std::io::Cursor;
let data = vec![];
let reader = Cursor::new(data);
let fields: Vec<_> = reader
.read_protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 0);
}
#[test]
fn test_iterator_ext_read_varint_field() {
use super::IteratorExtProtobuf;
let bytes = vec![0x08, 0x96, 0x01]; let iter = bytes.into_iter();
let fields: Vec<_> = iter
.protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].field_number.as_u32(), 1);
match &fields[0].value {
FieldValue::Varint(varint) => {
assert_eq!(varint.to_uint64(), 150);
}
_ => panic!("Expected Varint field"),
}
}
#[test]
fn test_iterator_ext_read_multiple_fields() {
use super::IteratorExtProtobuf;
let bytes = vec![
0x08, 0x96, 0x01, 0x12, 0x03, 0x48, 0x65, 0x6c, ];
let iter = bytes.into_iter();
let fields: Vec<_> = iter
.protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 2);
assert_eq!(fields[0].field_number.as_u32(), 1);
match &fields[0].value {
FieldValue::Varint(varint) => {
assert_eq!(varint.to_uint64(), 150);
}
_ => panic!("Expected Varint field"),
}
assert_eq!(fields[1].field_number.as_u32(), 2);
match &fields[1].value {
FieldValue::Len(data) => {
assert_eq!(&data[..], b"Hel");
}
_ => panic!("Expected Len field"),
}
}
#[test]
fn test_iterator_ext_read_len_field() {
use super::IteratorExtProtobuf;
let bytes = vec![0x12, 0x03, 0x48, 0x65, 0x6c]; let iter = bytes.into_iter();
let fields: Vec<_> = iter
.protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].field_number.as_u32(), 2);
match &fields[0].value {
FieldValue::Len(data) => {
assert_eq!(&data[..], b"Hel");
}
_ => panic!("Expected Len field"),
}
}
#[test]
fn test_iterator_ext_read_i32_field() {
use super::IteratorExtProtobuf;
let bytes = vec![0x15, 0x78, 0x56, 0x34, 0x12]; let iter = bytes.into_iter();
let fields: Vec<_> = iter
.protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].field_number.as_u32(), 2);
match &fields[0].value {
FieldValue::I32(bytes) => {
assert_eq!(*bytes, [0x78, 0x56, 0x34, 0x12]);
}
_ => panic!("Expected I32 field"),
}
}
#[test]
fn test_iterator_ext_read_i64_field() {
use super::IteratorExtProtobuf;
let bytes = vec![0x19, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12]; let iter = bytes.into_iter();
let fields: Vec<_> = iter
.protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].field_number.as_u32(), 3);
match &fields[0].value {
FieldValue::I64(bytes) => {
assert_eq!(*bytes, [0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12]);
}
_ => panic!("Expected I64 field"),
}
}
#[test]
fn test_iterator_ext_read_empty_stream() {
use super::IteratorExtProtobuf;
let bytes = vec![];
let iter = bytes.into_iter();
let fields: Vec<_> = iter
.protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 0);
}
#[test]
fn test_try_iterator_ext_read_varint_field() {
use super::TryIteratorExtProtobuf;
use ::std::io::{Cursor, Read};
let data = vec![0x08, 0x96, 0x01]; let reader = Cursor::new(data);
let iter = reader.bytes();
let fields: Vec<_> = iter
.protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].field_number.as_u32(), 1);
match &fields[0].value {
FieldValue::Varint(varint) => {
assert_eq!(varint.to_uint64(), 150);
}
_ => panic!("Expected Varint field"),
}
}
#[test]
fn test_try_iterator_ext_read_multiple_fields() {
use super::TryIteratorExtProtobuf;
use ::std::io::{Cursor, Read};
let data = vec![
0x08, 0x96, 0x01, 0x12, 0x03, 0x48, 0x65, 0x6c, ];
let reader = Cursor::new(data);
let iter = reader.bytes();
let fields: Vec<_> = iter
.protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 2);
assert_eq!(fields[0].field_number.as_u32(), 1);
match &fields[0].value {
FieldValue::Varint(varint) => {
assert_eq!(varint.to_uint64(), 150);
}
_ => panic!("Expected Varint field"),
}
assert_eq!(fields[1].field_number.as_u32(), 2);
match &fields[1].value {
FieldValue::Len(data) => {
assert_eq!(&data[..], b"Hel");
}
_ => panic!("Expected Len field"),
}
}
#[test]
fn test_try_iterator_ext_read_len_field() {
use super::TryIteratorExtProtobuf;
use ::std::io::{Cursor, Read};
let data = vec![0x12, 0x03, 0x48, 0x65, 0x6c]; let reader = Cursor::new(data);
let iter = reader.bytes();
let fields: Vec<_> = iter
.protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].field_number.as_u32(), 2);
match &fields[0].value {
FieldValue::Len(data) => {
assert_eq!(&data[..], b"Hel");
}
_ => panic!("Expected Len field"),
}
}
#[test]
fn test_try_iterator_ext_read_i32_field() {
use super::TryIteratorExtProtobuf;
use ::std::io::{Cursor, Read};
let data = vec![0x15, 0x78, 0x56, 0x34, 0x12]; let reader = Cursor::new(data);
let iter = reader.bytes();
let fields: Vec<_> = iter
.protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].field_number.as_u32(), 2);
match &fields[0].value {
FieldValue::I32(bytes) => {
assert_eq!(*bytes, [0x78, 0x56, 0x34, 0x12]);
}
_ => panic!("Expected I32 field"),
}
}
#[test]
fn test_try_iterator_ext_read_i64_field() {
use super::TryIteratorExtProtobuf;
use ::std::io::{Cursor, Read};
let data = vec![0x19, 0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12]; let reader = Cursor::new(data);
let iter = reader.bytes();
let fields: Vec<_> = iter
.protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 1);
assert_eq!(fields[0].field_number.as_u32(), 3);
match &fields[0].value {
FieldValue::I64(bytes) => {
assert_eq!(*bytes, [0xEF, 0xCD, 0xAB, 0x90, 0x78, 0x56, 0x34, 0x12]);
}
_ => panic!("Expected I64 field"),
}
}
#[test]
fn test_try_iterator_ext_read_empty_stream() {
use super::TryIteratorExtProtobuf;
use ::std::io::{Cursor, Read};
let data = vec![];
let reader = Cursor::new(data);
let iter = reader.bytes();
let fields: Vec<_> = iter
.protobuf_fields()
.collect::<::std::result::Result<Vec<_>, _>>()
.unwrap();
assert_eq!(fields.len(), 0);
}
}