#![forbid(unsafe_code)]
use prost::alloc::{collections::BTreeMap, vec::Vec};
use crate::message::OxiMessage;
use crate::{wire, OxiProtoResult};
#[derive(Debug, Default, Clone)]
pub struct Extensions {
raw: BTreeMap<u32, Vec<u8>>,
}
impl Extensions {
pub fn new() -> Self {
Self {
raw: BTreeMap::new(),
}
}
pub fn is_empty(&self) -> bool {
self.raw.is_empty()
}
pub fn len(&self) -> usize {
self.raw.len()
}
pub fn has_extension(&self, field_number: u32) -> bool {
self.raw.contains_key(&field_number)
}
pub fn clear_extension(&mut self, field_number: u32) {
self.raw.remove(&field_number);
}
pub fn clear(&mut self) {
self.raw.clear();
}
pub fn get_extension<T: OxiMessage>(&self, field_number: u32) -> OxiProtoResult<Option<T>> {
match self.raw.get(&field_number) {
None => Ok(None),
Some(bytes) => {
let value = T::decode(bytes)?;
Ok(Some(value))
}
}
}
pub fn set_extension<T: OxiMessage>(
&mut self,
field_number: u32,
value: &T,
) -> OxiProtoResult<()> {
let bytes = value.encode_to_vec();
self.raw.insert(field_number, bytes);
Ok(())
}
pub fn merge_raw(
&mut self,
field_number: u32,
wire_type: wire::WireType,
buf: &mut wire::DecodeBuffer,
) -> OxiProtoResult<()> {
let bytes = match wire_type {
wire::WireType::Len => {
let payload = buf.read_length_delimited()?;
payload.to_vec()
}
wire::WireType::Varint => {
let value = buf.read_varint()?;
let mut tmp = Vec::new();
wire::encode_varint(value, &mut tmp);
tmp
}
wire::WireType::I32 => {
let value = buf.read_fixed32()?;
let mut tmp = Vec::new();
wire::encode_fixed32(value, &mut tmp);
tmp
}
wire::WireType::I64 => {
let value = buf.read_fixed64()?;
let mut tmp = Vec::new();
wire::encode_fixed64(value, &mut tmp);
tmp
}
wire::WireType::SGroup | wire::WireType::EGroup => {
buf.skip_field(wire_type)?;
return Ok(());
}
};
self.raw.insert(field_number, bytes);
Ok(())
}
pub fn encode_raw(&self, buf: &mut wire::EncodeBuffer) {
for (&field_number, bytes) in &self.raw {
let _ = buf.write_tag(field_number, wire::WireType::Len);
buf.write_length_delimited(bytes);
}
}
pub fn encoded_len(&self) -> usize {
self.raw
.iter()
.map(|(&field_number, bytes)| {
let tag_value = (u64::from(field_number) << 3) | 2u64; let tag_len = wire::varint::encoded_len_varint(tag_value);
tag_len + wire::encoded_len_length_delimited(bytes.len())
})
.sum()
}
}