use alloc::vec::Vec;
use bytes::BufMut;
#[derive(Clone, Debug, Default, PartialEq, Hash)]
pub struct UnknownFields {
fields: Vec<UnknownField>,
}
impl UnknownFields {
pub fn new() -> Self {
Self::default()
}
pub fn is_empty(&self) -> bool {
self.fields.is_empty()
}
pub fn len(&self) -> usize {
self.fields.len()
}
pub fn push(&mut self, field: UnknownField) {
self.fields.push(field);
}
pub fn iter(&self) -> core::slice::Iter<'_, UnknownField> {
self.fields.iter()
}
pub fn clear(&mut self) {
self.fields.clear();
}
pub fn retain(&mut self, f: impl FnMut(&UnknownField) -> bool) {
self.fields.retain(f);
}
pub fn encoded_len(&self) -> usize {
self.fields.iter().map(|f| f.encoded_len()).sum()
}
pub fn write_to(&self, buf: &mut impl BufMut) {
for field in &self.fields {
field.write_to(buf);
}
}
pub fn decode_from_slice(mut data: &[u8]) -> Result<Self, crate::DecodeError> {
use crate::encoding::{decode_unknown_field, Tag};
use crate::message::RECURSION_LIMIT;
let mut out = Self::new();
while !data.is_empty() {
let tag = Tag::decode(&mut data)?;
out.push(decode_unknown_field(tag, &mut data, RECURSION_LIMIT)?);
}
Ok(out)
}
}
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()
}
}
impl IntoIterator for UnknownFields {
type Item = UnknownField;
type IntoIter = alloc::vec::IntoIter<UnknownField>;
fn into_iter(self) -> Self::IntoIter {
self.fields.into_iter()
}
}
#[derive(Clone, Debug, PartialEq, Hash)]
pub struct UnknownField {
pub number: u32,
pub data: UnknownFieldData,
}
impl UnknownField {
pub fn encoded_len(&self) -> usize {
let tag_len =
crate::encoding::varint_len(((self.number as u64) << 3) | self.data.wire_type_value());
tag_len + self.data.encoded_len(self.number)
}
pub fn write_to(&self, buf: &mut impl BufMut) {
use crate::encoding::encode_varint;
let tag_value = ((self.number as u64) << 3) | self.data.wire_type_value();
encode_varint(tag_value, buf);
match &self.data {
UnknownFieldData::Varint(v) => encode_varint(*v, buf),
UnknownFieldData::Fixed64(v) => buf.put_u64_le(*v),
UnknownFieldData::Fixed32(v) => buf.put_u32_le(*v),
UnknownFieldData::LengthDelimited(data) => {
encode_varint(data.len() as u64, buf);
buf.put_slice(data);
}
UnknownFieldData::Group(fields) => {
fields.write_to(buf);
encode_varint(((self.number as u64) << 3) | 4, buf);
}
}
}
}
#[derive(Clone, Debug, PartialEq, Hash)]
pub enum UnknownFieldData {
Varint(u64),
Fixed64(u64),
Fixed32(u32),
LengthDelimited(Vec<u8>),
Group(UnknownFields),
}
impl UnknownFieldData {
fn wire_type_value(&self) -> u64 {
match self {
Self::Varint(_) => 0,
Self::Fixed64(_) => 1,
Self::LengthDelimited(_) => 2,
Self::Group(_) => 3,
Self::Fixed32(_) => 5,
}
}
fn encoded_len(&self, field_number: u32) -> usize {
match self {
Self::Varint(v) => crate::encoding::varint_len(*v),
Self::Fixed64(_) => 8,
Self::Fixed32(_) => 4,
Self::LengthDelimited(data) => {
crate::encoding::varint_len(data.len() as u64) + data.len()
}
Self::Group(fields) => {
let end_tag_len = crate::encoding::varint_len((field_number as u64) << 3 | 4);
fields.encoded_len() + end_tag_len
}
}
}
}
#[cfg(feature = "arbitrary")]
impl<'a> arbitrary::Arbitrary<'a> for UnknownFields {
fn arbitrary(_u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
Ok(UnknownFields::new())
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::encoding::MAX_FIELD_NUMBER;
fn varint_field(number: u32, value: u64) -> UnknownField {
UnknownField {
number,
data: UnknownFieldData::Varint(value),
}
}
fn fixed32_field(number: u32, value: u32) -> UnknownField {
UnknownField {
number,
data: UnknownFieldData::Fixed32(value),
}
}
fn fixed64_field(number: u32, value: u64) -> UnknownField {
UnknownField {
number,
data: UnknownFieldData::Fixed64(value),
}
}
fn ld_field(number: u32, data: Vec<u8>) -> UnknownField {
UnknownField {
number,
data: UnknownFieldData::LengthDelimited(data),
}
}
fn group_field(number: u32, fields: UnknownFields) -> UnknownField {
UnknownField {
number,
data: UnknownFieldData::Group(fields),
}
}
#[test]
fn test_empty_encoded_len() {
assert_eq!(UnknownFields::new().encoded_len(), 0);
}
#[test]
fn test_varint_encoded_len() {
assert_eq!(varint_field(1, 0).encoded_len(), 2);
assert_eq!(varint_field(1, 128).encoded_len(), 3);
}
#[test]
fn test_fixed32_encoded_len() {
assert_eq!(fixed32_field(1, 0xDEAD_BEEF).encoded_len(), 5);
}
#[test]
fn test_fixed64_encoded_len() {
assert_eq!(fixed64_field(1, 0xDEAD_BEEF_CAFE_BABE).encoded_len(), 9);
}
#[test]
fn test_length_delimited_encoded_len() {
assert_eq!(ld_field(1, vec![0xAA, 0xBB, 0xCC]).encoded_len(), 5);
assert_eq!(ld_field(1, vec![]).encoded_len(), 2);
assert_eq!(ld_field(1, vec![0u8; 128]).encoded_len(), 131);
}
#[test]
fn test_group_encoded_len() {
assert_eq!(group_field(1, UnknownFields::new()).encoded_len(), 2);
let mut inner = UnknownFields::new();
inner.push(varint_field(1, 0));
assert_eq!(group_field(1, inner).encoded_len(), 4);
}
#[test]
fn test_large_field_number_two_byte_tag() {
assert_eq!(varint_field(16, 0).encoded_len(), 3);
}
#[test]
fn test_multiple_fields_sum() {
let mut fields = UnknownFields::new();
fields.push(varint_field(1, 0)); fields.push(fixed32_field(2, 0)); assert_eq!(fields.encoded_len(), 7);
}
#[test]
fn test_into_iter_by_ref() {
let mut fields = UnknownFields::new();
fields.push(varint_field(1, 0));
fields.push(varint_field(2, 0));
let numbers: Vec<u32> = (&fields).into_iter().map(|f| f.number).collect();
assert_eq!(numbers, vec![1, 2]);
let mut count = 0;
for _ in &fields {
count += 1;
}
assert_eq!(count, 2);
}
fn assert_len_matches_write(f: UnknownField) {
let mut fields = UnknownFields::new();
let claimed = f.encoded_len();
fields.push(f);
let mut buf = alloc::vec::Vec::new();
fields.write_to(&mut buf);
assert_eq!(
buf.len(),
claimed,
"encoded_len={claimed} but wrote {} bytes for {fields:?}",
buf.len()
);
}
#[test]
fn test_encoded_len_matches_write_varint() {
for &num in &[1, 15, 16, 2047, 2048, MAX_FIELD_NUMBER] {
for &val in &[0, 1, 127, 128, u32::MAX as u64, u64::MAX] {
assert_len_matches_write(varint_field(num, val));
}
}
}
#[test]
fn test_encoded_len_matches_write_fixed() {
for &num in &[1, 16, MAX_FIELD_NUMBER] {
assert_len_matches_write(fixed32_field(num, 0));
assert_len_matches_write(fixed32_field(num, u32::MAX));
assert_len_matches_write(fixed64_field(num, 0));
assert_len_matches_write(fixed64_field(num, u64::MAX));
}
}
#[test]
fn test_encoded_len_matches_write_length_delimited() {
for &num in &[1, 16, MAX_FIELD_NUMBER] {
assert_len_matches_write(ld_field(num, alloc::vec![]));
assert_len_matches_write(ld_field(num, alloc::vec![0xAB]));
assert_len_matches_write(ld_field(num, alloc::vec![0; 127]));
assert_len_matches_write(ld_field(num, alloc::vec![0; 128]));
}
}
#[test]
fn test_encoded_len_matches_write_group() {
for &num in &[1, 16, MAX_FIELD_NUMBER] {
assert_len_matches_write(group_field(num, UnknownFields::new()));
let mut inner = UnknownFields::new();
inner.push(varint_field(2, 42));
inner.push(ld_field(3, alloc::vec![1, 2, 3]));
assert_len_matches_write(group_field(num, inner.clone()));
let mut inner2 = UnknownFields::new();
inner2.push(group_field(4, inner));
assert_len_matches_write(group_field(num, inner2));
}
}
#[test]
fn test_encoded_len_matches_write_multi_field() {
let mut fields = UnknownFields::new();
fields.push(varint_field(1, 42));
fields.push(fixed32_field(2, 0xDEADBEEF));
fields.push(fixed64_field(3, u64::MAX));
fields.push(ld_field(4, alloc::vec![1, 2, 3, 4, 5]));
let mut nested = UnknownFields::new();
nested.push(varint_field(10, 7));
fields.push(group_field(5, nested));
let claimed = fields.encoded_len();
let mut buf = alloc::vec::Vec::new();
fields.write_to(&mut buf);
assert_eq!(buf.len(), claimed);
}
#[test]
fn test_decode_from_slice_empty() {
let out = UnknownFields::decode_from_slice(&[]).unwrap();
assert!(out.is_empty());
}
#[test]
fn test_decode_from_slice_roundtrip() {
let mut orig = UnknownFields::new();
orig.push(varint_field(1, 42));
orig.push(fixed32_field(2, 0xDEAD_BEEF));
orig.push(fixed64_field(3, u64::MAX));
orig.push(ld_field(4, vec![1, 2, 3]));
let mut nested = UnknownFields::new();
nested.push(varint_field(10, 7));
orig.push(group_field(5, nested));
let mut buf = Vec::new();
orig.write_to(&mut buf);
let decoded = UnknownFields::decode_from_slice(&buf).unwrap();
assert_eq!(decoded, orig);
}
#[test]
fn test_decode_from_slice_truncated() {
assert!(UnknownFields::decode_from_slice(&[0x08]).is_err());
}
}