use std::path::Path;
use crate::{
Error, Result,
format::{DbFile, DbKind},
};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileRecord {
pub path: String,
pub packages: Vec<String>,
}
#[derive(Debug)]
pub struct PackagesDb {
db: DbFile,
}
impl PackagesDb {
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::Packages {
return Err(Error::InvalidDatabase(
"expected a packages database (kind = packages)".into(),
));
}
Ok(Self { db })
}
pub fn query(&self, query: &str) -> Result<Vec<FileRecord>> {
let bucket = DbFile::query_bucket(query);
let lines = self.db.bucket_lines(bucket)?;
let mut records = Vec::new();
for line in &lines {
if let Some(tab) = line.find('\t') {
let path = &line[..tab];
if path.contains(query) {
let packages = line[tab + 1..]
.split(',')
.filter(|s| !s.is_empty())
.map(str::to_owned)
.collect();
records.push(FileRecord {
path: path.to_owned(),
packages,
});
}
}
}
Ok(records)
}
}