use crate::oyster::Oyster;
use crate::pearl::{Pearl, ResourceDescriptor};
use pathbufd::PathBufD;
use rusqlite::{Connection, Result};
use std::hash::Hash;
use std::{fs, sync::LazyLock};
pub static PATH: LazyLock<PathBufD> = LazyLock::new(|| PathBufD::current().extend(&["dump.db"]));
impl<K, V> Oyster<K, V>
where
K: Hash + Ord + Clone + Send + ToString + From<String>,
V: Clone + Send + ToString + From<String>,
{
pub fn dump(&self) -> Result<()> {
if fs::exists(PATH.as_ref()).unwrap_or(false) {
if let Err(e) = fs::remove_file(PATH.as_ref()) {
panic!("{}", e);
};
}
if let Err(e) = fs::write(PATH.to_string(), []) {
panic!("{}", e);
};
let conn = Connection::open(PATH.as_ref())?;
conn.execute(
"CREATE TABLE map (
key TEXT NOT NULL,
value TEXT NOT NULL,
used INT
)",
(),
)?;
for (k, v) in &self.0 {
conn.execute(
"INSERT INTO \"map\" VALUES (?, ?, ?)",
(k.to_string(), v.0.to_string(), v.1.used),
)?;
}
Ok(())
}
pub fn restore(&mut self) -> Result<()> {
if !fs::exists(PATH.as_ref()).unwrap_or(false) {
return Ok(());
}
let conn = Connection::open(PATH.as_ref())?;
let mut query = conn.prepare("SELECT \"key\", \"value\", \"used\" FROM \"map\"")?;
let iter = query.query_map([], |row| {
Ok((
row.get::<usize, String>(0)?,
row.get::<usize, String>(1)?,
row.get::<usize, usize>(2)?,
))
})?;
for i in iter {
let (key, value, used) = i.unwrap();
self.insert_full(
key.into(),
Pearl(
value.into(),
ResourceDescriptor {
#[cfg(feature = "lru")]
used,
},
),
);
}
Ok(())
}
}