use std::{marker::PhantomData, ops::RangeInclusive};
use derive_where::derive_where;
use thiserror::Error;
use malachitebft_core_types::Context;
use malachitebft_peer::PeerId;
use crate::{InboundRequestId, OutboundRequestId, ValueRequest, ValueResponse};
pub trait Resumable<Ctx: Context> {
type Value;
fn resume_with(self, value: Self::Value) -> Resume<Ctx>;
}
#[derive_where(Debug)]
#[derive(Error)]
pub enum Error<Ctx: Context> {
#[error("Unexpected resume: {0:?}, expected one of: {1}")]
UnexpectedResume(Resume<Ctx>, &'static str),
}
#[derive_where(Debug)]
pub enum Resume<Ctx: Context> {
Continue(PhantomData<Ctx>),
ValueRequestId(Option<OutboundRequestId>),
}
impl<Ctx: Context> Default for Resume<Ctx> {
fn default() -> Self {
Self::Continue(PhantomData)
}
}
#[derive_where(Debug)]
pub enum Effect<Ctx: Context> {
BroadcastStatus(Ctx::Height, resume::Continue),
SendValueRequest(PeerId, ValueRequest<Ctx>, resume::ValueRequestId),
SendValueResponse(InboundRequestId, ValueResponse<Ctx>, resume::Continue),
GetDecidedValues(
InboundRequestId,
RangeInclusive<Ctx::Height>,
resume::Continue,
),
ProcessValueResponse(
PeerId,
OutboundRequestId,
ValueResponse<Ctx>,
resume::Continue,
),
}
pub mod resume {
use super::*;
#[derive(Debug, Default)]
pub struct Continue;
impl<Ctx: Context> Resumable<Ctx> for Continue {
type Value = ();
fn resume_with(self, _: ()) -> Resume<Ctx> {
Resume::default()
}
}
#[derive(Debug, Default)]
pub struct ValueRequestId;
impl<Ctx: Context> Resumable<Ctx> for ValueRequestId {
type Value = Option<OutboundRequestId>;
fn resume_with(self, value: Self::Value) -> Resume<Ctx> {
Resume::ValueRequestId(value)
}
}
}