cask 0.7.1

A fast key-value store backed by a log-structured hash table
Documentation
use std::collections::{HashMap, VecDeque};
use std::collections::hash_map::Entry;
use std::fs::File;

pub struct FilePool {
    queue: VecDeque<u32>,
    files: HashMap<u32, Vec<File>>,
    capacity: usize,
    size: usize,
}

impl FilePool {
    pub fn new(capacity: usize) -> FilePool {
        FilePool {
            queue: VecDeque::new(),
            files: HashMap::new(),
            capacity: capacity,
            size: 0,
        }
    }

    pub fn get(&mut self, file_id: u32) -> Option<File> {
        let mut remove = false;

        let f = self.files.get_mut(&file_id).and_then(|v| {
            let f = v.pop();
            if v.is_empty() {
                remove = true;
            }
            f
        });

        if f.is_some() {
            if remove {
                self.files.remove(&file_id);
            }

            if let Some(index) = self.queue.iter().position(|&f| f == file_id) {
                self.queue.remove(index);
            }

            self.size -= 1;
        }

        f
    }

    pub fn put(&mut self, file_id: u32, file: File) {
        self.queue.push_back(file_id);

        match self.files.entry(file_id) {
            Entry::Occupied(mut o) => {
                o.get_mut().push(file);
            }
            Entry::Vacant(e) => {
                e.insert(vec![file]);
            }
        }

        self.size += 1;

        if self.size > self.capacity {
            self.remove_lru();
        }
    }

    fn remove_lru(&mut self) {
        if let Some(file_id) = self.queue.pop_front() {
            let mut remove = false;

            if let Some(files) = self.files.get_mut(&file_id) {
                files.pop();

                if files.is_empty() {
                    remove = true;
                }

                self.size -= 1;
            }

            if remove {
                self.files.remove(&file_id);
            }
        }
    }
}