| use std::io::{self, Read}; |
| use std::process; |
| |
| use csv_core::{ReadFieldResult, Reader}; |
| |
| fn run(mut data: &[u8]) -> Option<u64> { |
| let mut rdr = Reader::new(); |
| |
| // Count the number of records in Massachusetts. |
| let mut count = 0; |
| // Indicates the current field index. Reset to 0 at start of each record. |
| let mut fieldidx = 0; |
| // True when the current record is in the United States. |
| let mut inus = false; |
| // Buffer for field data. Must be big enough to hold the largest field. |
| let mut field = [0; 1024]; |
| loop { |
| // Attempt to incrementally read the next CSV field. |
| let (result, nread, nwrite) = rdr.read_field(data, &mut field); |
| // nread is the number of bytes read from our input. We should never |
| // pass those bytes to read_field again. |
| data = &data[nread..]; |
| // nwrite is the number of bytes written to the output buffer `field`. |
| // The contents of the buffer after this point is unspecified. |
| let field = &field[..nwrite]; |
| |
| match result { |
| // We don't need to handle this case because we read all of the |
| // data up front. If we were reading data incrementally, then this |
| // would be a signal to read more. |
| ReadFieldResult::InputEmpty => {} |
| // If we get this case, then we found a field that contains more |
| // than 1024 bytes. We keep this example simple and just fail. |
| ReadFieldResult::OutputFull => { |
| return None; |
| } |
| // This case happens when we've successfully read a field. If the |
| // field is the last field in a record, then `record_end` is true. |
| ReadFieldResult::Field { record_end } => { |
| if fieldidx == 0 && field == b"us" { |
| inus = true; |
| } else if inus && fieldidx == 3 && field == b"MA" { |
| count += 1; |
| } |
| if record_end { |
| fieldidx = 0; |
| inus = false; |
| } else { |
| fieldidx += 1; |
| } |
| } |
| // This case happens when the CSV reader has successfully exhausted |
| // all input. |
| ReadFieldResult::End => { |
| break; |
| } |
| } |
| } |
| Some(count) |
| } |
| |
| fn main() { |
| // Read the entire contents of stdin up front. |
| let mut data = vec![]; |
| if let Err(err) = io::stdin().read_to_end(&mut data) { |
| println!("{}", err); |
| process::exit(1); |
| } |
| match run(&data) { |
| None => { |
| println!("error: could not count records, buffer too small"); |
| process::exit(1); |
| } |
| Some(count) => { |
| println!("{}", count); |
| } |
| } |
| } |