use std::path::Path;
use crate::{
Error, Result,
format::{DbFile, DbKind},
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OptionRecord {
pub name: String,
pub summary: Option<String>,
}
#[derive(Debug)]
pub struct OptionsDb {
db: DbFile,
}
impl OptionsDb {
pub(crate) fn from_file(db: DbFile) -> Self {
Self { db }
}
pub fn open(path: impl AsRef<Path>) -> Result<Self> {
let db = DbFile::open(path)?;
if db.kind != DbKind::Options {
return Err(Error::InvalidDatabase(
"expected an options database (kind = options)".into(),
));
}
Ok(Self { db })
}
pub fn query(&self, query: &str) -> Result<Vec<OptionRecord>> {
let bucket = DbFile::query_bucket(query);
let lines = self.db.bucket_lines(bucket)?;
let mut records = Vec::new();
for line in &lines {
let (name, summary) = split_tab(line);
if name.contains(query) {
records.push(OptionRecord {
name: name.to_owned(),
summary: summary.filter(|s| !s.is_empty()).map(str::to_owned),
});
}
}
Ok(records)
}
}
fn split_tab(line: &str) -> (&str, Option<&str>) {
match line.find('\t') {
Some(tab) => (&line[..tab], Some(&line[tab + 1..])),
None => (line, None),
}
}