use paste::paste;
use crate::{Header, IntoVarInt, VarInt, WireType};
macro_rules! h {
($field:ident, $t:expr) => {
Header::new($field, $t).to_bytes()
};
}
macro_rules! impl_encode {
($($t:tt),*) => {
$(
paste! {
fn [<write_ $t>](&mut self, field: u32, value: $t) {
self.extend(h!(field, WireType::VarInt));
self.extend(value.into_varint());
}
}
)*
};
}
pub trait ProtobufBytes {
fn write_bytes(&mut self, field: u32, value: &[u8]);
fn write_str(&mut self, field: u32, value: &str);
fn write_u32(&mut self, field: u32, value: u32);
fn write_u64(&mut self, field: u32, value: u64);
fn write_i32(&mut self, field: u32, value: i32);
fn write_i64(&mut self, field: u32, value: i64);
fn write_f32(&mut self, field: u32, value: f32);
fn write_f64(&mut self, field: u32, value: f64);
}
impl ProtobufBytes for Vec<u8> {
fn write_bytes(&mut self, field: u32, value: &[u8]) {
self.extend(h!(field, WireType::LengthDelimited));
self.extend(VarInt::encode(value.len() as i32));
self.extend(value);
}
fn write_str(&mut self, field: u32, value: &str) {
self.write_bytes(field, value.as_bytes());
}
impl_encode!(i32, i64, u32, u64);
fn write_f32(&mut self, field: u32, value: f32) {
self.extend(h!(field, WireType::Fixed32));
self.extend(value.to_le_bytes());
}
fn write_f64(&mut self, field: u32, value: f64) {
self.extend(h!(field, WireType::Fixed64));
self.extend(value.to_le_bytes());
}
}