resizing-vec 0.1.4

An automatic resizing vector for data with linear increasing ids
Documentation
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
use resizing_vec::ResizingVec;
use std::collections::HashSet;
use std::fs::File;
use std::hash::Hash;
use std::io::{prelude::*, BufReader};

fn criterion_benchmark(c: &mut Criterion) {
    let mut group = c.benchmark_group("ChainAccess");

    let root_rv = setup_rv();
    let root_hs = setup_hs();

    let upper = black_box(3);
    for locate in 0..upper {
        group.bench_with_input(
            BenchmarkId::new("ResizingVec", locate),
            &locate,
            |b, locate| {
                for channel in 0..upper {
                    b.iter(|| root_rv.get(channel, *locate))
                }
            },
        );
        group.bench_with_input(BenchmarkId::new("HashSet", locate), &locate, |b, locate| {
            for channel in 0..upper {
                b.iter(|| root_hs.get(channel, *locate))
            }
        });
    }
}

#[derive(Eq, Hash, PartialEq)]
struct LocateId(pub usize, pub usize);

pub struct Chain {
    channel: usize,
    locate: usize,
    hash_id: LocateId,
}

impl PartialEq for Chain {
    fn eq(&self, other: &Self) -> bool {
        self.locate == other.locate && self.channel == other.channel
    }
}
impl Eq for Chain {}
impl Hash for Chain {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.locate.hash(state);
        self.channel.hash(state);
    }
}

impl std::borrow::Borrow<LocateId> for Chain {
    fn borrow(&self) -> &LocateId {
        &self.hash_id
    }
}

fn base_setup() -> Vec<Chain> {
    let file = File::open("./nl.csv").unwrap();
    let reader = BufReader::new(file);

    let mut v = Vec::default();

    let mut header_seen = false;
    for line in reader.lines() {
        if !header_seen {
            header_seen = true;
            continue;
        }

        let line = line.unwrap();
        let splits = line.split(',').collect::<Vec<&str>>();

        v.push(Chain {
            channel: splits[1].parse().unwrap(),
            locate: splits[2].parse().unwrap(),
            hash_id: LocateId(splits[1].parse().unwrap(), splits[2].parse().unwrap()),
        });
    }

    v
}

struct RsRoot {
    dat: ResizingVec<ResizingVec<Chain>>,
}

impl RsRoot {
    pub fn get(&self, channel: usize, locate: usize) -> Option<&Chain> {
        if let Some(rv) = self.dat.get(channel) {
            return rv.get(locate);
        }

        None
    }
}

fn setup_rv() -> RsRoot {
    let data = base_setup();

    let mut root = RsRoot {
        dat: ResizingVec::new(),
    };

    for x in data {
        if root.dat.get(x.channel).is_none() {
            root.dat.insert(x.channel, ResizingVec::new());
        }

        root.dat.get_mut(x.channel).unwrap().insert(x.locate, x);
    }

    root
}

struct HsRoot {
    dat: HashSet<Chain>,
}

impl HsRoot {
    pub fn get(&self, channel: usize, locate: usize) -> Option<&Chain> {
        self.dat.get(&LocateId(channel, locate))
    }
}

fn setup_hs() -> HsRoot {
    let data = base_setup();

    let mut root = HsRoot {
        dat: HashSet::new(),
    };
    let len = data.len();
    for x in data {
        root.dat.insert(x);
    }

    if root.dat.len() != len {
        panic!("Data went missing")
    }

    root
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);