use crate::inplace::InplaceOption;
use crate::protobuf::FieldReader;
use crate::protobuf::MessageReader;
use crate::protobuf::MessageSizer;
use crate::protobuf::MessageWriter;
use crate::protofile::DescribeField;
use crate::protofile::DescribeMessage;
use crate::protofile::FieldType;
use crate::protofile::MessageDescription;
use crate::Error;
use crate::FieldDecode;
use crate::FieldEncode;
use crate::MessageDecode;
use crate::MessageEncode;
use crate::Result;
use crate::ResultExt;
use thiserror::Error;
pub struct OneofEncoder;
#[derive(Debug, Error)]
#[error("missing enum variant")]
struct UnassignedEnum;
pub trait OneofEncode<R> {
fn write_variant(self, writer: MessageWriter<'_, '_, R>);
fn compute_variant_size(&mut self, sizer: MessageSizer<'_>);
}
pub trait DescribeOneof {
const DESCRIPTION: MessageDescription<'static>;
}
impl<T: DescribeOneof> DescribeMessage<T> for OneofEncoder {
const DESCRIPTION: MessageDescription<'static> = T::DESCRIPTION;
}
impl<T: DescribeOneof> DescribeField<T> for OneofEncoder {
const FIELD_TYPE: FieldType<'static> = FieldType::message(|| T::DESCRIPTION);
}
impl<T: OneofEncode<R>, R> MessageEncode<T, R> for OneofEncoder {
fn write_message(item: T, writer: MessageWriter<'_, '_, R>) {
item.write_variant(writer)
}
fn compute_message_size(item: &mut T, sizer: MessageSizer<'_>) {
item.compute_variant_size(sizer)
}
}
impl<T: OneofEncode<R>, R> FieldEncode<T, R> for OneofEncoder {
fn write_field(item: T, writer: crate::protobuf::FieldWriter<'_, '_, R>) {
writer.message(|writer| item.write_variant(writer))
}
fn compute_field_size(item: &mut T, sizer: crate::protobuf::FieldSizer<'_>) {
sizer.message(|sizer| item.compute_variant_size(sizer))
}
}
pub trait OneofDecode<'de, R>: Sized {
fn read_variant(
this: &mut InplaceOption<'_, Self>,
number: u32,
reader: FieldReader<'de, '_, R>,
) -> Result<()>;
}
impl<'de, T: OneofDecode<'de, R>, R> MessageDecode<'de, T, R> for OneofEncoder {
fn read_message(
item: &mut InplaceOption<'_, T>,
reader: MessageReader<'de, '_, R>,
) -> Result<()> {
for field in reader {
let (n, field) = field.typed::<T>()?;
T::read_variant(item, n, field)?;
}
if item.is_none() {
return Err(Error::new(UnassignedEnum).typed::<T>());
}
Ok(())
}
}
impl<'de, T: OneofDecode<'de, R>, R> FieldDecode<'de, T, R> for OneofEncoder {
fn read_field(item: &mut InplaceOption<'_, T>, reader: FieldReader<'de, '_, R>) -> Result<()> {
Self::read_message(item, reader.message()?)
}
fn default_field(_item: &mut InplaceOption<'_, T>) -> Result<()> {
Err(Error::new(UnassignedEnum).typed::<T>())
}
}