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
|
use crate::schema::{Person, Team};
use failure::{Error, ResultExt};
use serde::Deserialize;
use std::collections::HashMap;
use std::ffi::OsStr;
#[derive(Debug)]
pub(crate) struct Data {
people: HashMap<String, Person>,
teams: HashMap<String, Team>,
}
impl Data {
pub(crate) fn load() -> Result<Self, Error> {
let mut data = Data {
people: HashMap::new(),
teams: HashMap::new(),
};
data.load_dir("people", |this, person: Person| {
this.people.insert(person.github().to_string(), person);
})?;
data.load_dir("teams", |this, team: Team| {
this.teams.insert(team.name().to_string(), team);
})?;
Ok(data)
}
fn load_dir<T, F>(&mut self, dir: &str, f: F) -> Result<(), Error>
where
T: for<'de> Deserialize<'de>,
F: Fn(&mut Self, T),
{
for entry in std::fs::read_dir(dir)? {
let path = entry?.path();
if path.is_file() && path.extension() == Some(OsStr::new("toml")) {
let content = std::fs::read(&path)
.with_context(|_| format!("failed to read {}", path.display()))?;
let parsed: T = toml::from_slice(&content)
.with_context(|_| format!("failed to parse {}", path.display()))?;
f(self, parsed);
}
}
Ok(())
}
pub(crate) fn team(&self, name: &str) -> Option<&Team> {
self.teams.get(name)
}
pub(crate) fn teams(&self) -> impl Iterator<Item = &Team> {
self.teams.values()
}
pub(crate) fn person(&self, name: &str) -> Option<&Person> {
self.people.get(name)
}
pub(crate) fn people(&self) -> impl Iterator<Item = &Person> {
self.people.values()
}
}
|