Skip to content

Instantly share code, notes, and snippets.

@muhamadazmy
Last active May 12, 2025 14:03
Show Gist options
  • Select an option

  • Save muhamadazmy/24576749bb516871fdc7665ce63d5369 to your computer and use it in GitHub Desktop.

Select an option

Save muhamadazmy/24576749bb516871fdc7665ce63d5369 to your computer and use it in GitHub Desktop.
Bilrost Custom Encoder
use std::ops::RangeInclusive;
use bilrost::{Message, OwnedMessage};
use bytes::Bytes;
#[derive(bilrost::Message)]
struct Container {
inner: Inner,
}
#[derive(bilrost::Message)]
struct ContainerVec {
inner: Vec<Inner>,
}
struct Inner {
range: RangeInclusive<u64>,
}
impl ::bilrost::encoding::Encoder<::bilrost::encoding::General> for Inner {
fn encode<B: bytes::BufMut + ?Sized>(
tag: u32,
value: &Self,
buf: &mut B,
tw: &mut ::bilrost::encoding::TagWriter,
) {
let value = InnerDto::from(value);
<InnerDto as ::bilrost::encoding::Encoder<::bilrost::encoding::General>>::encode(
tag, &value, buf, tw,
);
}
fn encoded_len(
tag: u32,
value: &Self,
tm: &mut impl ::bilrost::encoding::TagMeasurer,
) -> usize {
let value = InnerDto::from(value);
<InnerDto as ::bilrost::encoding::Encoder<::bilrost::encoding::General>>::encoded_len(
tag, &value, tm,
)
}
fn prepend_encode<B: ::bilrost::buf::ReverseBuf + ?Sized>(
tag: u32,
value: &Self,
buf: &mut B,
tw: &mut ::bilrost::encoding::TagRevWriter,
) {
let value = InnerDto::from(value);
<InnerDto as ::bilrost::encoding::Encoder<::bilrost::encoding::General>>::prepend_encode(
tag, &value, buf, tw,
);
}
}
impl ::bilrost::encoding::Decoder<::bilrost::encoding::General> for Inner {
fn decode<B: bytes::Buf + ?Sized>(
wire_type: ::bilrost::encoding::WireType,
value: &mut Self,
buf: ::bilrost::encoding::Capped<B>,
ctx: ::bilrost::encoding::DecodeContext,
) -> Result<(), ::bilrost::DecodeError> {
let mut dto = <InnerDto as ::bilrost::encoding::ForOverwrite>::for_overwrite();
<InnerDto as ::bilrost::encoding::Decoder<::bilrost::encoding::General>>::decode(
wire_type, &mut dto, buf, ctx,
)?;
*value = dto.into();
Ok(())
}
}
impl ::bilrost::encoding::EmptyState<::bilrost::encoding::General> for Inner {
fn clear(&mut self) {
*self = Inner::default()
}
fn empty() -> Self
where
Self: Sized,
{
Self::default()
}
fn is_empty(&self) -> bool {
*self.range.start() == 0 && *self.range.end() == 0
}
}
impl ::bilrost::encoding::ForOverwrite<::bilrost::encoding::General> for Inner {
fn for_overwrite() -> Self
where
Self: Sized,
{
Self::default()
}
}
impl Default for Inner {
fn default() -> Self {
Self { range: 0..=0 }
}
}
#[derive(Default, bilrost::Message)]
struct InnerDto {
range: (u64, u64),
}
impl From<&Inner> for InnerDto {
fn from(value: &Inner) -> Self {
Self {
range: (*value.range.start(), *value.range.end()),
}
}
}
impl From<InnerDto> for Inner {
fn from(value: InnerDto) -> Self {
Self {
range: value.range.0..=value.range.1,
}
}
}
fn main() {
let v = Container {
inner: Inner { range: 0..=10 },
};
let b = v.encode_to_vec();
let c = Container::decode(Bytes::from(b)).unwrap();
assert_eq!(c.inner.range, v.inner.range);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment