use std::sync::Arc;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct RevertRange {
first: u64,
tip: u64,
}
impl RevertRange {
pub fn new(first: u64, tip: u64) -> Self {
assert!(first > 0, "RevertRange: first block number must be > 0");
assert!(first <= tip, "RevertRange: first ({first}) must be <= tip ({tip})");
Self { first, tip }
}
pub const fn first(&self) -> u64 {
self.first
}
pub const fn tip(&self) -> u64 {
self.tip
}
pub const fn len(&self) -> u64 {
self.tip - self.first + 1
}
pub const fn is_empty(&self) -> bool {
false
}
}
#[derive(Debug, Clone)]
pub struct HostNotification<C> {
pub kind: HostNotificationKind<C>,
pub safe_block_number: Option<u64>,
pub finalized_block_number: Option<u64>,
}
impl<C> HostNotification<C> {
pub const fn committed_chain(&self) -> Option<&Arc<C>> {
self.kind.committed_chain()
}
pub const fn revert_range(&self) -> Option<RevertRange> {
self.kind.revert_range()
}
}
#[derive(Debug, Clone)]
pub enum HostNotificationKind<C> {
ChainCommitted {
new: Arc<C>,
},
ChainReverted {
old: RevertRange,
},
ChainReorged {
old: RevertRange,
new: Arc<C>,
},
}
impl<C> HostNotificationKind<C> {
pub const fn committed_chain(&self) -> Option<&Arc<C>> {
match self {
Self::ChainCommitted { new } | Self::ChainReorged { new, .. } => Some(new),
Self::ChainReverted { .. } => None,
}
}
pub const fn revert_range(&self) -> Option<RevertRange> {
match self {
Self::ChainReverted { old } | Self::ChainReorged { old, .. } => Some(*old),
Self::ChainCommitted { .. } => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn revert_range_valid() {
let range = RevertRange::new(1, 1);
assert_eq!(range.first(), 1);
assert_eq!(range.tip(), 1);
assert_eq!(range.len(), 1);
let range = RevertRange::new(5, 10);
assert_eq!(range.len(), 6);
}
#[test]
#[should_panic(expected = "first block number must be > 0")]
fn revert_range_zero_first() {
RevertRange::new(0, 5);
}
#[test]
#[should_panic(expected = "first (10) must be <= tip (5)")]
fn revert_range_inverted() {
RevertRange::new(10, 5);
}
}