use crate::{RankAccuracy, ReqError, ReqSketch, Result, TotalOrd};
use std::marker::PhantomData;
#[derive(Debug, Clone)]
pub struct ReqSketchBuilder<T> {
k: u16,
rank_accuracy: RankAccuracy,
_phantom: PhantomData<T>,
}
impl<T> ReqSketchBuilder<T>
where
T: Clone + TotalOrd + PartialEq,
{
pub fn new() -> Self {
Self {
k: 12,
rank_accuracy: RankAccuracy::HighRank,
_phantom: PhantomData,
}
}
pub fn k(mut self, k: u16) -> Result<Self> {
validate_k(k)?;
self.k = k;
Ok(self)
}
pub fn rank_accuracy(mut self, accuracy: RankAccuracy) -> Self {
self.rank_accuracy = accuracy;
self
}
pub fn build(self) -> Result<ReqSketch<T>> {
Ok(ReqSketch {
k: self.k,
rank_accuracy: self.rank_accuracy,
total_n: 0,
max_nom_size: 0,
num_retained: 0,
compactors: Vec::new(),
promotion_buf: Vec::with_capacity(self.k as usize), min_item: None,
max_item: None,
sorted_view_cache: None,
})
}
pub fn get_k(&self) -> u16 {
self.k
}
pub fn get_rank_accuracy(&self) -> RankAccuracy {
self.rank_accuracy
}
}
impl<T> Default for ReqSketchBuilder<T>
where
T: Clone + TotalOrd + PartialEq,
{
fn default() -> Self {
Self::new()
}
}
pub(crate) fn validate_k(k: u16) -> Result<()> {
if k < 4 || !k.is_multiple_of(2) {
Err(ReqError::InvalidK(k))
} else {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default_builder() {
let builder: ReqSketchBuilder<f64> = ReqSketchBuilder::new();
assert_eq!(builder.get_k(), 12);
assert_eq!(builder.get_rank_accuracy(), RankAccuracy::HighRank);
}
#[test]
fn test_builder_k_validation() {
assert!(ReqSketchBuilder::<f64>::new().k(4).is_ok());
assert!(ReqSketchBuilder::<f64>::new().k(12).is_ok());
assert!(ReqSketchBuilder::<f64>::new().k(1024).is_ok());
assert!(ReqSketchBuilder::<f64>::new().k(2048).is_ok()); assert!(ReqSketchBuilder::<f64>::new().k(u16::MAX - 1).is_ok());
assert!(ReqSketchBuilder::<f64>::new().k(3).is_err()); assert!(ReqSketchBuilder::<f64>::new().k(5).is_err()); assert!(ReqSketchBuilder::<f64>::new().k(u16::MAX).is_err()); }
#[test]
fn test_builder_fluent_interface() -> Result<()> {
let sketch = ReqSketchBuilder::<i32>::new()
.k(16)?
.rank_accuracy(RankAccuracy::LowRank)
.build()?;
assert_eq!(sketch.k(), 16);
assert_eq!(sketch.rank_accuracy(), RankAccuracy::LowRank);
Ok(())
}
#[test]
fn test_validate_k() {
assert!(validate_k(4).is_ok());
assert!(validate_k(12).is_ok());
assert!(validate_k(1024).is_ok());
assert!(validate_k(2048).is_ok()); assert!(validate_k(u16::MAX - 1).is_ok());
assert!(validate_k(3).is_err());
assert!(validate_k(5).is_err());
assert!(validate_k(u16::MAX).is_err()); }
}