use std::sync::Arc;
use microsandbox_protocol::wire::Envelope;
use crate::{
BoxFuture, BoxTransport, ClientError, ClientLimits, ClientResult, ConnectOptions, ErrorKind,
Message,
};
pub trait Protocol: Send + Sync + 'static {
const REUSE_IDS: bool = true;
type Ready: Send + Sync + 'static;
fn establish(
stream: BoxTransport,
options: ConnectOptions,
) -> BoxFuture<'static, ClientResult<Established<Self::Ready>>>;
fn prepare(ready: &Self::Ready, wire_name: &str) -> ClientResult<SendMetadata>;
}
pub trait EnvelopeCodec: Send + Sync + 'static {
fn encode(&self, generation: u8, wire_name: &str, payload: Vec<u8>) -> ClientResult<Vec<u8>>;
fn decode(&self, frame: crate::RawFrame) -> ClientResult<Message>;
}
#[derive(Debug, Clone, Copy, Default)]
pub struct CborEnvelopeCodec;
pub struct Established<R> {
pub transport: BoxTransport,
pub codec: Arc<dyn EnvelopeCodec>,
pub ids: IdRange,
pub ready: R,
pub limits: ClientLimits,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IdRange {
pub start: u32,
pub end_exclusive: u64,
}
#[derive(Debug, Clone, Copy)]
pub struct SendMetadata {
pub generation: u8,
pub flags: u8,
}
impl IdRange {
pub fn validate(self) -> ClientResult<()> {
if self.start == 0
|| u64::from(self.start) >= self.end_exclusive
|| self.end_exclusive > (1u64 << 32)
{
return Err(ClientError::new(ErrorKind::InvalidOptions));
}
Ok(())
}
}
impl EnvelopeCodec for CborEnvelopeCodec {
fn encode(&self, generation: u8, wire_name: &str, payload: Vec<u8>) -> ClientResult<Vec<u8>> {
Ok(Envelope {
v: generation,
t: wire_name.into(),
p: payload,
}
.encode()?)
}
fn decode(&self, frame: crate::RawFrame) -> ClientResult<Message> {
let envelope = Envelope::decode(&frame.body)?;
Ok(Message::new(frame, envelope))
}
}