Add support for protobuf map fields

Update the generator to detect map fields and use MapFieldIterator.
Implement MapFieldIterator in the runtime to handle key-value pair
extraction and add write_map_entry to ProtoBuilder. Add tests to
verify that map-bearing messages generate and compile correctly.
This commit is contained in:
2026-05-07 20:15:08 -07:00
parent 8395195ac1
commit a20eed7223
6 changed files with 167 additions and 16 deletions
+46 -1
View File
@@ -1,6 +1,33 @@
use std::fmt;
#[derive(Debug, PartialEq, Eq)]
pub struct MapFieldIterator<'a> {
inner: RepeatedFieldIterator<'a>,
}
impl<'a> MapFieldIterator<'a> {
pub fn new(inner: RepeatedFieldIterator<'a>) -> Self {
Self { inner }
}
}
impl<'a> Iterator for MapFieldIterator<'a> {
type Item = Result<(&'a [u8], &'a [u8])>;
fn next(&mut self) -> Option<Self::Item> {
match self.inner.next() {
Some(Ok((value, _wire_type))) => {
let accessor = ProtoAccessor::new(value).ok()?;
let (key_bytes, _) = accessor.get_value(1).ok()?;
let (val_bytes, _) = accessor.get_value(2).ok()?;
Some(Ok((key_bytes, val_bytes)))
}
Some(Err(e)) => Some(Err(e)),
None => None,
}
}
}
#[derive(Debug, PartialEq)]
pub enum RotoError {
UnexpectedEndOfBuffer,
InvalidVarint,
@@ -769,6 +796,24 @@ impl<'a> ProtoBuilder<'a> {
self.append_bytes(raw_bytes)
}
pub fn write_map_entry(
&mut self,
field_number: u32,
key_encoded: &[u8],
value_encoded: &[u8],
) -> Result<()> {
let entry_len = key_encoded.len() + value_encoded.len();
self.write_tag(field_number, WireType::LengthDelimited)?;
let mut len_buf = [0u8; 10];
let len_len = write_varint(entry_len as u64, &mut len_buf)?;
self.append_bytes(&len_buf[..len_len])?;
self.append_bytes(key_encoded)?;
self.append_bytes(value_encoded)?;
Ok(())
}
pub fn finish(self) -> Result<&'a mut [u8]> {
Ok(&mut self.buf[..self.pos])
}