+fn tally_votes(dir: &Path) -> std::io::Result<HashMap<String, HashSet<String>>> {
+ let mut tally: HashMap<String, HashSet<String>> = HashMap::new();
+ match std::fs::File::open(dir.to_owned().join("votes")) {
+ Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(tally),
+ Err(e) => Err(e),
+ Ok(vfile) => {
+ for liner in std::io::BufReader::new(vfile).lines() {
+ let line = liner?;
+ if let Some((voter, datum)) = line.split_once(' ') {
+ if voter.len() == COOKIE_LENGTH {
+ if let Some((vote, candidate)) = datum.split_once(' ') {
+ if vote == "0" {
+ if let Some(entry) = tally.get_mut(candidate) {
+ entry.remove(voter);
+ }
+ } else if vote == "1" {
+ tally
+ .entry(candidate.to_owned())
+ .or_default()
+ .insert(voter.to_owned());
+ }
+ }
+ }
+ }
+ }
+ Ok(tally)
+ }
+ }
+}
+
+fn read_elim_list(dir: &Path) -> std::io::Result<HashSet<String>> {
+ match std::fs::File::open(dir.join("eliminated")) {
+ Err(e) if e.kind() == std::io::ErrorKind::NotFound => Ok(HashSet::new()),
+ Err(e) => Err(e),
+ Ok(elimfile) => std::io::BufReader::new(elimfile).lines().collect(),
+ }
+}
+
+fn valid_id_char(c: u8) -> bool {
+ c.is_ascii_alphanumeric()
+}
+