use crate::{types::Round, Block};
use commonware_codec::{Codec, Read};
use commonware_cryptography::{Digest, Digestible, PublicKey};
use commonware_p2p::Recipients;
use commonware_utils::channel::oneshot;
use std::{future::Future, sync::Arc};
pub trait Variant: Clone + Send + Sync + 'static {
type Block: Block<Digest = <Self::ApplicationBlock as Digestible>::Digest>
+ Into<Self::StoredBlock>
+ Clone;
type ApplicationBlock: Block + Clone;
type StoredBlock: Block<Digest = <Self::Block as Digestible>::Digest>
+ Into<Self::Block>
+ Clone
+ Codec<Cfg = <Self::Block as Read>::Cfg>;
type Commitment: Digest;
fn commitment(block: &Self::Block) -> Self::Commitment;
fn commitment_to_inner(commitment: Self::Commitment) -> <Self::Block as Digestible>::Digest;
fn parent_commitment(block: &Self::Block) -> Self::Commitment;
fn into_inner(block: Self::Block) -> Self::ApplicationBlock;
}
pub trait Buffer<V: Variant>: Clone + Send + Sync + 'static {
type PublicKey: PublicKey;
type CachedBlock: IntoBlock<V::Block>;
fn find_by_digest(
&self,
digest: <V::Block as Digestible>::Digest,
) -> impl Future<Output = Option<Self::CachedBlock>> + Send;
fn find_by_commitment(
&self,
commitment: V::Commitment,
) -> impl Future<Output = Option<Self::CachedBlock>> + Send;
fn subscribe_by_digest(
&self,
digest: <V::Block as Digestible>::Digest,
) -> impl Future<Output = oneshot::Receiver<Self::CachedBlock>> + Send;
fn subscribe_by_commitment(
&self,
commitment: V::Commitment,
) -> impl Future<Output = oneshot::Receiver<Self::CachedBlock>> + Send;
fn finalized(&self, commitment: V::Commitment) -> impl Future<Output = ()> + Send;
fn send(
&self,
round: Round,
block: V::Block,
recipients: Recipients<Self::PublicKey>,
) -> impl Future<Output = ()> + Send;
}
pub trait IntoBlock<B>: Clone + Send {
fn into_block(self) -> B;
}
impl<B: Clone + Send> IntoBlock<B> for B {
fn into_block(self) -> B {
self
}
}
impl<B: Clone + Send + Sync> IntoBlock<B> for Arc<B> {
fn into_block(self) -> B {
Self::unwrap_or_clone(self)
}
}