• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::env;
2 use std::error::Error;
3 use std::io;
4 use std::process;
5 
6 use serde::{Deserialize, Serialize};
7 
8 // Unlike previous examples, we derive both Deserialize and Serialize. This
9 // means we'll be able to automatically deserialize and serialize this type.
10 #[derive(Debug, Deserialize, Serialize)]
11 #[serde(rename_all = "PascalCase")]
12 struct Record {
13     city: String,
14     state: String,
15     population: Option<u64>,
16     latitude: f64,
17     longitude: f64,
18 }
19 
run() -> Result<(), Box<dyn Error>>20 fn run() -> Result<(), Box<dyn Error>> {
21     // Get the query from the positional arguments.
22     // If one doesn't exist or isn't an integer, return an error.
23     let minimum_pop: u64 = match env::args().nth(1) {
24         None => return Err(From::from("expected 1 argument, but got none")),
25         Some(arg) => arg.parse()?,
26     };
27 
28     // Build CSV readers and writers to stdin and stdout, respectively.
29     // Note that we don't need to write headers explicitly. Since we're
30     // serializing a custom struct, that's done for us automatically.
31     let mut rdr = csv::Reader::from_reader(io::stdin());
32     let mut wtr = csv::Writer::from_writer(io::stdout());
33 
34     // Iterate over all the records in `rdr`, and write only records containing
35     // a population that is greater than or equal to `minimum_pop`.
36     for result in rdr.deserialize() {
37         // Remember that when deserializing, we must use a type hint to
38         // indicate which type we want to deserialize our record into.
39         let record: Record = result?;
40 
41         // `map_or` is a combinator on `Option`. It take two parameters:
42         // a value to use when the `Option` is `None` (i.e., the record has
43         // no population count) and a closure that returns another value of
44         // the same type when the `Option` is `Some`. In this case, we test it
45         // against our minimum population count that we got from the command
46         // line.
47         if record.population.map_or(false, |pop| pop >= minimum_pop) {
48             wtr.serialize(record)?;
49         }
50     }
51 
52     // CSV writers use an internal buffer, so we should always flush when done.
53     wtr.flush()?;
54     Ok(())
55 }
56 
main()57 fn main() {
58     if let Err(err) = run() {
59         println!("{}", err);
60         process::exit(1);
61     }
62 }
63