Return Result from CSP parse_reader, better error messages
This commit is contained in:
parent
71dc671c34
commit
e78d06289a
7
Cargo.lock
generated
7
Cargo.lock
generated
@ -28,6 +28,12 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.6"
|
version = "0.3.6"
|
||||||
@ -711,6 +717,7 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
|||||||
name = "opentally"
|
name = "opentally"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
"clap",
|
"clap",
|
||||||
"console_error_panic_hook",
|
"console_error_panic_hook",
|
||||||
|
@ -8,6 +8,7 @@ edition = "2018"
|
|||||||
crate-type = ["lib", "cdylib"]
|
crate-type = ["lib", "cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow = "1.0.44"
|
||||||
csv = "1.1.6"
|
csv = "1.1.6"
|
||||||
derive_builder = "0.10.2"
|
derive_builder = "0.10.2"
|
||||||
derive_more = "0.99.14"
|
derive_more = "0.99.14"
|
||||||
|
@ -113,7 +113,7 @@ pub fn main(mut cmd_opts: SubcmdOptions) -> Result<(), i32> {
|
|||||||
}
|
}
|
||||||
"csp" => {
|
"csp" => {
|
||||||
let file = File::open(cmd_opts.infile).expect("IO Error");
|
let file = File::open(cmd_opts.infile).expect("IO Error");
|
||||||
election = parser::csp::parse_reader(file, cmd_opts.require_1, cmd_opts.require_sequential, cmd_opts.require_strict_order);
|
election = parser::csp::parse_reader(file, cmd_opts.require_1, cmd_opts.require_sequential, cmd_opts.require_strict_order).expect("Syntax Error");
|
||||||
}
|
}
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
};
|
};
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
use crate::election::{Ballot, Candidate, Election};
|
use crate::election::{Ballot, Candidate, Election};
|
||||||
use crate::numbers::Number;
|
use crate::numbers::Number;
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
use csv::ReaderBuilder;
|
use csv::ReaderBuilder;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
@ -25,7 +26,7 @@ use std::collections::HashMap;
|
|||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
/// Parse the given CSP file
|
/// Parse the given CSP file
|
||||||
pub fn parse_reader<R: Read, N: Number>(reader: R, require_1: bool, require_sequential: bool, require_strict_order: bool) -> Election<N> {
|
pub fn parse_reader<R: Read, N: Number>(reader: R, require_1: bool, require_sequential: bool, require_strict_order: bool) -> Result<Election<N>> {
|
||||||
// Read CSV file
|
// Read CSV file
|
||||||
let mut reader = ReaderBuilder::new()
|
let mut reader = ReaderBuilder::new()
|
||||||
.has_headers(true)
|
.has_headers(true)
|
||||||
@ -33,14 +34,14 @@ pub fn parse_reader<R: Read, N: Number>(reader: R, require_1: bool, require_sequ
|
|||||||
|
|
||||||
// Read candidates
|
// Read candidates
|
||||||
let mut candidates = Vec::new();
|
let mut candidates = Vec::new();
|
||||||
let mut idx_map = HashMap::new(); // Map csp index -> candidates index
|
let mut col_map = HashMap::new(); // Map csp column -> candidates index
|
||||||
|
|
||||||
for (i, cand_name) in reader.headers().expect("Syntax Error").into_iter().enumerate() {
|
for (i, cand_name) in reader.headers()?.into_iter().enumerate() {
|
||||||
if cand_name == "$mult" {
|
if cand_name == "$mult" {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
idx_map.insert(i, candidates.len());
|
col_map.insert(i, candidates.len());
|
||||||
candidates.push(Candidate {
|
candidates.push(Candidate {
|
||||||
name: cand_name.to_string(),
|
name: cand_name.to_string(),
|
||||||
});
|
});
|
||||||
@ -49,22 +50,22 @@ pub fn parse_reader<R: Read, N: Number>(reader: R, require_1: bool, require_sequ
|
|||||||
// Read ballots
|
// Read ballots
|
||||||
let mut ballots = Vec::new();
|
let mut ballots = Vec::new();
|
||||||
|
|
||||||
for record in reader.into_records() {
|
for (csv_row, record) in reader.into_records().enumerate() {
|
||||||
let record = record.expect("Syntax Error");
|
let record = record?;
|
||||||
|
|
||||||
let mut value = N::one();
|
let mut value = N::one();
|
||||||
|
|
||||||
// Record preferences
|
// Record preferences
|
||||||
let mut preferences = Vec::new(); // Vec of (ranking, candidate index)
|
let mut preferences = Vec::new(); // Vec of (ranking, candidate index)
|
||||||
for (csv_index, preference) in record.into_iter().enumerate() {
|
for (csv_col, preference) in record.into_iter().enumerate() {
|
||||||
match idx_map.get(&csv_index) {
|
match col_map.get(&csv_col) {
|
||||||
Some(cand_index) => {
|
Some(cand_index) => {
|
||||||
// Preference
|
// Preference
|
||||||
if preference.len() == 0 || preference == "-" {
|
if preference.len() == 0 || preference == "-" {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let preference: usize = preference.parse().expect("Syntax Error");
|
let preference: usize = preference.parse().context(format!("Invalid number \"{}\" at row {}, column {}", preference, csv_row + 2, csv_col + 1))?;
|
||||||
if preference == 0 {
|
if preference == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -73,7 +74,7 @@ pub fn parse_reader<R: Read, N: Number>(reader: R, require_1: bool, require_sequ
|
|||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
// $mult column
|
// $mult column
|
||||||
let mult: usize = preference.parse().expect("Syntax Error");
|
let mult: usize = preference.parse().context(format!("Invalid number \"{}\" at row {}, column {}", preference, csv_row + 2, csv_col + 1))?;
|
||||||
if mult == 1 {
|
if mult == 1 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -131,7 +132,7 @@ pub fn parse_reader<R: Read, N: Number>(reader: R, require_1: bool, require_sequ
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return Election {
|
return Ok(Election {
|
||||||
name: String::new(),
|
name: String::new(),
|
||||||
seats: 0,
|
seats: 0,
|
||||||
candidates: candidates,
|
candidates: candidates,
|
||||||
@ -139,5 +140,5 @@ pub fn parse_reader<R: Read, N: Number>(reader: R, require_1: bool, require_sequ
|
|||||||
ballots: ballots,
|
ballots: ballots,
|
||||||
total_votes: None,
|
total_votes: None,
|
||||||
constraints: None,
|
constraints: None,
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user