db_map/
db_map.rs

1use std::marker::PhantomData;
2use rusqlite::{Connection, params, ToSql, types::FromSql};
3use anyhow::Result;
4
5#[derive(Debug, Clone)]
6pub struct DBMap<K, V> {
7    path: String,
8    key_type: PhantomData<K>,
9    value_type: PhantomData<V>
10}
11
12impl<K, V> DBMap<K, V> {
13    pub fn new(db_path: &str) -> Result<Self> {
14        let conn = Connection::open(db_path)?;
15        conn.execute(
16            "CREATE TABLE IF NOT EXISTS Map (
17                key BLOB PRIMARY KEY,
18                value BLOB
19            )",
20            [],
21        )?;
22        Ok(DBMap {
23            path: db_path.to_string(),
24            key_type: PhantomData,
25            value_type: PhantomData
26        })
27    }
28}
29
30impl<K: ToSql, V: ToSql> DBMap<K, V> {
31    pub fn insert(&self, key: K, value: V) -> Result<()> {
32        let conn = Connection::open(&self.path)?;
33        conn.execute(
34            "INSERT OR REPLACE INTO Map (key, value)
35            VALUES (?1, ?2)", 
36            params![key, value]
37        )?;
38        Ok(())
39    }
40}
41
42impl<K: ToSql, V: FromSql> DBMap<K, V> {
43    pub fn get(&self, key: K) -> Result<V> {
44        let conn = Connection::open(&self.path)?;
45        let mut stmt = conn
46            .prepare("SELECT value FROM Map WHERE key = ?1")
47            .unwrap();
48        let value = stmt
49            .query_row([key], |row| {
50                row.get::<usize, V>(0)
51            })?;
52        Ok(value)
53    }
54}
55
56impl<K: FromSql, V: ToSql> DBMap<K, V> {
57    pub fn get_keys(&self, value: V) -> Result<Vec<K>> {
58        let conn = Connection::open(&self.path)?;
59        let mut stmt = conn
60            .prepare("SELECT key FROM Map WHERE value = ?1")
61            .unwrap();
62        let values = stmt
63            .query_map([value], |row| {
64                row.get::<usize, K>(0)
65            })?
66            .collect::<Result<Vec<K>, rusqlite::Error>>()?;
67        Ok(values)
68    }
69}