1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
use serde::de::DeserializeOwned;
use serde::Serialize;
use std::ffi::OsStr;
use std::fs::{self, File};
use std::io::Read;
use std::path::Path;
use walkdir::{DirEntry, WalkDir};

use crate::error::{Error, Result};
use crate::report::BenchmarkId;

pub fn load<A, P: ?Sized>(path: &P) -> Result<A>
where
    A: DeserializeOwned,
    P: AsRef<Path>,
{
    let path = path.as_ref();
    let mut f = File::open(path).map_err(|inner| Error::AccessError {
        inner,
        path: path.to_owned(),
    })?;
    let mut string = String::new();
    let _ = f.read_to_string(&mut string);
    let result: A = serde_json::from_str(string.as_str()).map_err(|inner| Error::SerdeError {
        inner,
        path: path.to_owned(),
    })?;

    Ok(result)
}

pub fn is_dir<P>(path: &P) -> bool
where
    P: AsRef<Path>,
{
    let path: &Path = path.as_ref();
    path.is_dir()
}

pub fn mkdirp<P>(path: &P) -> Result<()>
where
    P: AsRef<Path>,
{
    fs::create_dir_all(path.as_ref()).map_err(|inner| Error::AccessError {
        inner,
        path: path.as_ref().to_owned(),
    })?;
    Ok(())
}

pub fn cp(from: &Path, to: &Path) -> Result<()> {
    fs::copy(from, to).map_err(|inner| Error::CopyError {
        inner,
        from: from.to_owned(),
        to: to.to_owned(),
    })?;
    Ok(())
}

pub fn save<D, P>(data: &D, path: &P) -> Result<()>
where
    D: Serialize,
    P: AsRef<Path>,
{
    let buf = serde_json::to_string(&data).map_err(|inner| Error::SerdeError {
        path: path.as_ref().to_owned(),
        inner,
    })?;
    save_string(&buf, path)
}

pub fn save_string<P>(data: &str, path: &P) -> Result<()>
where
    P: AsRef<Path>,
{
    use std::io::Write;

    File::create(path)
        .and_then(|mut f| f.write_all(data.as_bytes()))
        .map_err(|inner| Error::AccessError {
            inner,
            path: path.as_ref().to_owned(),
        })?;

    Ok(())
}

pub fn list_existing_benchmarks<P>(directory: &P) -> Result<Vec<BenchmarkId>>
where
    P: AsRef<Path>,
{
    fn is_benchmark(entry: &DirEntry) -> bool {
        // Look for benchmark.json files inside folders named "new" (because we want to ignore
        // the baselines)
        entry.file_name() == OsStr::new("benchmark.json")
            && entry.path().parent().unwrap().file_name().unwrap() == OsStr::new("new")
    }

    let mut ids = vec![];

    for entry in WalkDir::new(directory)
        .into_iter()
        // Ignore errors.
        .filter_map(::std::result::Result::ok)
        .filter(is_benchmark)
    {
        let id: BenchmarkId = load(entry.path())?;
        ids.push(id);
    }

    Ok(ids)
}