use crate::pool::Transaction;
use std::{cmp, fmt};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Choice {
RejectNew,
ReplaceOld,
InsertNew,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Change<T = ()> {
InsertedAt(usize),
RemovedAt(usize),
ReplacedAt(usize),
Culled(usize),
Event(T),
}
pub trait Scoring<T>: fmt::Debug {
type Score: cmp::Ord + Clone + Default + fmt::Debug + Send + fmt::LowerHex;
type Event: fmt::Debug;
fn compare(&self, old: &T, other: &T) -> cmp::Ordering;
fn choose(&self, old: &T, new: &T) -> Choice;
fn update_scores(&self, txs: &[Transaction<T>], scores: &mut [Self::Score], change: Change<Self::Event>);
fn should_ignore_sender_limit(&self, _new: &T) -> bool {
false
}
}
#[derive(Debug)]
pub struct ScoreWithRef<T, S> {
pub score: S,
pub transaction: Transaction<T>,
}
impl<T, S> ScoreWithRef<T, S> {
pub fn new(score: S, transaction: Transaction<T>) -> Self {
ScoreWithRef { score, transaction }
}
}
impl<T, S: Clone> Clone for ScoreWithRef<T, S> {
fn clone(&self) -> Self {
ScoreWithRef { score: self.score.clone(), transaction: self.transaction.clone() }
}
}
impl<S: cmp::Ord, T> Ord for ScoreWithRef<T, S> {
fn cmp(&self, other: &Self) -> cmp::Ordering {
other.score.cmp(&self.score).then(self.transaction.insertion_id.cmp(&other.transaction.insertion_id))
}
}
impl<S: cmp::Ord, T> PartialOrd for ScoreWithRef<T, S> {
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<S: cmp::Ord, T> PartialEq for ScoreWithRef<T, S> {
fn eq(&self, other: &Self) -> bool {
self.score == other.score && self.transaction.insertion_id == other.transaction.insertion_id
}
}
impl<S: cmp::Ord, T> Eq for ScoreWithRef<T, S> {}
#[cfg(test)]
mod tests {
use super::*;
fn score(score: u64, insertion_id: u64) -> ScoreWithRef<(), u64> {
ScoreWithRef { score, transaction: Transaction { insertion_id, transaction: Default::default() } }
}
#[test]
fn scoring_comparison() {
assert_eq!(score(10, 0).cmp(&score(0, 0)), cmp::Ordering::Less);
assert_eq!(score(0, 0).cmp(&score(10, 0)), cmp::Ordering::Greater);
assert_eq!(score(0, 0).cmp(&score(0, 0)), cmp::Ordering::Equal);
assert_eq!(score(0, 0).cmp(&score(0, 10)), cmp::Ordering::Less);
assert_eq!(score(0, 10).cmp(&score(0, 0)), cmp::Ordering::Greater);
}
}