use std::io; use std::ops; use csv; use csv_index::RandomAccessSimple; use CliResult; /// Indexed composes a CSV reader with a simple random access index. pub struct Indexed { csv_rdr: csv::Reader, idx: RandomAccessSimple, } impl ops::Deref for Indexed { type Target = csv::Reader; fn deref(&self) -> &csv::Reader { &self.csv_rdr } } impl ops::DerefMut for Indexed { fn deref_mut(&mut self) -> &mut csv::Reader { &mut self.csv_rdr } } impl Indexed { /// Opens an index. pub fn open( csv_rdr: csv::Reader, idx_rdr: I, ) -> CliResult> { Ok(Indexed { csv_rdr: csv_rdr, idx: RandomAccessSimple::open(idx_rdr)?, }) } /// Return the number of records (not including the header record) in this /// index. pub fn count(&self) -> u64 { if self.csv_rdr.has_headers() && !self.idx.is_empty() { self.idx.len() - 1 } else { self.idx.len() } } /// Seek to the starting position of record `i`. pub fn seek(&mut self, mut i: u64) -> CliResult<()> { if i >= self.count() { let msg = format!( "invalid record index {} (there are {} records)", i, self.count()); return fail!(io::Error::new(io::ErrorKind::Other, msg)); } if self.csv_rdr.has_headers() { i += 1; } let pos = self.idx.get(i)?; self.csv_rdr.seek(pos)?; Ok(()) } }