cask 0.7.1

A fast key-value store backed by a log-structured hash table
Documentation
use std::fs::{File, OpenOptions};
use std::io::{Result, Write};
use std::path::Path;
use std::result::Result::Ok;
use std::sync::atomic::{AtomicUsize, Ordering};

use xxhash2::{State32, hash32};

pub struct XxHash32(State32);

impl XxHash32 {
    pub fn new() -> XxHash32 {
        let mut state = State32::new();
        state.reset(0);
        XxHash32(state)
    }

    pub fn update(&mut self, buf: &[u8]) {
        self.0.update(buf);
    }

    pub fn get(&self) -> u32 {
        self.0.finish()
    }
}

impl Write for XxHash32 {
    fn write(&mut self, buf: &[u8]) -> Result<usize> {
        self.update(buf);
        Ok(buf.len())
    }

    fn flush(&mut self) -> Result<()> {
        Ok(())
    }
}

pub fn xxhash32(buf: &[u8]) -> u32 {
    hash32(buf, 0)
}

pub fn get_file_handle(path: &Path, write: bool) -> Result<File> {
    if write {
        OpenOptions::new()
            .write(true)
            .create(true)
            .truncate(true)
            .open(path)
    } else {
        OpenOptions::new().read(true).open(path)
    }
}

pub struct Sequence(AtomicUsize);

impl Sequence {
    pub fn new(id: u32) -> Sequence {
        Sequence(AtomicUsize::new(id as usize))
    }

    pub fn increment(&self) -> u32 {
        self.0.fetch_add(1, Ordering::SeqCst) as u32 + 1
    }
}

pub fn human_readable_byte_count(bytes: usize, si: bool) -> String {
    let unit = if si { 1000 } else { 1024 };
    if bytes < unit {
        return format!("{} B", bytes);
    }
    let exp = ((bytes as f64).ln() / (unit as f64).ln()) as usize;

    let units = if si { "kMGTPE" } else { "KMGTPE" };
    let pre = format!(
        "{}{}",
        units.chars().nth(exp - 1).unwrap(),
        if si { "" } else { "i" }
    );

    format!("{:.1} {}B", bytes / unit.pow(exp as u32), pre)
}