use crate::{MessageId, Versioned};
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::any::type_name;
pub trait GroupHeader {
fn msg_id(&self) -> u16;
fn msg_ver(&self) -> u16;
}
pub trait UpgradeLatest: DeserializeOwned + Versioned {
fn upgrade_latest<Src>(src: &mut Src, header: Src::Header) -> Result<Self, Src::Error>
where
Src: DataSource;
}
pub trait DataSource {
type Error;
type Header: GroupHeader;
fn read_header(&mut self) -> Result<Self::Header, Self::Error>;
fn read_message<T>(&mut self, header: &Self::Header) -> Result<T, Self::Error>
where
T: DeserializeOwned;
fn unknown_message(&self, msg_id: u16) -> Self::Error {
panic!("unknown message id {}", msg_id);
}
fn unknown_version<T>(&self, ver: u16) -> Self::Error {
panic!("unknown version {} for {}", ver, type_name::<T>());
}
fn unexpected_message<T>(&self, msg_id: u16) -> Self::Error {
panic!(
"unexpected message id {} (expected {})",
msg_id,
type_name::<T>()
);
}
}
pub trait DataSourceExt: DataSource {
fn expect_message<T>(&mut self) -> Result<T, Self::Error>
where
T: MessageId + UpgradeLatest;
}
impl<Src> DataSourceExt for Src
where
Src: DataSource,
{
fn expect_message<T>(&mut self) -> Result<T, Src::Error>
where
Src: DataSource,
T: MessageId + UpgradeLatest,
{
let header: Src::Header = self.read_header()?;
if header.msg_id() == T::MSG_ID {
T::upgrade_latest(self, header)
} else {
Err(self.unexpected_message::<T>(header.msg_id()))
}
}
}
pub trait GroupDeserialize: Sized {
fn read_message<Src>(src: &mut Src) -> Result<Self, Src::Error>
where
Src: DataSource;
}
pub trait DataSink {
type Error;
fn write_message<T>(&mut self, msg: &T) -> Result<(), Self::Error>
where
T: Serialize + Versioned,
T::Base: MessageId;
}