use crossbeam_skiplist::SkipMap;
use crossbeam_skiplist::map::Iter;
use either::Either;
use pricelevel::{PriceLevel, Side};
use std::iter::Rev;
use std::sync::Arc;
type PriceLevelIter<'a> =
Either<Rev<Iter<'a, u128, Arc<PriceLevel>>>, Iter<'a, u128, Arc<PriceLevel>>>;
#[derive(Debug, Clone)]
pub struct LevelInfo {
pub price: u128,
pub quantity: u64,
pub cumulative_depth: u64,
}
pub struct LevelsWithCumulativeDepth<'a> {
iter: PriceLevelIter<'a>,
cumulative_depth: u64,
}
impl<'a> LevelsWithCumulativeDepth<'a> {
pub fn new(price_levels: &'a SkipMap<u128, Arc<PriceLevel>>, side: Side) -> Self {
let iter = match side {
Side::Buy => Either::Left(price_levels.iter().rev()), Side::Sell => Either::Right(price_levels.iter()), };
Self {
iter,
cumulative_depth: 0,
}
}
}
impl<'a> Iterator for LevelsWithCumulativeDepth<'a> {
type Item = LevelInfo;
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|entry| {
let price = *entry.key();
let quantity = entry.value().total_quantity().unwrap_or(0);
self.cumulative_depth = self.cumulative_depth.saturating_add(quantity);
LevelInfo {
price,
quantity,
cumulative_depth: self.cumulative_depth,
}
})
}
}
pub struct LevelsUntilDepth<'a> {
iter: PriceLevelIter<'a>,
target_depth: u64,
cumulative_depth: u64,
finished: bool,
}
impl<'a> LevelsUntilDepth<'a> {
pub fn new(
price_levels: &'a SkipMap<u128, Arc<PriceLevel>>,
side: Side,
target_depth: u64,
) -> Self {
let iter = match side {
Side::Buy => Either::Left(price_levels.iter().rev()),
Side::Sell => Either::Right(price_levels.iter()),
};
Self {
iter,
target_depth,
cumulative_depth: 0,
finished: false,
}
}
}
impl<'a> Iterator for LevelsUntilDepth<'a> {
type Item = LevelInfo;
fn next(&mut self) -> Option<Self::Item> {
if self.finished {
return None;
}
self.iter.next().map(|entry| {
let price = *entry.key();
let quantity = entry.value().total_quantity().unwrap_or(0);
self.cumulative_depth = self.cumulative_depth.saturating_add(quantity);
let level_info = LevelInfo {
price,
quantity,
cumulative_depth: self.cumulative_depth,
};
if self.cumulative_depth >= self.target_depth {
self.finished = true;
}
level_info
})
}
}
pub struct LevelsInRange<'a> {
iter: PriceLevelIter<'a>,
min_price: u128,
max_price: u128,
finished: bool,
}
impl<'a> LevelsInRange<'a> {
pub fn new(
price_levels: &'a SkipMap<u128, Arc<PriceLevel>>,
side: Side,
min_price: u128,
max_price: u128,
) -> Self {
let iter = match side {
Side::Buy => Either::Left(price_levels.iter().rev()),
Side::Sell => Either::Right(price_levels.iter()),
};
Self {
iter,
min_price,
max_price,
finished: false,
}
}
}
impl<'a> Iterator for LevelsInRange<'a> {
type Item = LevelInfo;
fn next(&mut self) -> Option<Self::Item> {
if self.finished {
return None;
}
for entry in self.iter.by_ref() {
let price = *entry.key();
if price >= self.min_price && price <= self.max_price {
let quantity = entry.value().total_quantity().unwrap_or(0);
return Some(LevelInfo {
price,
quantity,
cumulative_depth: 0, });
}
}
self.finished = true;
None
}
}