diff --git a/city-pop/src/main.rs b/city-pop/src/main.rs index 7737fce21678db1b68afe3d17a5a51bc24f36260..c82944e783f5a611bf3cfe9cb800a43f3960c2c7 100644 --- a/city-pop/src/main.rs +++ b/city-pop/src/main.rs @@ -5,6 +5,7 @@ extern crate csv; use getopts::Options; use std::{env,path,fs}; +use std::error::Error; // This struct represents the data in each row of the CSV file. // Type based decoding absolves us of a lot of the nitty gritty error @@ -32,13 +33,22 @@ struct PopulationCount { count: u64, } +// We are making use of this impl in the code above, since we call `From::from` +// on a `&'static str`. +//impl<'a, 'b> From<&'b str> for Box<Error + Send + Sync + 'a> + +// But this is also useful when you need to allocate a new string for an +// error message, usually with `format!`. +//impl From<String> for Box<Error + Send + Sync> + fn print_usage(program: &str, opts: Options) { println!("{}", opts.usage(&format!("Usage: {} [options] <data-path> <city>",program))); } -fn search<P: AsRef<path::Path>>(file_path: P, city: &str) -> Vec<PopulationCount> { +fn search<P: AsRef<path::Path>> (file_path: P, city: &str) + -> Result<Vec<PopulationCount>, Box<Error+Send+Sync>> { let mut found = vec![]; - let file = fs::File::open(file_path).unwrap(); + let file = try!(fs::File::open(file_path)); let mut rdr = csv::Reader::from_reader(file); for row in rdr.decode::<Row>() { let row = row.unwrap(); @@ -53,7 +63,11 @@ fn search<P: AsRef<path::Path>>(file_path: P, city: &str) -> Vec<PopulationCount }, } } - found + if found.is_empty() { + Err(From::from("No matching cities with a population were found.")) + } else { + Ok(found) + } } fn main() { @@ -76,7 +90,7 @@ fn main() { let data_path = path::Path::new(&data_file); let city = args[2].clone(); - for pop in search(&data_path, &city) { + for pop in search(&data_path, &city).unwrap() { println!("{}, {}: {:?}",pop.city, pop.country, pop.count); }