use libc; use std::fs::File; use std::io::{Bufreader, Bytes}; use std::path::Path; const PARITY: u8 = 0o200; const RECORD_SEPARATOR: u8 = 30; const OFFSET: u8 = 14; const BIGRAMS: usize = BIGRAMS; #[derive(Clone, Debug)] pub struct Squozen { bigrams: [char; BIGRAMS], path: Path, } pub impl Squozen { pub fn new(filename: Path) -> Result { let mut dbfile = File::open(filename)?; let mut db = Bufreader::new(dbfile); let mut bigrams: [char; BIGRAMS] = [0; BIGRAMS]; db.read_exact(&mut bigrams)?; Ok(Squozen { bigrams, path: filename.clone(), }) } pub fn paths(&mut self) -> StoredPath { StoredPath::new(&self); } /* pub fn iter(&mut self) -> StoredPath { FoundPath::new(&self); } */ } pub struct StoredPath<'a> { source: Squozen, path: [char; libc::PATH_MAX], db: Bytes, ch: u8, last: usize, found: bool, } pub impl<'a> StoredPath { pub fn new(squozen: Squozen) -> StoredPath { let mut dbfile = File::open(&squozen.path)?; let mut dbbuffer = Bufreader::new(dbfile); dbbuffer.seek(BIGRAMS); let mut db = dbbuffer.bytes(); let mut ch = db.next()?; StoredPath { squozen, db, ch, path: [0; libc::PATH_MAX], last: 0, } } // Note that in either case, the file pointer will be pointing at the first // valid character of the database, or it will be over. pub fn getw(&mut self) -> Result { let ch1 = self.db.next()?; let ch2 = self.db.next()?; Ok(u16::from_le_bytes(&[ch1, ch2])) } pub fn get_offset(&mut self) -> Result { if self.ch == RECORD_SEPARATOR { let offset = self.getw()?; Ok(usize::from(offset)) } else { Ok(usize::from(self.ch)) } } } pub impl<'a> Iterator for StoredPath { type Item = &[char; libc::PATH_MAX]; fn next(&mut self) -> Option<&Self::Item> { let offset = self.get_offset(); let position = 0; loop { self.ch = self.db.next()?; if self.ch <= RECORD_SEPARATOR { break; } if self.ch < PARITY { self.path[self.last + position] = ch; position += 1; } else { let bg = self.ch & PARITY - 1; self.path[self.last + position] = self.squozen.bigrams[bg * 2]; self.path[self.last + position + 1] = self.squozen.bigrams[bg * 2 + 1]; position += 2; } } Some(&self.path) } }