use std::error::Error;
use std::fmt::Display;
use std::fmt::Formatter;
use display_more::DisplayOptionExt;
use validit::Validate;
use crate::LogIdOptionExt;
use crate::RaftTypeConfig;
use crate::type_config::alias::LogIdOf;
#[derive(Clone, Debug)]
#[derive(PartialEq, Eq)]
pub(crate) struct LogIdRange<C>
where C: RaftTypeConfig
{
pub(crate) prev: Option<LogIdOf<C>>,
pub(crate) last: Option<LogIdOf<C>>,
}
impl<C> Copy for LogIdRange<C>
where
C: RaftTypeConfig,
LogIdOf<C>: Copy,
{
}
impl<C> Display for LogIdRange<C>
where C: RaftTypeConfig
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "({}, {}]", self.prev.display(), self.last.display())
}
}
impl<C> Validate for LogIdRange<C>
where C: RaftTypeConfig
{
fn validate(&self) -> Result<(), Box<dyn Error>> {
validit::less_equal!(&self.prev, &self.last);
Ok(())
}
}
impl<C> LogIdRange<C>
where C: RaftTypeConfig
{
pub(crate) fn new(prev: Option<LogIdOf<C>>, last: Option<LogIdOf<C>>) -> Self {
Self { prev, last }
}
#[allow(dead_code)]
pub(crate) fn len(&self) -> u64 {
self.last.next_index() - self.prev.next_index()
}
}
#[cfg(test)]
mod tests {
use validit::Valid;
use crate::engine::testing::UTConfig;
use crate::log_id_range::LogIdRange;
use crate::type_config::alias::LogIdOf;
fn log_id(index: u64) -> LogIdOf<UTConfig> {
crate::engine::testing::log_id(1, 1, index)
}
#[test]
fn test_log_id_range_validate() -> anyhow::Result<()> {
let res = std::panic::catch_unwind(|| {
let r = Valid::new(LogIdRange::<UTConfig>::new(Some(log_id(5)), None));
let _x = &r.last;
});
tracing::info!("res: {:?}", res);
assert!(res.is_err(), "prev(5) > last(None)");
let res = std::panic::catch_unwind(|| {
let r = Valid::new(LogIdRange::<UTConfig>::new(Some(log_id(5)), Some(log_id(4))));
let _x = &r.last;
});
tracing::info!("res: {:?}", res);
assert!(res.is_err(), "prev(5) > last(4)");
Ok(())
}
}