use core::marker::{Send, Sync};
use core::time::Duration;
use dyn_clone::DynClone;
use erased_serde::Serialize as ErasedSerialize;
use ibc_proto::google::protobuf::Any;
use ibc_proto::protobuf::Protobuf as ErasedProtobuf;
use crate::core::ics02_client::client_type::ClientType;
use crate::core::ics02_client::error::Error;
use crate::core::ics24_host::identifier::ChainId;
use crate::dynamic_typing::AsAny;
use crate::prelude::*;
use crate::Height;
use super::consensus_state::ConsensusState;
pub trait ClientState:
AsAny
+ sealed::ErasedPartialEqClientState
+ DynClone
+ ErasedSerialize
+ ErasedProtobuf<Any, Error = Error>
+ core::fmt::Debug
+ Send
+ Sync
{
fn chain_id(&self) -> ChainId;
fn client_type(&self) -> ClientType;
fn latest_height(&self) -> Height;
fn is_frozen(&self) -> bool {
self.frozen_height().is_some()
}
fn frozen_height(&self) -> Option<Height>;
fn expired(&self, elapsed: Duration) -> bool;
fn upgrade(
&mut self,
upgrade_height: Height,
upgrade_options: &dyn UpgradeOptions,
chain_id: ChainId,
);
fn into_box(self) -> Box<dyn ClientState>
where
Self: Sized,
{
Box::new(self)
}
}
dyn_clone::clone_trait_object!(ClientState);
erased_serde::serialize_trait_object!(ClientState);
impl PartialEq for dyn ClientState {
fn eq(&self, other: &Self) -> bool {
self.eq_client_state(other)
}
}
impl PartialEq<&Self> for Box<dyn ClientState> {
fn eq(&self, other: &&Self) -> bool {
self.eq_client_state(other.as_ref())
}
}
pub fn downcast_client_state<CS: ClientState>(h: &dyn ClientState) -> Option<&CS> {
h.as_any().downcast_ref::<CS>()
}
pub trait UpgradeOptions: AsAny {}
pub struct UpdatedState {
pub client_state: Box<dyn ClientState>,
pub consensus_state: Box<dyn ConsensusState>,
}
mod sealed {
use super::*;
pub trait ErasedPartialEqClientState {
fn eq_client_state(&self, other: &dyn ClientState) -> bool;
}
impl<CS> ErasedPartialEqClientState for CS
where
CS: ClientState + PartialEq,
{
fn eq_client_state(&self, other: &dyn ClientState) -> bool {
other
.as_any()
.downcast_ref::<CS>()
.map_or(false, |h| self == h)
}
}
}