bloom-filter-yss 0.1.0

Simple bloom filter for me or you
Documentation
use super::bit_array::BitArray;

#[allow(dead_code)]
pub struct BloomFilter {
    filter_size: usize,
    max_items: usize,
    bit_array: BitArray,
}

#[allow(dead_code)]
impl BloomFilter {
    pub fn new(filter_size: usize) -> Self {
        Self {
            filter_size,
            max_items: 100,
            bit_array: BitArray::new(filter_size),
        }
    }

    pub fn lookup(&self, s: &str) -> bool {
        self.hashing(s).iter().all(|&i| self.bit_array.get_bit(i))
    }

    pub fn insert(&mut self, s: &str) {
        if self.lookup(s) {
            println!("{} is probably present", s);
        } else {
            for i in self.hashing(s) {
                self.bit_array.set(i, true)
            }
            println!("Inserted: {}", s);
        }
    }

    fn hashing(&self, s: &str) -> Vec<usize> {
        vec![
            hash1(s, self.filter_size),
            hash2(s, self.filter_size),
            hash3(s, self.filter_size),
            hash4(s, self.filter_size),
        ]
    }
}

fn mod_exp(base: usize, exp: usize, modulo: usize) -> usize {
    let mut result = 1_usize;
    let mut base = base % modulo;
    let mut exp = exp;

    while exp > 0 {
        if exp % 2 == 1 {
            result = (result * base) % modulo;
        }
        base = (base * base) % modulo;
        exp /= 2;
    }

    result
}

fn hash1(s: &str, size: usize) -> usize {
    let mut hash = 0;
    for ch in s.chars() {
        let ch_val = ch as usize;
        hash = (hash + ch_val) % size;
    }
    hash
}

fn hash2(s: &str, size: usize) -> usize {
    let mut hash = 1;
    for (idx, ch) in s.chars().enumerate() {
        let power = mod_exp(19, idx, size);
        let temp = power * (ch as usize) % size;
        hash = (hash + temp) % size;
    }
    hash
}

fn hash3(s: &str, size: usize) -> usize {
    let mut hash = 7;
    for ch in s.chars() {
        hash = (hash * 31 + (ch as usize)) % size;
    }
    hash
}

fn hash4(s: &str, size: usize) -> usize {
    let mut hash = 3;
    let p = 7;
    let fst_ch_val = s.chars().next().unwrap() as usize;
    for idx in 0..s.len() {
        let temp = mod_exp(p, idx, size) * fst_ch_val % size;
        hash = (hash * p + temp) % size;
    }
    hash
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_bloom_filter() {
        let mut bloom_filter = BloomFilter::new(100);
        bloom_filter.insert("abound");
        bloom_filter.insert("abound1");
        bloom_filter.insert("abound2");
        bloom_filter.insert("abound");

        assert!(bloom_filter.lookup("abound"));
        assert!(bloom_filter.lookup("abound1"));
        assert!(bloom_filter.lookup("abound2"));
        assert!(!bloom_filter.lookup("abbound"));
        assert!(!bloom_filter.lookup("dnuoba"));
    }
}