use super::wire_type::WireType;
use prost::alloc::vec::Vec;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct UnknownField {
pub field_number: u32,
pub value: UnknownValue,
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum UnknownValue {
Varint(u64),
Fixed64(u64),
LengthDelimited(Vec<u8>),
Fixed32(u32),
Group(Vec<u8>),
}
impl UnknownValue {
pub fn wire_type(&self) -> WireType {
match self {
UnknownValue::Varint(_) => WireType::Varint,
UnknownValue::Fixed64(_) => WireType::I64,
UnknownValue::LengthDelimited(_) => WireType::Len,
UnknownValue::Fixed32(_) => WireType::I32,
UnknownValue::Group(_) => WireType::SGroup,
}
}
}
#[derive(Debug, Clone, Default, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct UnknownFields {
fields: Vec<UnknownField>,
}
impl UnknownFields {
pub fn new() -> Self {
Self { fields: Vec::new() }
}
pub fn push(&mut self, field: UnknownField) {
self.fields.push(field);
}
pub fn push_varint(&mut self, field_number: u32, value: u64) {
self.fields.push(UnknownField {
field_number,
value: UnknownValue::Varint(value),
});
}
pub fn push_fixed64(&mut self, field_number: u32, value: u64) {
self.fields.push(UnknownField {
field_number,
value: UnknownValue::Fixed64(value),
});
}
pub fn push_length_delimited(&mut self, field_number: u32, data: Vec<u8>) {
self.fields.push(UnknownField {
field_number,
value: UnknownValue::LengthDelimited(data),
});
}
pub fn push_fixed32(&mut self, field_number: u32, value: u32) {
self.fields.push(UnknownField {
field_number,
value: UnknownValue::Fixed32(value),
});
}
pub fn iter(&self) -> core::slice::Iter<'_, UnknownField> {
self.fields.iter()
}
pub fn is_empty(&self) -> bool {
self.fields.is_empty()
}
pub fn len(&self) -> usize {
self.fields.len()
}
pub fn get_field(&self, field_number: u32) -> Vec<&UnknownField> {
self.fields
.iter()
.filter(|f| f.field_number == field_number)
.collect()
}
pub fn clear(&mut self) {
self.fields.clear();
}
pub fn encoded_len(&self) -> usize {
self.fields
.iter()
.map(|f| {
let tag_val =
(u64::from(f.field_number) << 3) | u64::from(f.value.wire_type() as u32);
let tag_len = super::varint::encoded_len_varint(tag_val);
let val_len = match &f.value {
UnknownValue::Varint(v) => super::varint::encoded_len_varint(*v),
UnknownValue::Fixed64(_) => 8usize,
UnknownValue::LengthDelimited(d) => {
super::varint::encoded_len_varint(d.len() as u64) + d.len()
}
UnknownValue::Fixed32(_) => 4usize,
UnknownValue::Group(d) => d.len(),
};
tag_len + val_len
})
.sum()
}
pub fn encode_to(&self, buf: &mut super::buf::EncodeBuffer) {
for field in &self.fields {
let wt = field.value.wire_type();
if field.field_number == 0 {
continue;
}
if buf.write_tag(field.field_number, wt).is_err() {
continue;
}
match &field.value {
UnknownValue::Varint(v) => buf.write_varint(*v),
UnknownValue::Fixed64(v) => buf.write_fixed64(*v),
UnknownValue::LengthDelimited(data) => buf.write_length_delimited(data),
UnknownValue::Fixed32(v) => buf.write_fixed32(*v),
UnknownValue::Group(data) => buf.write_raw(data),
}
}
}
}
impl<'a> IntoIterator for &'a UnknownFields {
type Item = &'a UnknownField;
type IntoIter = core::slice::Iter<'a, UnknownField>;
fn into_iter(self) -> Self::IntoIter {
self.fields.iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
use prost::alloc::vec;
#[test]
fn unknown_fields_push_and_iter() {
let mut fields = UnknownFields::new();
assert!(fields.is_empty());
fields.push_varint(100, 42);
fields.push_fixed32(101, 0xDEAD);
fields.push_length_delimited(102, vec![1, 2, 3]);
fields.push_fixed64(103, 0xCAFE_BABE);
assert_eq!(fields.len(), 4);
assert!(!fields.is_empty());
let f100 = fields.get_field(100);
assert_eq!(f100.len(), 1);
assert_eq!(f100[0].value, UnknownValue::Varint(42));
}
#[test]
fn unknown_fields_multiple_same_number() {
let mut fields = UnknownFields::new();
fields.push_varint(1, 10);
fields.push_varint(1, 20);
fields.push_varint(1, 30);
let all_1 = fields.get_field(1);
assert_eq!(all_1.len(), 3);
}
#[test]
fn unknown_fields_clear() {
let mut fields = UnknownFields::new();
fields.push_varint(1, 42);
fields.clear();
assert!(fields.is_empty());
}
#[test]
fn unknown_value_wire_types() {
assert_eq!(UnknownValue::Varint(0).wire_type(), WireType::Varint);
assert_eq!(UnknownValue::Fixed64(0).wire_type(), WireType::I64);
assert_eq!(
UnknownValue::LengthDelimited(vec![]).wire_type(),
WireType::Len
);
assert_eq!(UnknownValue::Fixed32(0).wire_type(), WireType::I32);
assert_eq!(UnknownValue::Group(vec![]).wire_type(), WireType::SGroup);
}
#[test]
fn encode_round_trip() {
let mut fields = UnknownFields::new();
fields.push_varint(1, 42);
fields.push_fixed32(2, 100);
fields.push_length_delimited(3, vec![10, 20, 30]);
let mut enc = super::super::buf::EncodeBuffer::new();
fields.encode_to(&mut enc);
assert!(!enc.is_empty());
let mut dec = super::super::buf::DecodeBuffer::new(enc.as_bytes());
let tag1 = dec.read_tag().expect("tag1");
assert_eq!(tag1.field_number, 1);
assert_eq!(tag1.wire_type, WireType::Varint);
assert_eq!(dec.read_varint().expect("val1"), 42);
let tag2 = dec.read_tag().expect("tag2");
assert_eq!(tag2.field_number, 2);
assert_eq!(tag2.wire_type, WireType::I32);
assert_eq!(dec.read_fixed32().expect("val2"), 100);
let tag3 = dec.read_tag().expect("tag3");
assert_eq!(tag3.field_number, 3);
assert_eq!(tag3.wire_type, WireType::Len);
assert_eq!(dec.read_length_delimited().expect("val3"), &[10, 20, 30]);
assert!(dec.is_empty());
}
}