sqlitemap 0.2.1

An alternative map implementation, backed by a sqlite database
Documentation
use rusqlite::Row;
use rusqlite::MappedRows;
use rusqlite::Connection;
use rusqlite::Statement;
use rusqlite::Result;
use rusqlite::types::{ToSql, FromSql};

pub struct SqliteMap<'a> {
    replace_key_value: Statement<'a>,
    select_value: Statement<'a>,
    select_key: Statement<'a>,
    select_keys: Statement<'a>,
    select_values: Statement<'a>,
    select_keys_values: Statement<'a>,
    delete_key: Statement<'a>,
    select_count: Statement<'a>,
    select_one: Statement<'a>,
}

impl<'a> SqliteMap<'a> {
    pub fn new(connection: &'a Connection, tablename: &str, keytype: &str, valuetype: &str) -> Result<Self> {
        connection.execute(&format!("
            CREATE TABLE IF NOT EXISTS {} (
                id INTEGER PRIMARY KEY,
                key {} UNIQUE NOT NULL,
                value {} NOT NULL
            )", tablename, keytype, valuetype), &[])?;
        let replace_key_value = connection.prepare(&format!("INSERT OR REPLACE INTO {} (key, value) VALUES (?, ?)", tablename))?;
        let select_value = connection.prepare(&format!("SELECT value FROM {} WHERE key=?", tablename))?;
        let select_key = connection.prepare(&format!("SELECT 1 FROM {} WHERE key=?", tablename))?;
        let select_keys = connection.prepare(&format!("SELECT key FROM {}", tablename))?;
        let select_values = connection.prepare(&format!("SELECT value FROM {}", tablename))?;
        let select_keys_values = connection.prepare(&format!("SELECT key, value FROM {}", tablename))?;
        let delete_key = connection.prepare(&format!("DELETE FROM {} WHERE key=?", tablename))?;
        let select_count = connection.prepare(&format!("SELECT COUNT(*) FROM {}", tablename))?;
        let select_one = connection.prepare(&format!("SELECT 1 FROM {}", tablename))?;

        Ok(Self {
            replace_key_value,
            select_value,
            select_key,
            select_keys,
            select_values,
            select_keys_values,
            delete_key,
            select_count,
            select_one,
        })
    }

    pub fn insert<R>(&mut self, key: &ToSql, value: &ToSql) -> Result<Option<R>>
        where R: FromSql {

        let mut rows = self.select_value.query(&[key])?;
        let output = match rows.next() {
            Some(row) => row?.get_checked(0)?,
            None => None,
        };
        self.replace_key_value.execute(&[key, value])?;
        Ok(output)
    }

    pub fn get<R>(&mut self, key: &ToSql) -> Result<Option<R>>
        where R: FromSql {

        let mut rows = self.select_value.query(&[key])?;
        let row = match rows.next() {
            Some(row) => row?,
            None => return Ok(None),
        };
        Ok(Some(row.get_checked(0)?))
    }

    pub fn keys<R>(&mut self) -> Result<MappedRows<impl FnMut(&Row) -> R>>
        where R: FromSql {

        self.select_keys.query_map(&[], |row| row.get(0))
    }

    pub fn values<R>(&mut self) -> Result<MappedRows<impl FnMut(&Row) -> R>>
        where R: FromSql {

        self.select_values.query_map(&[], |row| row.get(0))
    }

    pub fn iter<K, V>(&mut self) -> Result<MappedRows<impl FnMut(&Row) -> (K, V)>>
        where K: FromSql,
              V: FromSql {

        self.select_keys_values.query_map(&[], |row| (row.get(0), row.get(1)))
    }

    pub fn contains_key(&mut self, key: &ToSql) -> Result<bool> {
        let mut rows = self.select_key.query(&[key])?;
        Ok(match rows.next() {
            Some(Ok(_)) => true,
            Some(Err(x)) => return Err(x),
            None => false,
        })
    }

    pub fn len(&mut self) -> Result<usize> {
        let mut rows = self.select_count.query(&[])?;
        let row = match rows.next() {
            Some(row) => row?,
            None => return Ok(0),
        };
        let size: isize = row.get_checked(0)?;
        Ok(size as usize)
    }

    pub fn remove<R>(&mut self, key: &ToSql) -> Result<Option<R>>
        where R: FromSql {

        let mut rows = self.select_value.query(&[key])?;
        let row = match rows.next() {
            Some(row) => row?,
            None => return Ok(None),
        };
        match row.get_checked(0) {
            Ok(value) => {
                self.delete_key.execute(&[key])?;
                Ok(Some(value))
            },
            Err(x) => Err(x)
        }
    }

    pub fn is_empty(&mut self) -> Result<bool> {
        let mut rows = self.select_one.query(&[])?;
        Ok(match rows.next() {
            Some(Ok(_)) => false,
            Some(Err(x)) => return Err(x),
            None => true,
        })
    }
}