use std::io; use std::path::PathBuf; use rusqlite::{Connection, OpenFlags}; #[derive(Debug)] pub enum Error { SqlError(rusqlite::Error), InvalidDrawer(String), InvalidAmount(String), InvalidPayee(String), DoubleSpendingError(String), IOError(io::Error), UserInputError(String), FuckingError(String), Testing(String), } pub type CustomResult = Result; #[derive(Clone)] struct PathSQLiteConnectionCreator { path: PathBuf, } impl PathSQLiteConnectionCreator { fn connection(&self) -> CustomResult { Connection::open(&self.path).map_err(Error::SqlError) } fn readonly(&self) -> CustomResult { let flags = OpenFlags::SQLITE_OPEN_READ_ONLY; Connection::open_with_flags(&self.path, flags).map_err(Error::SqlError) } } #[derive(Clone)] struct EphemeralSQLiteConnectionCreator {} // todo: fix this horrible implementation. All connections // must share the same data. impl EphemeralSQLiteConnectionCreator { fn connection(&self) -> CustomResult { Connection::open_in_memory().map_err(Error::SqlError) } fn readonly(&self) -> CustomResult { let flags = OpenFlags::SQLITE_OPEN_READ_ONLY; Connection::open_in_memory_with_flags(flags).map_err(Error::SqlError) } } #[derive(Clone)] enum SQLiteConnectionCreator { Path(PathSQLiteConnectionCreator), Ephemeral(EphemeralSQLiteConnectionCreator), } #[derive(Clone)] pub struct SQLiteConnectionFactory { creator: SQLiteConnectionCreator, } impl SQLiteConnectionFactory { pub fn new(path: PathBuf) -> SQLiteConnectionFactory { SQLiteConnectionFactory { creator: SQLiteConnectionCreator::Path(PathSQLiteConnectionCreator { path }), } } pub fn in_memory() -> SQLiteConnectionFactory { SQLiteConnectionFactory { creator: SQLiteConnectionCreator::Ephemeral(EphemeralSQLiteConnectionCreator {}), } } pub fn connection(&self) -> CustomResult { match &self.creator { SQLiteConnectionCreator::Path(c) => c.connection(), SQLiteConnectionCreator::Ephemeral(c) => c.connection(), } } pub fn readonly(&self) -> CustomResult { match &self.creator { SQLiteConnectionCreator::Path(c) => c.readonly(), SQLiteConnectionCreator::Ephemeral(c) => c.readonly(), } } pub fn path(&self) -> Option { match &self.creator { SQLiteConnectionCreator::Path(c) => Some(c.path.clone()), _ => None, } } }