bitgrep 0.1.5

Binary grep for numerical data types
Documentation
use std::{cell::RefCell, rc::Rc};

use crate::{
    types::{bit_type::BitType, compare::Compare},
    workers::entropy_processor::EntropyProducer,
};

use super::{
    and::And, entropy::Entropy, equal::Equal, filter::Filter, max::Max, min::Min,
    notequal::NotEqual, notequal_exact::NotEqualExact,
};

#[derive(Default)]
pub struct Configuration<T: Compare + 'static> {
    pub minimum: Option<T>,
    pub maximum: Option<T>,
    pub literal: Option<T>,
    pub exclude_zero: bool,
    pub exclude_literal: Option<T>,
    pub entropy: Option<EntropyConfig>,
}

type BoxedFilter<T> = Box<dyn Filter<T>>;

impl<T: Compare> Configuration<T> {
    #[allow(clippy::option_map_unit_fn)]
    pub fn create_filter(&self) -> Option<BoxedFilter<T>> {
        let mut filters: Vec<BoxedFilter<T>> = Vec::with_capacity(5);

        self.create_equal_filter().map(|f| filters.push(f));
        self.create_max_filter().map(|f| filters.push(f));
        self.create_min_filter().map(|f| filters.push(f));
        self.create_exclude_zero_filter().map(|f| filters.push(f));
        self.create_exclude_literal_filter()
            .map(|f| filters.push(f));

        self.entropy
            .as_ref()
            .and_then(EntropyConfig::create_filter)
            .map(|f| filters.push(f));

        if filters.is_empty() {
            return None;
        }

        return Some(And::with_box(filters));
    }

    fn create_max_filter(&self) -> Option<BoxedFilter<T>> {
        if let Some(max) = self.maximum {
            return Some(Max::with_box(max));
        }

        return None;
    }

    fn create_min_filter(&self) -> Option<BoxedFilter<T>> {
        if let Some(min) = self.minimum {
            return Some(Min::with_box(min));
        }

        return None;
    }

    fn create_equal_filter(&self) -> Option<BoxedFilter<T>> {
        if let Some(literal) = self.literal {
            return Some(Equal::with_box(literal));
        }

        return None;
    }

    fn create_exclude_zero_filter(&self) -> Option<BoxedFilter<T>> {
        if self.exclude_zero {
            return Some(NotEqualExact::with_box(T::zero()));
        }

        return None;
    }

    fn create_exclude_literal_filter(&self) -> Option<BoxedFilter<T>> {
        if let Some(literal) = self.exclude_literal {
            return Some(NotEqual::with_box(literal));
        }

        return None;
    }
}

pub struct EntropyConfig {
    pub max_entropy: f64,
    pub entropy_producer: Rc<RefCell<dyn EntropyProducer>>,
}

impl EntropyConfig {
    fn create_filter<T: BitType>(&self) -> Option<BoxedFilter<T>> {
        let boxed_filter = Entropy::with_box(self.max_entropy, self.entropy_producer.clone());
        return Some(boxed_filter as BoxedFilter<T>);
    }
}