1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
use std::convert::TryFrom; use std::fs::File; use std::io::{BufRead, BufReader}; use std::path::Path; use std::rc::Rc; use rusqlite::{Connection, NO_PARAMS}; mod autojump; mod brave; mod histfile; mod mcfly; pub struct ProviderInfo { pub name: String, pub size: usize, } type ProviderError = String; pub trait Provider { fn info(&self) -> &ProviderInfo; fn search(&self, term: &str) -> Result<Vec<String>, ProviderError>; } pub fn available() -> (Vec<Rc<Provider>>, Vec<String>) { let mut out: Vec<Rc<Provider>> = Vec::new(); let mut errors: Vec<String> = Vec::new(); if let Ok(p) = autojump::build() { out.push(Rc::new(p)) } match brave::build() { Ok(p) => out.push(Rc::new(p)), Err(e) => errors.push(e), } if let Ok(p) = histfile::build() { out.push(Rc::new(p)); } if let Ok(p) = mcfly::build() { out.push(Rc::new(p)); } (out, errors) } #[allow(dead_code)] pub fn lines_in_file(path: &Path) -> Result<usize, ProviderError> { let file = File::open(&path).map_err(|_e| "file error".to_owned())?; let br = BufReader::new(file); Ok(br.lines().count()) } pub struct Db { connection: Connection, table_name: String, } impl Db { pub fn open(path: &Path, table_name: &str) -> Result<Db, String> { let connection = Connection::open(path) .map_err(|e| format!("db open sqlite error {:?}, db {:?}", e, path))?; Ok(Db { connection, table_name: table_name.to_owned(), }) } fn count(&self) -> Result<usize, String> { let result: isize = self .connection .query_row( &format!("select count(rowid) from {}", self.table_name), NO_PARAMS, |row| row.get(0), ) .map_err(|e| format!("db count got sqlite query {:?}", e))?; usize::try_from(result).map_err(|_| "bad isize".to_owned()) } } pub fn read_lines(path: &Path) -> Result<Vec<String>, ProviderError> { let mut data = Vec::new(); let file = File::open(path).map_err(|_e| "file error".to_owned())?; let br = BufReader::new(file); for line in br.lines() { if let Ok(line) = line { data.push(line); } } Ok(data) } pub fn search(term: &str, data: &[String]) -> Result<Vec<String>, String> { let mut out = Vec::new(); for d in data.iter() { if d.contains(term) { out.push(d.clone()); } } Ok(out) }