use crate::encoding::read_varint;
use crate::encoding::zigzag;
use crate::message::Message;
use crate::Error;
use core::iter::FusedIterator;
use core::str;
#[derive(Debug)]
pub struct Field<'a> {
pub number: u64,
pub value: FieldValue<'a>,
}
#[derive(Debug)]
pub enum FieldValue<'a> {
Varint(Varint),
Fixed64(Fixed64),
LengthDelimited(LengthDelimited<'a>),
StartGroup,
EndGroup,
Fixed32(Fixed32),
}
impl<'a> FieldValue<'a> {
#[inline]
pub fn get_bool(&self) -> Result<bool, Error> {
match self {
FieldValue::Varint(f) => Ok(f.get_bool()),
_ => Err(Error),
}
}
#[inline]
pub fn get_enum(&self) -> Result<i32, Error> {
match self {
FieldValue::Varint(f) => Ok(f.get_enum()),
_ => Err(Error),
}
}
#[inline]
pub fn get_int32(&self) -> Result<i32, Error> {
match self {
FieldValue::Varint(f) => Ok(f.get_int32()),
_ => Err(Error),
}
}
#[inline]
pub fn get_int64(&self) -> Result<i64, Error> {
match self {
FieldValue::Varint(f) => Ok(f.get_int64()),
_ => Err(Error),
}
}
#[inline]
pub fn get_sint32(&self) -> Result<i32, Error> {
match self {
FieldValue::Varint(f) => Ok(f.get_sint32()),
_ => Err(Error),
}
}
#[inline]
pub fn get_sint64(&self) -> Result<i64, Error> {
match self {
FieldValue::Varint(f) => Ok(f.get_sint64()),
_ => Err(Error),
}
}
#[inline]
pub fn get_uint32(&self) -> Result<u32, Error> {
match self {
FieldValue::Varint(f) => Ok(f.get_uint32()),
_ => Err(Error),
}
}
#[inline]
pub fn get_uint64(&self) -> Result<u64, Error> {
match self {
FieldValue::Varint(f) => Ok(f.get_uint64()),
_ => Err(Error),
}
}
#[inline]
pub fn get_fixed64(&self) -> Result<u64, Error> {
match self {
FieldValue::Fixed64(f) => Ok(f.get_fixed64()),
_ => Err(Error),
}
}
#[inline]
pub fn get_sfixed64(&self) -> Result<i64, Error> {
match self {
FieldValue::Fixed64(f) => Ok(f.get_sfixed64()),
_ => Err(Error),
}
}
#[inline]
pub fn get_double(&self) -> Result<f64, Error> {
match self {
FieldValue::Fixed64(f) => Ok(f.get_double()),
_ => Err(Error),
}
}
#[inline]
pub fn get_bytes(&self) -> Result<&'a [u8], Error> {
match self {
FieldValue::LengthDelimited(f) => Ok(f.get_bytes()),
_ => Err(Error),
}
}
#[inline]
pub fn get_message(&self) -> Result<Message<'a>, Error> {
match self {
FieldValue::LengthDelimited(f) => Ok(f.get_message()),
_ => Err(Error),
}
}
#[inline]
pub fn get_string(&self) -> Result<&'a str, Error> {
match self {
FieldValue::LengthDelimited(f) => f.get_string(),
_ => Err(Error),
}
}
#[inline]
pub fn get_fixed32(&self) -> Result<u32, Error> {
match self {
FieldValue::Fixed32(f) => Ok(f.get_fixed32()),
_ => Err(Error),
}
}
#[inline]
pub fn get_sfixed32(&self) -> Result<i32, Error> {
match self {
FieldValue::Fixed32(f) => Ok(f.get_sfixed32()),
_ => Err(Error),
}
}
#[inline]
pub fn get_float(&self) -> Result<f32, Error> {
match self {
FieldValue::Fixed32(f) => Ok(f.get_float()),
_ => Err(Error),
}
}
#[inline]
pub fn get_repeated_bool(&self) -> Result<Repeated<bool, PackedBool<'a>>, Error> {
match self {
FieldValue::Varint(f) => Ok(Repeated::Value(Some(f.get_bool()))),
FieldValue::LengthDelimited(f) => Ok(Repeated::Packed(f.get_packed_bool())),
_ => Err(Error),
}
}
#[inline]
pub fn get_repeated_enum(&self) -> Result<Repeated<i32, PackedEnum<'a>>, Error> {
match self {
FieldValue::Varint(f) => Ok(Repeated::Value(Some(f.get_enum()))),
FieldValue::LengthDelimited(f) => Ok(Repeated::Packed(f.get_packed_enum())),
_ => Err(Error),
}
}
#[inline]
pub fn get_repeated_int32(&self) -> Result<Repeated<i32, PackedInt32<'a>>, Error> {
match self {
FieldValue::Varint(f) => Ok(Repeated::Value(Some(f.get_int32()))),
FieldValue::LengthDelimited(f) => Ok(Repeated::Packed(f.get_packed_int32())),
_ => Err(Error),
}
}
#[inline]
pub fn get_repeated_int64(&self) -> Result<Repeated<i64, PackedInt64<'a>>, Error> {
match self {
FieldValue::Varint(f) => Ok(Repeated::Value(Some(f.get_int64()))),
FieldValue::LengthDelimited(f) => Ok(Repeated::Packed(f.get_packed_int64())),
_ => Err(Error),
}
}
#[inline]
pub fn get_repeated_sint32(&self) -> Result<Repeated<i32, PackedSint32<'a>>, Error> {
match self {
FieldValue::Varint(f) => Ok(Repeated::Value(Some(f.get_sint32()))),
FieldValue::LengthDelimited(f) => Ok(Repeated::Packed(f.get_packed_sint32())),
_ => Err(Error),
}
}
#[inline]
pub fn get_repeated_sint64(&self) -> Result<Repeated<i64, PackedSint64<'a>>, Error> {
match self {
FieldValue::Varint(f) => Ok(Repeated::Value(Some(f.get_sint64()))),
FieldValue::LengthDelimited(f) => Ok(Repeated::Packed(f.get_packed_sint64())),
_ => Err(Error),
}
}
#[inline]
pub fn get_repeated_uint32(&self) -> Result<Repeated<u32, PackedUint32<'a>>, Error> {
match self {
FieldValue::Varint(f) => Ok(Repeated::Value(Some(f.get_uint32()))),
FieldValue::LengthDelimited(f) => Ok(Repeated::Packed(f.get_packed_uint32())),
_ => Err(Error),
}
}
#[inline]
pub fn get_repeated_uint64(&self) -> Result<Repeated<u64, PackedUint64<'a>>, Error> {
match self {
FieldValue::Varint(f) => Ok(Repeated::Value(Some(f.get_uint64()))),
FieldValue::LengthDelimited(f) => Ok(Repeated::Packed(f.get_packed_uint64())),
_ => Err(Error),
}
}
#[inline]
pub fn get_repeated_fixed64(&self) -> Result<Repeated<u64, PackedFixed64<'a>>, Error> {
match self {
FieldValue::Fixed64(f) => Ok(Repeated::Value(Some(f.get_fixed64()))),
FieldValue::LengthDelimited(f) => Ok(Repeated::Packed(f.get_packed_fixed64())),
_ => Err(Error),
}
}
#[inline]
pub fn get_repeated_sfixed64(&self) -> Result<Repeated<i64, PackedSfixed64<'a>>, Error> {
match self {
FieldValue::Fixed64(f) => Ok(Repeated::Value(Some(f.get_sfixed64()))),
FieldValue::LengthDelimited(f) => Ok(Repeated::Packed(f.get_packed_sfixed64())),
_ => Err(Error),
}
}
#[inline]
pub fn get_repeated_double(&self) -> Result<Repeated<f64, PackedDouble<'a>>, Error> {
match self {
FieldValue::Fixed64(f) => Ok(Repeated::Value(Some(f.get_double()))),
FieldValue::LengthDelimited(f) => Ok(Repeated::Packed(f.get_packed_double())),
_ => Err(Error),
}
}
#[inline]
pub fn get_repeated_fixed32(&self) -> Result<Repeated<u32, PackedFixed32<'a>>, Error> {
match self {
FieldValue::LengthDelimited(f) => Ok(Repeated::Packed(f.get_packed_fixed32())),
FieldValue::Fixed32(f) => Ok(Repeated::Value(Some(f.get_fixed32()))),
_ => Err(Error),
}
}
#[inline]
pub fn get_repeated_sfixed32(&self) -> Result<Repeated<i32, PackedSfixed32<'a>>, Error> {
match self {
FieldValue::LengthDelimited(f) => Ok(Repeated::Packed(f.get_packed_sfixed32())),
FieldValue::Fixed32(f) => Ok(Repeated::Value(Some(f.get_sfixed32()))),
_ => Err(Error),
}
}
#[inline]
pub fn get_repeated_float(&self) -> Result<Repeated<f32, PackedFloat<'a>>, Error> {
match self {
FieldValue::LengthDelimited(f) => Ok(Repeated::Packed(f.get_packed_float())),
FieldValue::Fixed32(f) => Ok(Repeated::Value(Some(f.get_float()))),
_ => Err(Error),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct Fixed32 {
pub(crate) bytes: [u8; 4],
}
impl Fixed32 {
#[inline]
pub fn get_fixed32(&self) -> u32 {
u32::from_le_bytes(self.bytes)
}
#[inline]
pub fn get_sfixed32(&self) -> i32 {
i32::from_le_bytes(self.bytes)
}
#[inline]
pub fn get_float(&self) -> f32 {
f32::from_le_bytes(self.bytes)
}
}
#[derive(Clone, Copy, Debug)]
pub struct Fixed64 {
pub(crate) bytes: [u8; 8],
}
impl Fixed64 {
#[inline]
pub fn get_fixed64(&self) -> u64 {
u64::from_le_bytes(self.bytes)
}
#[inline]
pub fn get_sfixed64(&self) -> i64 {
i64::from_le_bytes(self.bytes)
}
#[inline]
pub fn get_double(&self) -> f64 {
f64::from_le_bytes(self.bytes)
}
}
#[derive(Clone, Copy, Debug)]
pub struct LengthDelimited<'a> {
pub(crate) buf: &'a [u8],
}
impl<'a> LengthDelimited<'a> {
#[inline]
pub fn get_bytes(&self) -> &'a [u8] {
self.buf
}
#[inline]
pub fn get_message(&self) -> Message<'a> {
Message::new(self.buf)
}
#[inline]
pub fn get_string(&self) -> Result<&'a str, Error> {
str::from_utf8(self.buf).map_err(|_| Error)
}
#[inline]
pub fn get_packed_bool(&self) -> PackedBool<'a> {
PackedBool { buf: self.buf }
}
#[inline]
pub fn get_packed_enum(&self) -> PackedEnum<'a> {
PackedEnum { buf: self.buf }
}
#[inline]
pub fn get_packed_int32(&self) -> PackedInt32<'a> {
PackedInt32 { buf: self.buf }
}
#[inline]
pub fn get_packed_int64(&self) -> PackedInt64<'a> {
PackedInt64 { buf: self.buf }
}
#[inline]
pub fn get_packed_sint32(&self) -> PackedSint32<'a> {
PackedSint32 { buf: self.buf }
}
#[inline]
pub fn get_packed_sint64(&self) -> PackedSint64<'a> {
PackedSint64 { buf: self.buf }
}
#[inline]
pub fn get_packed_uint32(&self) -> PackedUint32<'a> {
PackedUint32 { buf: self.buf }
}
#[inline]
pub fn get_packed_uint64(&self) -> PackedUint64<'a> {
PackedUint64 { buf: self.buf }
}
#[inline]
pub fn get_packed_fixed64(&self) -> PackedFixed64<'a> {
PackedFixed64 { buf: self.buf }
}
#[inline]
pub fn get_packed_sfixed64(&self) -> PackedSfixed64<'a> {
PackedSfixed64 { buf: self.buf }
}
#[inline]
pub fn get_packed_double(&self) -> PackedDouble<'a> {
PackedDouble { buf: self.buf }
}
#[inline]
pub fn get_packed_fixed32(&self) -> PackedFixed32<'a> {
PackedFixed32 { buf: self.buf }
}
#[inline]
pub fn get_packed_sfixed32(&self) -> PackedSfixed32<'a> {
PackedSfixed32 { buf: self.buf }
}
#[inline]
pub fn get_packed_float(&self) -> PackedFloat<'a> {
PackedFloat { buf: self.buf }
}
}
#[derive(Clone, Copy, Debug)]
pub struct Varint {
pub(crate) value: u64,
}
impl Varint {
#[inline]
pub fn get_bool(&self) -> bool {
self.value != 0
}
#[inline]
pub fn get_enum(&self) -> i32 {
self.value as i32
}
#[inline]
pub fn get_int32(&self) -> i32 {
self.value as i32
}
#[inline]
pub fn get_int64(&self) -> i64 {
self.value as i64
}
#[inline]
pub fn get_sint32(&self) -> i32 {
zigzag::decode_32(self.value as u32)
}
#[inline]
pub fn get_sint64(&self) -> i64 {
zigzag::decode_64(self.value)
}
#[inline]
pub fn get_uint32(&self) -> u32 {
self.value as u32
}
#[inline]
pub fn get_uint64(&self) -> u64 {
self.value
}
}
macro_rules! impl_packed {
($(#[$meta:meta])* $name:ident, Varint, $get_fn:ident, $return_type:ty) => {
$(#[$meta])*
#[derive(Clone, Debug, Default)]
pub struct $name<'a> {
buf: &'a [u8],
}
impl<'a> Iterator for $name<'a> {
type Item = Result<$return_type, Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.buf.is_empty() {
return None;
}
match read_varint(self.buf) {
Ok((buf, value)) => {
self.buf = buf;
Some(Ok(Varint { value }.$get_fn()))
}
Err(e) => Some(Err(e)),
}
}
}
impl FusedIterator for $name<'_> {}
};
($(#[$meta:meta])* $name:ident, Fixed64, $get_fn:ident, $return_type:ty) => {
$(#[$meta])*
#[derive(Clone, Debug, Default)]
pub struct $name<'a> {
buf: &'a [u8],
}
impl<'a> Iterator for $name<'a> {
type Item = Result<$return_type, Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.buf.is_empty() {
return None;
}
if self.buf.len() < 8 {
return Some(Err(Error));
}
let bytes = self.buf[..8].try_into().unwrap();
self.buf = &self.buf[8..];
Some(Ok(Fixed64 { bytes }.$get_fn()))
}
}
impl FusedIterator for $name<'_> {}
};
($(#[$meta:meta])* $name:ident, Fixed32, $get_fn:ident, $return_type:ty) => {
$(#[$meta])*
#[derive(Clone, Debug, Default)]
pub struct $name<'a> {
buf: &'a [u8],
}
impl<'a> Iterator for $name<'a> {
type Item = Result<$return_type, Error>;
fn next(&mut self) -> Option<Self::Item> {
if self.buf.is_empty() {
return None;
}
if self.buf.len() < 4 {
return Some(Err(Error));
}
let bytes = self.buf[..4].try_into().unwrap();
self.buf = &self.buf[4..];
Some(Ok(Fixed32 { bytes }.$get_fn()))
}
}
impl FusedIterator for $name<'_> {}
};
}
impl_packed!(
PackedBool,
Varint,
get_bool,
bool
);
impl_packed!(
PackedEnum,
Varint,
get_enum,
i32
);
impl_packed!(
PackedInt32,
Varint,
get_int32,
i32
);
impl_packed!(
PackedInt64,
Varint,
get_int64,
i64
);
impl_packed!(
PackedSint32,
Varint,
get_sint32,
i32
);
impl_packed!(
PackedSint64,
Varint,
get_sint64,
i64
);
impl_packed!(
PackedUint32,
Varint,
get_uint32,
u32
);
impl_packed!(
PackedUint64,
Varint,
get_uint64,
u64
);
impl_packed!(
PackedFixed64,
Fixed64,
get_fixed64,
u64
);
impl_packed!(
PackedSfixed64,
Fixed64,
get_sfixed64,
i64
);
impl_packed!(
PackedDouble,
Fixed64,
get_double,
f64
);
impl_packed!(
PackedFixed32,
Fixed32,
get_fixed32,
u32
);
impl_packed!(
PackedSfixed32,
Fixed32,
get_sfixed32,
i32
);
impl_packed!(
PackedFloat,
Fixed32,
get_float,
f32
);
#[derive(Clone, Debug)]
pub enum Repeated<T, P> {
Packed(P),
Value(Option<T>),
}
impl<T, P> Iterator for Repeated<T, P>
where
P: Iterator<Item = Result<T, Error>>,
{
type Item = Result<T, Error>;
fn next(&mut self) -> Option<Self::Item> {
match self {
Repeated::Packed(p) => p.next(),
Repeated::Value(v) => v.take().map(Ok),
}
}
}
impl<T, P> FusedIterator for Repeated<T, P> where
P: Iterator<Item = Result<T, Error>> + FusedIterator
{
}
#[cfg(test)]
mod tests {
use super::{FieldValue, PackedInt32, Repeated, Varint};
use crate::message::Message;
#[test]
fn repeated_value() {
let mut iter = Repeated::<i32, PackedInt32>::Value(Some(137_i32));
assert_eq!(iter.next(), Some(Ok(137_i32)));
assert_eq!(iter.next(), None);
assert_eq!(iter.next(), None);
}
#[test]
fn varint() {
let message = Message::new(&b"\x08\x01"[..]);
let field = message.fields().next().unwrap().unwrap();
assert_eq!(field.number, 1);
assert!(matches!(
field.value,
FieldValue::Varint(Varint { value: 1 })
));
}
}