#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FetchKind {
Data,
NaturalEof,
Failure,
}
#[derive(Debug, Clone)]
pub struct Fetch<C> {
pub data: C,
pub kind: FetchKind,
pub epoch: u64,
}
impl<C> Fetch<C> {
pub fn new(data: C, is_eof: bool, epoch: u64) -> Self {
let kind = if is_eof {
FetchKind::NaturalEof
} else {
FetchKind::Data
};
Self { data, kind, epoch }
}
pub fn data(data: C, epoch: u64) -> Self {
Self {
data,
epoch,
kind: FetchKind::Data,
}
}
pub fn epoch(&self) -> u64 {
self.epoch
}
pub fn failure(data: C, epoch: u64) -> Self {
Self {
data,
epoch,
kind: FetchKind::Failure,
}
}
pub fn into_inner(self) -> C {
self.data
}
pub fn is_eof(&self) -> bool {
self.kind == FetchKind::NaturalEof
}
pub fn is_terminal(&self) -> bool {
!matches!(self.kind, FetchKind::Data)
}
}
#[derive(Debug, Clone, Default)]
pub struct EpochValidator {
pub epoch: u64,
}
impl EpochValidator {
pub fn is_valid<C>(&self, item: &Fetch<C>) -> bool {
item.epoch == self.epoch
}
}
#[cfg(test)]
mod tests {
use kithara_test_utils::kithara;
use super::*;
#[kithara::test]
fn epoch_validator_keeps_matching_chunks() {
let mut validator = EpochValidator::default();
let item = Fetch::new(vec![1u8, 2, 3], false, 1);
validator.epoch = 1;
assert!(validator.is_valid(&item));
}
#[kithara::test]
fn epoch_validator_rejects_stale_chunks_after_seek() {
let mut validator = EpochValidator::default();
let stale = Fetch::new(vec![3u8], false, validator.epoch);
let first = Fetch::new(vec![1u8], false, validator.epoch);
validator.epoch = validator.epoch.wrapping_add(1);
let next = Fetch::new(vec![2u8], false, validator.epoch);
assert!(!validator.is_valid(&first));
assert!(!validator.is_valid(&stale));
assert!(validator.is_valid(&next));
}
}