diff --git a/city-pop/src/main.rs b/city-pop/src/main.rs
index e7a11a969c037e00a796aafeff6258501ec15e9a..6c6dd25a05dbbd729da0dcdea2fcb9323f2612ba 100644
--- a/city-pop/src/main.rs
+++ b/city-pop/src/main.rs
@@ -1,3 +1,71 @@
+extern crate getopts;
+extern crate rustc_serialize;
+extern crate csv;
+
+
+use getopts::Options;
+use std::{env,path,fs};
+
+// 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
+// handling, like parsing strings as integers or floats.
+#[derive(Debug,RustcDecodable)]
+struct Row {
+    country: String,
+    city: String,
+    accent_city: String,
+    region: String,
+
+    // Not every row has data for the population, latitude or longitude!
+    // So we express them as `Option` types, which admits the possibility of
+    // absence. The CSV parser will fill in the correct value for us.
+    population: Option<u64>,
+    latitude: Option<f64>,
+    longitude: Option<f64>,
+}
+
+struct PopulationCount {
+    city: String,
+    country: String
+    // This is no longer an `Option` because values of this type are only
+    // constructed if they have a population count.
+    count: u64,
+}
+
+fn print_usage(program: &str, opts: Options) {
+    println!("{}", opts.usage(&format!("Usage: {} [options] <data-path> <city>",program)));
+}
+
 fn main() {
-    println!("Hello, world!");
+    let args: Vec<String> = env::args().collect();
+    let program = args[0].clone();
+
+    let mut opts = Options::new();
+    opts.optflag("h","help","Show this usage message.");
+
+    let matches = match opts.parse(&args[1..]) {
+        Ok(m) => { m }
+        Err(e) => { panic!(e.to_string()) }
+    };
+    if matches.opt_present("h") {
+        print_usage(&program, opts);
+        return;
+    }
+
+    let data_file = args[1].clone();
+    let data_path = path::Path::new(&data_file);
+    let city = args[2].clone();
+
+    let file = fs::File::open(data_path).unwrap();
+    let mut rdr = csv::Reader::from_reader(file);
+
+    for row in rdr.decode::<Row>() {
+        let row = row.unwrap();
+
+        if row.city == city {
+            println!("{}, {}: {:?}",
+                     row.city, row.country,
+                     row.population.expect("population count"));
+        }
+    }
 }
diff --git a/city-pop/worldcitiespop.csv b/city-pop/worldcitiespop.csv
new file mode 100644
index 0000000000000000000000000000000000000000..8924d325b0697f8499d83bba8c33e942f94fead4
Binary files /dev/null and b/city-pop/worldcitiespop.csv differ