use std::fmt::Debug;
use std::ops::RangeBounds;
use std::{collections::BTreeMap, fmt::Display};
use bitcoin::{block::Header, BlockHash};
use crate::prelude::FutureResult;
use super::{BlockHeaderChanges, PersistedPeer};
pub trait HeaderStore: Debug + Send + Sync {
type Error: Debug + Display;
fn load<'a>(
&'a mut self,
range: impl RangeBounds<u32> + Send + Sync + 'a,
) -> FutureResult<'a, BTreeMap<u32, Header>, Self::Error>;
fn stage(&mut self, changes: BlockHeaderChanges);
fn write(&mut self) -> FutureResult<'_, (), Self::Error>;
fn height_of<'a>(
&'a mut self,
hash: &'a BlockHash,
) -> FutureResult<'a, Option<u32>, Self::Error>;
fn hash_at(&mut self, height: u32) -> FutureResult<'_, Option<BlockHash>, Self::Error>;
fn header_at(&mut self, height: u32) -> FutureResult<'_, Option<Header>, Self::Error>;
}
pub trait PeerStore: Debug + Send + Sync {
type Error: Debug + Display;
fn update(&mut self, peer: PersistedPeer) -> FutureResult<'_, (), Self::Error>;
fn random(&mut self) -> FutureResult<'_, PersistedPeer, Self::Error>;
fn num_unbanned(&mut self) -> FutureResult<'_, u32, Self::Error>;
}
#[cfg(test)]
mod test {
use super::*;
use std::convert::Infallible;
#[derive(Debug)]
pub enum UnitPeerStoreError {
NoPeers,
}
impl core::fmt::Display for UnitPeerStoreError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
UnitPeerStoreError::NoPeers => write!(f, "no peers in unit database."),
}
}
}
impl PeerStore for () {
type Error = UnitPeerStoreError;
fn update(&mut self, _peer: PersistedPeer) -> FutureResult<'_, (), Self::Error> {
async fn do_update() -> Result<(), UnitPeerStoreError> {
Ok(())
}
Box::pin(do_update())
}
fn random(&mut self) -> FutureResult<'_, PersistedPeer, Self::Error> {
async fn do_random() -> Result<PersistedPeer, UnitPeerStoreError> {
Err(UnitPeerStoreError::NoPeers)
}
Box::pin(do_random())
}
fn num_unbanned(&mut self) -> FutureResult<'_, u32, Self::Error> {
async fn do_num_unbanned() -> Result<u32, UnitPeerStoreError> {
Ok(0)
}
Box::pin(do_num_unbanned())
}
}
impl HeaderStore for () {
type Error = Infallible;
fn load<'a>(
&'a mut self,
_range: impl RangeBounds<u32> + Send + Sync + 'a,
) -> FutureResult<'a, BTreeMap<u32, Header>, Self::Error> {
async fn do_load() -> Result<BTreeMap<u32, Header>, Infallible> {
Ok(BTreeMap::new())
}
Box::pin(do_load())
}
fn stage(&mut self, _changes: BlockHeaderChanges) {}
fn write(&mut self) -> FutureResult<'_, (), Self::Error> {
async fn do_write() -> Result<(), Infallible> {
Ok(())
}
Box::pin(do_write())
}
fn height_of<'a>(
&'a mut self,
_block_hash: &'a BlockHash,
) -> FutureResult<'a, Option<u32>, Self::Error> {
async fn do_height_of() -> Result<Option<u32>, Infallible> {
Ok(None)
}
Box::pin(do_height_of())
}
fn hash_at(&mut self, _height: u32) -> FutureResult<'_, Option<BlockHash>, Self::Error> {
async fn do_hast_at() -> Result<Option<BlockHash>, Infallible> {
Ok(None)
}
Box::pin(do_hast_at())
}
fn header_at(&mut self, _height: u32) -> FutureResult<'_, Option<Header>, Self::Error> {
async fn do_header_at() -> Result<Option<Header>, Infallible> {
Ok(None)
}
Box::pin(do_header_at())
}
}
}