use anyhow::{Context, Result};
use std::io::Read;
use std::path::Path;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Kind {
Sqlite,
Rkyv,
}
const SQLITE_MAGIC: &[u8] = b"SQLite format 3\0";
pub fn detect(path: &Path, force_sqlite: bool, force_rkyv: bool) -> Result<Kind> {
if force_sqlite {
return Ok(Kind::Sqlite);
}
if force_rkyv {
return Ok(Kind::Rkyv);
}
let mut buf = [0u8; 16];
let mut f = std::fs::File::open(path).with_context(|| format!("open {}", path.display()))?;
let n = f.read(&mut buf)?;
if n >= SQLITE_MAGIC.len() {
return Ok(if &buf[..SQLITE_MAGIC.len()] == SQLITE_MAGIC {
Kind::Sqlite
} else {
Kind::Rkyv
});
}
match path.extension().and_then(|e| e.to_str()) {
Some("db") | Some("sqlite") | Some("sqlite3") => Ok(Kind::Sqlite),
_ => Ok(Kind::Rkyv),
}
}
pub enum Store {
Sqlite(crate::sqlite::SqliteStore),
Rkyv(crate::rkyv_inspect::RkyvStore),
}
impl Store {
pub fn open(path: &Path, kind: Kind) -> Result<(Self, Kind)> {
match kind {
Kind::Sqlite => match crate::sqlite::SqliteStore::open(path) {
Ok(s) => Ok((Store::Sqlite(s), Kind::Sqlite)),
Err(_) => {
let r = crate::rkyv_inspect::RkyvStore::open(path)?;
Ok((Store::Rkyv(r), Kind::Rkyv))
}
},
Kind::Rkyv => {
let r = crate::rkyv_inspect::RkyvStore::open(path)?;
Ok((Store::Rkyv(r), Kind::Rkyv))
}
}
}
}