From 5effd63575a6e2bc7af7a45ae0ae92323be5ab84 Mon Sep 17 00:00:00 2001 From: yggverse Date: Fri, 7 Mar 2025 18:14:37 +0200 Subject: [PATCH] use anyhow crate, return id on insert --- Cargo.toml | 1 + src/app.rs | 10 +- src/app/browser.rs | 80 ++++------- src/app/browser/database.rs | 24 ++-- src/app/browser/widget.rs | 63 +++----- src/app/browser/widget/database.rs | 25 ++-- src/app/browser/window.rs | 68 +++------ src/app/browser/window/database.rs | 24 ++-- src/app/browser/window/tab.rs | 135 +++++++----------- src/app/browser/window/tab/database.rs | 24 ++-- src/app/browser/window/tab/item.rs | 53 ++----- src/app/browser/window/tab/item/database.rs | 26 ++-- src/app/browser/window/tab/item/page.rs | 71 ++++----- .../browser/window/tab/item/page/database.rs | 26 ++-- .../window/tab/item/page/navigation.rs | 56 +++----- .../tab/item/page/navigation/bookmark.rs | 2 +- .../tab/item/page/navigation/database.rs | 29 ++-- .../tab/item/page/navigation/request.rs | 77 ++++------ .../item/page/navigation/request/database.rs | 27 ++-- src/main.rs | 2 +- src/profile.rs | 51 ++----- src/profile/bookmark.rs | 46 +++--- src/profile/bookmark/database.rs | 68 +++------ src/profile/bookmark/error.rs | 8 -- src/profile/bookmark/memory.rs | 21 ++- src/profile/bookmark/memory/error.rs | 18 --- src/profile/database.rs | 46 +++--- src/profile/history/database.rs | 80 ----------- src/profile/identity.rs | 71 +++------ src/profile/identity/auth.rs | 67 +++------ src/profile/identity/auth/database.rs | 61 +++----- src/profile/identity/auth/error.rs | 16 --- src/profile/identity/auth/memory.rs | 14 +- src/profile/identity/auth/memory/error.rs | 20 --- src/profile/identity/error.rs | 24 ---- src/profile/identity/item.rs | 8 +- src/profile/identity/item/error.rs | 15 -- src/profile/identity/memory.rs | 18 ++- src/profile/identity/memory/error.rs | 22 --- src/profile/search.rs | 66 +++------ src/profile/search/database.rs | 81 ++++------- src/profile/search/error.rs | 16 --- 42 files changed, 496 insertions(+), 1164 deletions(-) delete mode 100644 src/profile/bookmark/error.rs delete mode 100644 src/profile/bookmark/memory/error.rs delete mode 100644 src/profile/history/database.rs delete mode 100644 src/profile/identity/auth/error.rs delete mode 100644 src/profile/identity/auth/memory/error.rs delete mode 100644 src/profile/identity/error.rs delete mode 100644 src/profile/identity/item/error.rs delete mode 100644 src/profile/identity/memory/error.rs delete mode 100644 src/profile/search/error.rs diff --git a/Cargo.toml b/Cargo.toml index f3a8452e..45be17ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ version = "0.9.1" [dependencies] ansi-parser = "0.9.1" +anyhow = "1.0.97" ggemini = "0.17.0" ggemtext = "0.3.1" indexmap = "2.7.0" diff --git a/src/app.rs b/src/app.rs index 90a1d8d9..5bfdce66 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,10 +1,10 @@ pub mod browser; mod database; -use browser::Browser; - use crate::profile::Profile; use adw::Application; +use anyhow::Result; +use browser::Browser; use gtk::{ glib::ExitCode, prelude::{ActionExt, ApplicationExt, ApplicationExtManual, GtkApplicationExt}, @@ -294,11 +294,9 @@ impl App { } // Tools -fn migrate(tx: &Transaction) -> Result<(), String> { +fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components - if let Err(e) = database::init(tx) { - return Err(e.to_string()); - } + database::init(tx)?; // Delegate migration to childs browser::migrate(tx)?; diff --git a/src/app/browser.rs b/src/app/browser.rs index a120050a..df5f3c76 100644 --- a/src/app/browser.rs +++ b/src/app/browser.rs @@ -11,6 +11,7 @@ use window::Window; use crate::Profile; use adw::{prelude::AdwDialogExt, AboutDialog, Application}; +use anyhow::Result; use gtk::{ gio::{Cancellable, File}, prelude::GtkWindowExt, @@ -109,70 +110,43 @@ impl Browser { // Actions - pub fn clean(&self, transaction: &Transaction, app_id: i64) -> Result<(), String> { - match database::select(transaction, app_id) { - Ok(records) => { - for record in records { - match database::delete(transaction, record.id) { - Ok(_) => { - // Delegate clean action to childs - self.window.clean(transaction, record.id)?; - self.widget.clean(transaction, record.id)?; - - /* @TODO - self.header.clean(transaction, &record.id)?; */ - } - Err(e) => return Err(e.to_string()), - } - } - } - Err(e) => return Err(e.to_string()), + pub fn clean(&self, transaction: &Transaction, app_id: i64) -> Result<()> { + for record in database::select(transaction, app_id)? { + database::delete(transaction, record.id)?; + // Delegate clean action to childs + self.window.clean(transaction, record.id)?; + self.widget.clean(transaction, record.id)?; + /* @TODO + self.header.clean(transaction, &record.id)?; */ } - Ok(()) } - pub fn restore(&self, transaction: &Transaction, app_id: i64) -> Result<(), String> { - match database::select(transaction, app_id) { - Ok(records) => { - for record in records { - // Delegate restore action to childs - self.widget.restore(transaction, record.id)?; - self.window.restore(transaction, record.id)?; - - /* @TODO - self.header.restore(transaction, &record.id)?; */ - } - } - Err(e) => return Err(e.to_string()), + pub fn restore(&self, transaction: &Transaction, app_id: i64) -> Result<()> { + for record in database::select(transaction, app_id)? { + // Delegate restore action to childs + self.widget.restore(transaction, record.id)?; + self.window.restore(transaction, record.id)?; + /* @TODO + self.header.restore(transaction, &record.id)?; */ } - Ok(()) } - pub fn save(&self, transaction: &Transaction, app_id: i64) -> Result<(), String> { - match database::insert(transaction, app_id) { - Ok(_) => { - let id = database::last_insert_id(transaction); - - // Delegate save action to childs - self.widget.save(transaction, id)?; - self.window.save(transaction, id)?; - - /* @TODO - self.header.save(transaction, &id)?; */ - } - Err(e) => return Err(e.to_string()), - } - + pub fn save(&self, transaction: &Transaction, app_id: i64) -> Result<()> { + let id = database::insert(transaction, app_id)?; + // Delegate save action to childs + self.widget.save(transaction, id)?; + self.window.save(transaction, id)?; + /* @TODO + self.header.save(transaction, &id)?; */ Ok(()) } pub fn init(&self, application: Option<&Application>) -> &Self { // Assign browser window to this application self.widget.application_window.set_application(application); // @TODO - - // Init main window + // Init main window self.window.init(); self } @@ -184,11 +158,9 @@ impl Browser { } // Tools -pub fn migrate(tx: &Transaction) -> Result<(), String> { +pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components - if let Err(e) = database::init(tx) { - return Err(e.to_string()); - } + database::init(tx)?; // Delegate migration to childs /* @TODO diff --git a/src/app/browser/database.rs b/src/app/browser/database.rs index 37d6d30f..2dc8fff9 100644 --- a/src/app/browser/database.rs +++ b/src/app/browser/database.rs @@ -1,12 +1,13 @@ -use sqlite::{Error, Transaction}; +use anyhow::Result; +use sqlite::Transaction; pub struct Table { pub id: i64, // pub app_id: i64, not in use } -pub fn init(tx: &Transaction) -> Result { - tx.execute( +pub fn init(tx: &Transaction) -> Result { + Ok(tx.execute( "CREATE TABLE IF NOT EXISTS `app_browser` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, @@ -15,14 +16,15 @@ pub fn init(tx: &Transaction) -> Result { FOREIGN KEY (`app_id`) REFERENCES `app`(`id`) )", [], - ) + )?) } -pub fn insert(tx: &Transaction, app_id: i64) -> Result { - tx.execute("INSERT INTO `app_browser` (`app_id`) VALUES (?)", [app_id]) +pub fn insert(tx: &Transaction, app_id: i64) -> Result { + tx.execute("INSERT INTO `app_browser` (`app_id`) VALUES (?)", [app_id])?; + Ok(tx.last_insert_rowid()) } -pub fn select(tx: &Transaction, app_id: i64) -> Result, Error> { +pub fn select(tx: &Transaction, app_id: i64) -> Result> { let mut stmt = tx.prepare("SELECT `id`, `app_id` FROM `app_browser` WHERE `app_id` = ?")?; let result = stmt.query_map([app_id], |row| { @@ -42,10 +44,6 @@ pub fn select(tx: &Transaction, app_id: i64) -> Result, Error> { Ok(records) } -pub fn delete(tx: &Transaction, id: i64) -> Result { - tx.execute("DELETE FROM `app_browser` WHERE `id` = ?", [id]) -} - -pub fn last_insert_id(tx: &Transaction) -> i64 { - tx.last_insert_rowid() +pub fn delete(tx: &Transaction, id: i64) -> Result { + Ok(tx.execute("DELETE FROM `app_browser` WHERE `id` = ?", [id])?) } diff --git a/src/app/browser/widget.rs b/src/app/browser/widget.rs index 931d3ae3..4e618fa7 100644 --- a/src/app/browser/widget.rs +++ b/src/app/browser/widget.rs @@ -2,6 +2,7 @@ mod database; use super::Window; use adw::ApplicationWindow; +use anyhow::Result; use gtk::{ gio::SimpleActionGroup, glib::GString, @@ -59,74 +60,44 @@ impl Widget { } // Actions - pub fn clean(&self, transaction: &Transaction, app_browser_id: i64) -> Result<(), String> { - match database::select(transaction, app_browser_id) { - Ok(records) => { - for record in records { - match database::delete(transaction, record.id) { - Ok(_) => { - // Delegate clean action to childs - // nothing yet.. - } - Err(e) => return Err(e.to_string()), - } - } - } - Err(e) => return Err(e.to_string()), + pub fn clean(&self, transaction: &Transaction, app_browser_id: i64) -> Result<()> { + for record in database::select(transaction, app_browser_id)? { + database::delete(transaction, record.id)?; } - Ok(()) } - pub fn restore(&self, transaction: &Transaction, app_browser_id: i64) -> Result<(), String> { - match database::select(transaction, app_browser_id) { - Ok(records) => { - for record in records { - // Restore widget - self.application_window.set_maximized(record.is_maximized); - self.application_window - .set_default_size(record.default_width, record.default_height); + pub fn restore(&self, transaction: &Transaction, app_browser_id: i64) -> Result<()> { + for record in database::select(transaction, app_browser_id)? { + // Restore widget + self.application_window.set_maximized(record.is_maximized); + self.application_window + .set_default_size(record.default_width, record.default_height); - // Delegate restore action to childs - // nothing yet.. - } - } - Err(e) => return Err(e.to_string()), + // Delegate restore action to childs + // nothing yet.. } - Ok(()) } - pub fn save(&self, transaction: &Transaction, app_browser_id: i64) -> Result<(), String> { - match database::insert( + pub fn save(&self, transaction: &Transaction, app_browser_id: i64) -> Result<()> { + database::insert( transaction, app_browser_id, self.application_window.default_width(), self.application_window.default_height(), self.application_window.is_maximized(), - ) { - Ok(_) => { - // Delegate save action to childs - // let id = self.database.last_insert_id(transaction); - // nothing yet.. - } - Err(e) => return Err(e.to_string()), - } - + )?; Ok(()) } } // Tools -pub fn migrate(tx: &Transaction) -> Result<(), String> { +pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components - if let Err(e) = database::init(tx) { - return Err(e.to_string()); - } - + database::init(tx)?; // Delegate migration to childs // nothing yet.. - // Success Ok(()) } diff --git a/src/app/browser/widget/database.rs b/src/app/browser/widget/database.rs index b1315522..705536f1 100644 --- a/src/app/browser/widget/database.rs +++ b/src/app/browser/widget/database.rs @@ -1,4 +1,5 @@ -use sqlite::{Error, Transaction}; +use anyhow::Result; +use sqlite::Transaction; pub struct Table { pub id: i64, @@ -8,8 +9,8 @@ pub struct Table { pub is_maximized: bool, } -pub fn init(tx: &Transaction) -> Result { - tx.execute( +pub fn init(tx: &Transaction) -> Result { + Ok(tx.execute( "CREATE TABLE IF NOT EXISTS `app_browser_widget` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, @@ -21,7 +22,7 @@ pub fn init(tx: &Transaction) -> Result { FOREIGN KEY (`app_browser_id`) REFERENCES `app_browser`(`id`) )", [], - ) + )?) } pub fn insert( @@ -30,7 +31,7 @@ pub fn insert( default_width: i32, default_height: i32, is_maximized: bool, -) -> Result { +) -> Result { tx.execute( "INSERT INTO `app_browser_widget` ( `app_browser_id`, @@ -44,10 +45,11 @@ pub fn insert( default_height as i64, is_maximized as i64, ], - ) + )?; + Ok(tx.last_insert_rowid()) } -pub fn select(tx: &Transaction, app_browser_id: i64) -> Result, Error> { +pub fn select(tx: &Transaction, app_browser_id: i64) -> Result> { let mut stmt = tx.prepare( "SELECT `id`, `app_browser_id`, @@ -76,11 +78,6 @@ pub fn select(tx: &Transaction, app_browser_id: i64) -> Result, Error Ok(records) } -pub fn delete(tx: &Transaction, id: i64) -> Result { - tx.execute("DELETE FROM `app_browser_widget` WHERE `id` = ?", [id]) +pub fn delete(tx: &Transaction, id: i64) -> Result { + Ok(tx.execute("DELETE FROM `app_browser_widget` WHERE `id` = ?", [id])?) } - -/* not in use -pub fn last_insert_id(tx: &Transaction) -> i64 { - tx.last_insert_rowid() -} */ diff --git a/src/app/browser/window.rs b/src/app/browser/window.rs index 710b2fb7..9dc70ff3 100644 --- a/src/app/browser/window.rs +++ b/src/app/browser/window.rs @@ -3,16 +3,16 @@ mod database; mod header; pub mod tab; -use action::{Action, Position}; -use adw::ToolbarView; -use header::Header; -use sqlite::Transaction; -use tab::Tab; - use super::Action as BrowserAction; use crate::Profile; +use action::{Action, Position}; +use adw::ToolbarView; +use anyhow::Result; use gtk::{prelude::BoxExt, Box, Orientation}; +use header::Header; +use sqlite::Transaction; use std::rc::Rc; +use tab::Tab; pub struct Window { pub action: Rc, @@ -145,52 +145,26 @@ impl Window { self.tab.escape(); } - pub fn clean(&self, transaction: &Transaction, app_browser_id: i64) -> Result<(), String> { - match database::select(transaction, app_browser_id) { - Ok(records) => { - for record in records { - match database::delete(transaction, record.id) { - Ok(_) => { - // Delegate clean action to childs - self.tab.clean(transaction, record.id)?; - } - Err(e) => return Err(e.to_string()), - } - } - } - Err(e) => return Err(e.to_string()), + pub fn clean(&self, transaction: &Transaction, app_browser_id: i64) -> Result<()> { + for record in database::select(transaction, app_browser_id)? { + database::delete(transaction, record.id)?; + // Delegate clean action to childs + self.tab.clean(transaction, record.id)?; } Ok(()) } - pub fn restore(&self, transaction: &Transaction, app_browser_id: i64) -> Result<(), String> { - match database::select(transaction, app_browser_id) { - Ok(records) => { - for record in records { - // Delegate restore action to childs - self.tab.restore(transaction, record.id)?; - } - } - Err(e) => return Err(e.to_string()), + pub fn restore(&self, transaction: &Transaction, app_browser_id: i64) -> Result<()> { + for record in database::select(transaction, app_browser_id)? { + // Delegate restore action to childs + self.tab.restore(transaction, record.id)?; } - Ok(()) } - pub fn save(&self, transaction: &Transaction, app_browser_id: i64) -> Result<(), String> { - match database::insert(transaction, app_browser_id) { - Ok(_) => { - // Delegate save action to childs - if let Err(e) = self - .tab - .save(transaction, database::last_insert_id(transaction)) - { - return Err(e.to_string()); - } - } - Err(e) => return Err(e.to_string()), - } - + pub fn save(&self, transaction: &Transaction, app_browser_id: i64) -> Result<()> { + self.tab + .save(transaction, database::insert(transaction, app_browser_id)?)?; Ok(()) } @@ -200,11 +174,9 @@ impl Window { } // Tools -pub fn migrate(tx: &Transaction) -> Result<(), String> { +pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components - if let Err(e) = database::init(tx) { - return Err(e.to_string()); - } + database::init(tx)?; // Delegate migration to childs tab::migrate(tx)?; diff --git a/src/app/browser/window/database.rs b/src/app/browser/window/database.rs index 75ba1d55..70a3e688 100644 --- a/src/app/browser/window/database.rs +++ b/src/app/browser/window/database.rs @@ -1,12 +1,13 @@ -use sqlite::{Error, Transaction}; +use anyhow::Result; +use sqlite::Transaction; pub struct Table { pub id: i64, // pub app_browser_id: i64, not in use } -pub fn init(tx: &Transaction) -> Result { - tx.execute( +pub fn init(tx: &Transaction) -> Result { + Ok(tx.execute( "CREATE TABLE IF NOT EXISTS `app_browser_window` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, @@ -15,17 +16,18 @@ pub fn init(tx: &Transaction) -> Result { FOREIGN KEY (`app_browser_id`) REFERENCES `app_browser`(`id`) )", [], - ) + )?) } -pub fn insert(tx: &Transaction, app_browser_id: i64) -> Result { +pub fn insert(tx: &Transaction, app_browser_id: i64) -> Result { tx.execute( "INSERT INTO `app_browser_window` (`app_browser_id`) VALUES (?)", [app_browser_id], - ) + )?; + Ok(tx.last_insert_rowid()) } -pub fn select(tx: &Transaction, app_browser_id: i64) -> Result, Error> { +pub fn select(tx: &Transaction, app_browser_id: i64) -> Result> { let mut stmt = tx.prepare( "SELECT `id`, `app_browser_id` FROM `app_browser_window` @@ -49,10 +51,6 @@ pub fn select(tx: &Transaction, app_browser_id: i64) -> Result, Error Ok(records) } -pub fn delete(tx: &Transaction, id: i64) -> Result { - tx.execute("DELETE FROM `app_browser_window` WHERE `id` = ?", [id]) -} - -pub fn last_insert_id(tx: &Transaction) -> i64 { - tx.last_insert_rowid() +pub fn delete(tx: &Transaction, id: i64) -> Result { + Ok(tx.execute("DELETE FROM `app_browser_window` WHERE `id` = ?", [id])?) } diff --git a/src/app/browser/window/tab.rs b/src/app/browser/window/tab.rs index 5f1b4bc5..f7bc8bd8 100644 --- a/src/app/browser/window/tab.rs +++ b/src/app/browser/window/tab.rs @@ -8,6 +8,7 @@ use super::{Action as WindowAction, BrowserAction, Position}; use crate::Profile; use action::Action; use adw::{TabPage, TabView}; +use anyhow::Result; use error::Error; use gtk::{ gio::Icon, @@ -309,102 +310,68 @@ impl Tab { } } - pub fn clean( - &self, - transaction: &Transaction, - app_browser_window_id: i64, - ) -> Result<(), String> { - match database::select(transaction, app_browser_window_id) { - Ok(records) => { - for record in records { - match database::delete(transaction, record.id) { - Ok(_) => { - // Delegate clean action to childs - for (_, item) in self.index.borrow().iter() { - item.clean(transaction, record.id)? - } - } - Err(e) => return Err(e.to_string()), - } - } + pub fn clean(&self, transaction: &Transaction, app_browser_window_id: i64) -> Result<()> { + for record in database::select(transaction, app_browser_window_id)? { + database::delete(transaction, record.id)?; + // Delegate clean action to childs + for (_, item) in self.index.borrow().iter() { + item.clean(transaction, record.id)? } - Err(e) => return Err(e.to_string()), } Ok(()) } - pub fn restore( - &self, - transaction: &Transaction, - app_browser_window_id: i64, - ) -> Result<(), String> { - match database::select(transaction, app_browser_window_id) { - Ok(tab_records) => { - for tab_record in tab_records { - for item_record in item::restore(transaction, tab_record.id)? { - // Generate new `TabPage` with blank `Widget` - let (tab_page, target_child) = new_tab_page( - &self.tab_view, - Position::Number(item_record.page_position), - ); + pub fn restore(&self, transaction: &Transaction, app_browser_window_id: i64) -> Result<()> { + for tab_record in database::select(transaction, app_browser_window_id)? { + for item_record in item::restore(transaction, tab_record.id)? { + // Generate new `TabPage` with blank `Widget` + let (tab_page, target_child) = + new_tab_page(&self.tab_view, Position::Number(item_record.page_position)); - // Init new tab item - let item = Rc::new(Item::build( - (&tab_page, &target_child), - &self.profile, - // Actions - (&self.browser_action, &self.window_action, &self.action), - // Options - None, - false, - )); + // Init new tab item + let item = Rc::new(Item::build( + (&tab_page, &target_child), + &self.profile, + // Actions + (&self.browser_action, &self.window_action, &self.action), + // Options + None, + false, + )); - // Relate with GTK `TabPage` with app `Item` - self.index - .borrow_mut() - .insert(item.tab_page.clone(), item.clone()); + // Relate with GTK `TabPage` with app `Item` + self.index + .borrow_mut() + .insert(item.tab_page.clone(), item.clone()); - // Setup - self.tab_view - .set_page_pinned(&item.tab_page, item_record.is_pinned); + // Setup + self.tab_view + .set_page_pinned(&item.tab_page, item_record.is_pinned); - if item_record.is_selected { - self.tab_view.set_selected_page(&item.tab_page); - } - - // Forcefully update global actions on HashMap index build complete - // * `selected_page_notify` runs this action also, just before Item init @TODO - update_actions( - &self.tab_view, - self.tab_view.selected_page().as_ref(), - &self.index, - &self.window_action, - ); - - // Restore children components - item.page.restore(transaction, item_record.id)?; - } + if item_record.is_selected { + self.tab_view.set_selected_page(&item.tab_page); } + + // Forcefully update global actions on HashMap index build complete + // * `selected_page_notify` runs this action also, just before Item init @TODO + update_actions( + &self.tab_view, + self.tab_view.selected_page().as_ref(), + &self.index, + &self.window_action, + ); + + // Restore children components + item.page.restore(transaction, item_record.id)?; } - Err(e) => return Err(e.to_string()), } Ok(()) } - pub fn save( - &self, - transaction: &Transaction, - app_browser_window_id: i64, - ) -> Result<(), String> { - match database::insert(transaction, app_browser_window_id) { - Ok(_) => { - // Delegate save action to childs - let id = database::last_insert_id(transaction); - for (_, item) in self.index.borrow().iter() { - item.save(transaction, id, self.tab_view.page_position(&item.tab_page))?; - } - } - Err(e) => return Err(e.to_string()), + pub fn save(&self, transaction: &Transaction, app_browser_window_id: i64) -> Result<()> { + let id = database::insert(transaction, app_browser_window_id)?; + for (_, item) in self.index.borrow().iter() { + item.save(transaction, id, self.tab_view.page_position(&item.tab_page))?; } Ok(()) } @@ -430,11 +397,9 @@ impl Tab { // Tools -pub fn migrate(tx: &Transaction) -> Result<(), String> { +pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components - if let Err(e) = database::init(tx) { - return Err(e.to_string()); - } + database::init(tx)?; // Delegate migration to childs item::migrate(tx)?; diff --git a/src/app/browser/window/tab/database.rs b/src/app/browser/window/tab/database.rs index b4993e91..1f3d2d0a 100644 --- a/src/app/browser/window/tab/database.rs +++ b/src/app/browser/window/tab/database.rs @@ -1,12 +1,13 @@ -use sqlite::{Error, Transaction}; +use anyhow::Result; +use sqlite::Transaction; pub struct Table { pub id: i64, // pub app_browser_window_id: i64, not in use } -pub fn init(tx: &Transaction) -> Result { - tx.execute( +pub fn init(tx: &Transaction) -> Result { + Ok(tx.execute( "CREATE TABLE IF NOT EXISTS `app_browser_window_tab` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, @@ -15,19 +16,20 @@ pub fn init(tx: &Transaction) -> Result { FOREIGN KEY (`app_browser_window_id`) REFERENCES `app_browser_window`(`id`) )", [], - ) + )?) } -pub fn insert(tx: &Transaction, app_browser_window_id: i64) -> Result { +pub fn insert(tx: &Transaction, app_browser_window_id: i64) -> Result { tx.execute( "INSERT INTO `app_browser_window_tab` ( `app_browser_window_id` ) VALUES (?)", [app_browser_window_id], - ) + )?; + Ok(tx.last_insert_rowid()) } -pub fn select(tx: &Transaction, app_browser_window_id: i64) -> Result, Error> { +pub fn select(tx: &Transaction, app_browser_window_id: i64) -> Result> { let mut stmt = tx.prepare( "SELECT `id`, `app_browser_window_id` FROM `app_browser_window_tab` @@ -51,10 +53,6 @@ pub fn select(tx: &Transaction, app_browser_window_id: i64) -> Result Ok(records) } -pub fn delete(tx: &Transaction, id: i64) -> Result { - tx.execute("DELETE FROM `app_browser_window_tab` WHERE `id` = ?", [id]) -} - -pub fn last_insert_id(tx: &Transaction) -> i64 { - tx.last_insert_rowid() +pub fn delete(tx: &Transaction, id: i64) -> Result { + Ok(tx.execute("DELETE FROM `app_browser_window_tab` WHERE `id` = ?", [id])?) } diff --git a/src/app/browser/window/tab/item.rs b/src/app/browser/window/tab/item.rs index 24e46cc1..5f376d09 100644 --- a/src/app/browser/window/tab/item.rs +++ b/src/app/browser/window/tab/item.rs @@ -7,6 +7,7 @@ use super::{Action as TabAction, BrowserAction, WindowAction}; use crate::Profile; use action::Action; use adw::TabPage; +use anyhow::Result; use client::Client; use gtk::{ prelude::{ActionExt, ActionMapExt, BoxExt}, @@ -164,26 +165,12 @@ impl Item { } } - pub fn clean( - &self, - transaction: &Transaction, - app_browser_window_tab_id: i64, - ) -> Result<(), String> { - match database::select(transaction, app_browser_window_tab_id) { - Ok(records) => { - for record in records { - match database::delete(transaction, record.id) { - Ok(_) => { - // Delegate clean action to the item childs - self.page.clean(transaction, record.id)?; - } - Err(e) => return Err(e.to_string()), - } - } - } - Err(e) => return Err(e.to_string()), + pub fn clean(&self, transaction: &Transaction, app_browser_window_tab_id: i64) -> Result<()> { + for record in database::select(transaction, app_browser_window_tab_id)? { + database::delete(transaction, record.id)?; + // Delegate clean action to the item childs + self.page.clean(transaction, record.id)?; } - Ok(()) } @@ -192,32 +179,23 @@ impl Item { transaction: &Transaction, app_browser_window_tab_id: i64, page_position: i32, - ) -> Result<(), String> { - match database::insert( + ) -> Result<()> { + let id = database::insert( transaction, app_browser_window_tab_id, page_position, self.tab_page.is_pinned(), self.tab_page.is_selected(), - ) { - Ok(_) => { - // Delegate save action to childs - let id = database::last_insert_id(transaction); - self.page.save(transaction, id)?; - } - Err(e) => return Err(e.to_string()), - } - + )?; + self.page.save(transaction, id)?; Ok(()) } } // Tools -pub fn migrate(tx: &Transaction) -> Result<(), String> { +pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components - if let Err(e) = database::init(tx) { - return Err(e.to_string()); - } + database::init(tx)?; // Delegate migration to childs page::migrate(tx)?; @@ -231,9 +209,6 @@ pub fn migrate(tx: &Transaction) -> Result<(), String> { pub fn restore( transaction: &Transaction, app_browser_window_tab_id: i64, -) -> Result, String> { - match database::select(transaction, app_browser_window_tab_id) { - Ok(records) => Ok(records), - Err(e) => Err(e.to_string()), - } +) -> Result> { + database::select(transaction, app_browser_window_tab_id) } diff --git a/src/app/browser/window/tab/item/database.rs b/src/app/browser/window/tab/item/database.rs index f003ca31..b7a9f1f1 100644 --- a/src/app/browser/window/tab/item/database.rs +++ b/src/app/browser/window/tab/item/database.rs @@ -1,4 +1,5 @@ -use sqlite::{Error, Transaction}; +use anyhow::Result; +use sqlite::Transaction; pub struct Table { pub id: i64, @@ -8,8 +9,8 @@ pub struct Table { pub is_selected: bool, } -pub fn init(tx: &Transaction) -> Result { - tx.execute( +pub fn init(tx: &Transaction) -> Result { + Ok(tx.execute( "CREATE TABLE IF NOT EXISTS `app_browser_window_tab_item` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, @@ -21,7 +22,7 @@ pub fn init(tx: &Transaction) -> Result { FOREIGN KEY (`app_browser_window_tab_id`) REFERENCES `app_browser_window_tab` (`id`) )", [], - ) + )?) } pub fn insert( @@ -30,7 +31,7 @@ pub fn insert( page_position: i32, is_pinned: bool, is_selected: bool, -) -> Result { +) -> Result { tx.execute( "INSERT INTO `app_browser_window_tab_item` ( `app_browser_window_tab_id`, @@ -44,10 +45,11 @@ pub fn insert( is_pinned as i64, is_selected as i64, ], - ) + )?; + Ok(tx.last_insert_rowid()) } -pub fn select(tx: &Transaction, app_browser_window_tab_id: i64) -> Result, Error> { +pub fn select(tx: &Transaction, app_browser_window_tab_id: i64) -> Result> { let mut stmt = tx.prepare( "SELECT `id`, `app_browser_window_tab_id`, @@ -79,13 +81,9 @@ pub fn select(tx: &Transaction, app_browser_window_tab_id: i64) -> Result Result { - tx.execute( +pub fn delete(tx: &Transaction, id: i64) -> Result { + Ok(tx.execute( "DELETE FROM `app_browser_window_tab_item` WHERE `id` = ?", [id], - ) -} - -pub fn last_insert_id(tx: &Transaction) -> i64 { - tx.last_insert_rowid() + )?) } diff --git a/src/app/browser/window/tab/item/page.rs b/src/app/browser/window/tab/item/page.rs index 6e13b2e6..642264b2 100644 --- a/src/app/browser/window/tab/item/page.rs +++ b/src/app/browser/window/tab/item/page.rs @@ -7,6 +7,7 @@ mod search; use super::{Action as ItemAction, BrowserAction, Profile, TabAction, WindowAction}; use adw::TabPage; +use anyhow::Result; use content::Content; use error::Error; use input::Input; @@ -104,20 +105,11 @@ impl Page { &self, transaction: &Transaction, app_browser_window_tab_item_id: i64, - ) -> Result<(), String> { - match database::select(transaction, app_browser_window_tab_item_id) { - Ok(records) => { - for record in records { - match database::delete(transaction, record.id) { - Ok(_) => { - // Delegate clean action to the item childs - self.navigation.clean(transaction, &record.id)?; - } - Err(e) => return Err(e.to_string()), - } - } - } - Err(e) => return Err(e.to_string()), + ) -> Result<()> { + for record in database::select(transaction, app_browser_window_tab_item_id)? { + database::delete(transaction, record.id)?; + // Delegate clean action to the item childs + self.navigation.clean(transaction, &record.id)?; } Ok(()) } @@ -127,25 +119,20 @@ impl Page { &self, transaction: &Transaction, app_browser_window_tab_item_id: i64, - ) -> Result<(), String> { + ) -> Result<()> { // Begin page restore - match database::select(transaction, app_browser_window_tab_item_id) { - Ok(records) => { - for record in records { - // Restore `Self` - if let Some(title) = record.title { - self.set_title(title.as_str()); - } - self.set_needs_attention(record.is_needs_attention); - // Restore child components - self.navigation.restore(transaction, &record.id)?; - // Make initial page history snap using `navigation` values restored - if let Some(uri) = self.navigation.uri() { - self.profile.history.memory.request.set(uri); - } - } + for record in database::select(transaction, app_browser_window_tab_item_id)? { + // Restore `Self` + if let Some(title) = record.title { + self.set_title(title.as_str()); + } + self.set_needs_attention(record.is_needs_attention); + // Restore child components + self.navigation.restore(transaction, &record.id)?; + // Make initial page history snap using `navigation` values restored + if let Some(uri) = self.navigation.uri() { + self.profile.history.memory.request.set(uri); } - Err(e) => return Err(e.to_string()), } Ok(()) } @@ -155,10 +142,10 @@ impl Page { &self, transaction: &Transaction, app_browser_window_tab_item_id: i64, - ) -> Result<(), String> { + ) -> Result<()> { // Keep value in memory until operation complete let title = self.tab_page.title(); - match database::insert( + let id = database::insert( transaction, app_browser_window_tab_item_id, self.tab_page.needs_attention(), @@ -166,15 +153,9 @@ impl Page { true => None, false => Some(title.as_str()), }, - ) { - Ok(_) => { - let id = database::last_insert_id(transaction); - - // Delegate save action to childs - self.navigation.save(transaction, &id)?; - } - Err(e) => return Err(e.to_string()), - } + )?; + // Delegate save action to childs + self.navigation.save(transaction, &id)?; Ok(()) } @@ -198,11 +179,9 @@ impl Page { // Tools -pub fn migrate(tx: &Transaction) -> Result<(), String> { +pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components - if let Err(e) = database::init(tx) { - return Err(e.to_string()); - } + database::init(tx)?; // Delegate migration to childs navigation::migrate(tx)?; diff --git a/src/app/browser/window/tab/item/page/database.rs b/src/app/browser/window/tab/item/page/database.rs index f8b2d606..f1d6b232 100644 --- a/src/app/browser/window/tab/item/page/database.rs +++ b/src/app/browser/window/tab/item/page/database.rs @@ -1,4 +1,5 @@ -use sqlite::{Error, Transaction}; +use anyhow::Result; +use sqlite::Transaction; pub struct Table { pub id: i64, @@ -7,8 +8,8 @@ pub struct Table { pub title: Option, } -pub fn init(tx: &Transaction) -> Result { - tx.execute( +pub fn init(tx: &Transaction) -> Result { + Ok(tx.execute( "CREATE TABLE IF NOT EXISTS `app_browser_window_tab_item_page` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, @@ -19,7 +20,7 @@ pub fn init(tx: &Transaction) -> Result { FOREIGN KEY (`app_browser_window_tab_item_id`) REFERENCES `app_browser_window_tab_item` (`id`) )", [], - ) + )?) } pub fn insert( @@ -27,7 +28,7 @@ pub fn insert( app_browser_window_tab_item_id: i64, is_needs_attention: bool, title: Option<&str>, -) -> Result { +) -> Result { tx.execute( "INSERT INTO `app_browser_window_tab_item_page` ( `app_browser_window_tab_item_id`, @@ -35,10 +36,11 @@ pub fn insert( `title` ) VALUES (?, ?, ?)", (app_browser_window_tab_item_id, is_needs_attention, title), - ) + )?; + Ok(tx.last_insert_rowid()) } -pub fn select(tx: &Transaction, app_browser_window_tab_item_id: i64) -> Result, Error> { +pub fn select(tx: &Transaction, app_browser_window_tab_item_id: i64) -> Result> { let mut stmt = tx.prepare( "SELECT `id`, `app_browser_window_tab_item_id`, @@ -67,13 +69,9 @@ pub fn select(tx: &Transaction, app_browser_window_tab_item_id: i64) -> Result Result { - tx.execute( +pub fn delete(tx: &Transaction, id: i64) -> Result { + Ok(tx.execute( "DELETE FROM `app_browser_window_tab_item_page` WHERE `id` = ?", [id], - ) -} - -pub fn last_insert_id(tx: &Transaction) -> i64 { - tx.last_insert_rowid() + )?) } diff --git a/src/app/browser/window/tab/item/page/navigation.rs b/src/app/browser/window/tab/item/page/navigation.rs index ce36b383..963f77e2 100644 --- a/src/app/browser/window/tab/item/page/navigation.rs +++ b/src/app/browser/window/tab/item/page/navigation.rs @@ -6,6 +6,7 @@ mod reload; mod request; use super::{ItemAction, Profile, TabAction, WindowAction}; +use anyhow::Result; use bookmark::Bookmark; use gtk::{ glib::{GString, Uri}, @@ -72,22 +73,12 @@ impl Navigation { &self, transaction: &Transaction, app_browser_window_tab_item_page_id: &i64, - ) -> Result<(), String> { - match database::select(transaction, app_browser_window_tab_item_page_id) { - Ok(records) => { - for record in records { - match database::delete(transaction, &record.id) { - Ok(_) => { - // Delegate clean action to the item childs - self.request.clean(transaction, &record.id)?; - } - Err(e) => return Err(e.to_string()), - } - } - } - Err(e) => return Err(e.to_string()), + ) -> Result<()> { + for record in database::select(transaction, app_browser_window_tab_item_page_id)? { + database::delete(transaction, &record.id)?; + // Delegate clean action to the item childs + self.request.clean(transaction, &record.id)?; } - Ok(()) } @@ -95,17 +86,11 @@ impl Navigation { &self, transaction: &Transaction, app_browser_window_tab_item_page_id: &i64, - ) -> Result<(), String> { - match database::select(transaction, app_browser_window_tab_item_page_id) { - Ok(records) => { - for record in records { - // Delegate restore action to the item childs - self.request.restore(transaction, &record.id)?; - } - } - Err(e) => return Err(e.to_string()), + ) -> Result<()> { + for record in database::select(transaction, app_browser_window_tab_item_page_id)? { + // Delegate restore action to the item childs + self.request.restore(transaction, &record.id)?; } - Ok(()) } @@ -113,17 +98,10 @@ impl Navigation { &self, transaction: &Transaction, app_browser_window_tab_item_page_id: &i64, - ) -> Result<(), String> { - match database::insert(transaction, app_browser_window_tab_item_page_id) { - Ok(_) => { - let id = database::last_insert_id(transaction); - - // Delegate save action to childs - self.request.save(transaction, &id)?; - } - Err(e) => return Err(e.to_string()), - } - + ) -> Result<()> { + let id = database::insert(transaction, app_browser_window_tab_item_page_id)?; + // Delegate save action to childs + self.request.save(transaction, &id)?; Ok(()) } @@ -173,11 +151,9 @@ impl Navigation { } // Tools -pub fn migrate(tx: &Transaction) -> Result<(), String> { +pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components - if let Err(e) = database::init(tx) { - return Err(e.to_string()); - } + database::init(tx)?; // Delegate migration to childs request::migrate(tx)?; diff --git a/src/app/browser/window/tab/item/page/navigation/bookmark.rs b/src/app/browser/window/tab/item/page/navigation/bookmark.rs index b2aef321..834e71ad 100644 --- a/src/app/browser/window/tab/item/page/navigation/bookmark.rs +++ b/src/app/browser/window/tab/item/page/navigation/bookmark.rs @@ -48,7 +48,7 @@ impl Bookmark for Button { } fn update(&self, profile: &Profile, request: &Entry) { - let has_bookmark = profile.bookmark.get(&request.text()).is_ok(); + let has_bookmark = profile.bookmark.get(&request.text()).is_some(); self.set_icon_name(icon_name(has_bookmark)); self.set_tooltip_text(Some(tooltip_text(has_bookmark))); } diff --git a/src/app/browser/window/tab/item/page/navigation/database.rs b/src/app/browser/window/tab/item/page/navigation/database.rs index 52cb9ae2..b7968ce5 100644 --- a/src/app/browser/window/tab/item/page/navigation/database.rs +++ b/src/app/browser/window/tab/item/page/navigation/database.rs @@ -1,12 +1,13 @@ -use sqlite::{Error, Transaction}; +use anyhow::Result; +use sqlite::Transaction; pub struct Table { pub id: i64, // pub app_browser_window_tab_item_page_id: i64, not in use } -pub fn init(tx: &Transaction) -> Result { - tx.execute( +pub fn init(tx: &Transaction) -> Result { + Ok(tx.execute( "CREATE TABLE IF NOT EXISTS `app_browser_window_tab_item_page_navigation` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, @@ -15,22 +16,20 @@ pub fn init(tx: &Transaction) -> Result { FOREIGN KEY (`app_browser_window_tab_item_page_id`) REFERENCES `app_browser_window_tab_item_page`(`id`) )", [], - ) + )?) } -pub fn insert(tx: &Transaction, app_browser_window_tab_item_page_id: &i64) -> Result { +pub fn insert(tx: &Transaction, app_browser_window_tab_item_page_id: &i64) -> Result { tx.execute( "INSERT INTO `app_browser_window_tab_item_page_navigation` ( `app_browser_window_tab_item_page_id` ) VALUES (?)", [app_browser_window_tab_item_page_id], - ) + )?; + Ok(tx.last_insert_rowid()) } -pub fn select( - tx: &Transaction, - app_browser_window_tab_item_page_id: &i64, -) -> Result, Error> { +pub fn select(tx: &Transaction, app_browser_window_tab_item_page_id: &i64) -> Result> { let mut stmt = tx.prepare( "SELECT `id`, `app_browser_window_tab_item_page_id` @@ -55,13 +54,9 @@ pub fn select( Ok(records) } -pub fn delete(tx: &Transaction, id: &i64) -> Result { - tx.execute( +pub fn delete(tx: &Transaction, id: &i64) -> Result { + Ok(tx.execute( "DELETE FROM `app_browser_window_tab_item_page_navigation` WHERE `id` = ?", [id], - ) -} - -pub fn last_insert_id(tx: &Transaction) -> i64 { - tx.last_insert_rowid() + )?) } diff --git a/src/app/browser/window/tab/item/page/navigation/request.rs b/src/app/browser/window/tab/item/page/navigation/request.rs index 29e40635..40c15502 100644 --- a/src/app/browser/window/tab/item/page/navigation/request.rs +++ b/src/app/browser/window/tab/item/page/navigation/request.rs @@ -3,15 +3,15 @@ mod identity; mod primary_icon; mod search; -use adw::{prelude::AdwDialogExt, AlertDialog}; -use primary_icon::PrimaryIcon; - use super::{ItemAction, Profile}; +use adw::{prelude::AdwDialogExt, AlertDialog}; +use anyhow::Result; use gtk::{ glib::{gformat, GString, Uri, UriFlags}, prelude::{EditableExt, EntryExt, WidgetExt}, Entry, EntryIconPosition, StateFlags, }; +use primary_icon::PrimaryIcon; use sqlite::Transaction; use std::{cell::Cell, rc::Rc}; @@ -29,19 +29,19 @@ pub trait Request { &self, transaction: &Transaction, app_browser_window_tab_item_page_navigation_id: &i64, - ) -> Result<(), String>; + ) -> Result<()>; fn restore( &self, transaction: &Transaction, app_browser_window_tab_item_page_navigation_id: &i64, - ) -> Result<(), String>; + ) -> Result<()>; fn save( &self, transaction: &Transaction, app_browser_window_tab_item_page_navigation_id: &i64, - ) -> Result<(), String>; + ) -> Result<()>; fn update_primary_icon(&self, profile: &Profile); fn update_secondary_icon(&self); @@ -147,22 +147,13 @@ impl Request for Entry { &self, transaction: &Transaction, app_browser_window_tab_item_page_navigation_id: &i64, - ) -> Result<(), String> { - match database::select(transaction, app_browser_window_tab_item_page_navigation_id) { - Ok(records) => { - for record in records { - match database::delete(transaction, &record.id) { - Ok(_) => { - // Delegate clean action to the item childs - // nothing yet.. - } - Err(e) => return Err(e.to_string()), - } - } - } - Err(e) => return Err(e.to_string()), + ) -> Result<()> { + for record in database::select(transaction, app_browser_window_tab_item_page_navigation_id)? + { + database::delete(transaction, &record.id)?; + // Delegate clean action to the item childs + // nothing yet.. } - Ok(()) } @@ -170,21 +161,15 @@ impl Request for Entry { &self, transaction: &Transaction, app_browser_window_tab_item_page_navigation_id: &i64, - ) -> Result<(), String> { - match database::select(transaction, app_browser_window_tab_item_page_navigation_id) { - Ok(records) => { - for record in records { - if let Some(text) = record.text { - self.set_text(&text); - } - - // Delegate restore action to the item childs - // nothing yet.. - } + ) -> Result<()> { + for record in database::select(transaction, app_browser_window_tab_item_page_navigation_id)? + { + if let Some(text) = record.text { + self.set_text(&text); } - Err(e) => return Err(e.to_string()), + // Delegate restore action to the item childs + // nothing yet.. } - Ok(()) } @@ -192,27 +177,19 @@ impl Request for Entry { &self, transaction: &Transaction, app_browser_window_tab_item_page_navigation_id: &i64, - ) -> Result<(), String> { + ) -> Result<()> { // Keep value in memory until operation complete let text = self.text(); - - match database::insert( + let _id = database::insert( transaction, app_browser_window_tab_item_page_navigation_id, match text.is_empty() { true => None, false => Some(text.as_str()), }, - ) { - Ok(_) => { - // let id = database::last_insert_id(transaction); - - // Delegate save action to childs - // nothing yet.. - } - Err(e) => return Err(e.to_string()), - } - + )?; + // Delegate save action to childs + // nothing yet.. Ok(()) } @@ -369,11 +346,9 @@ impl Request for Entry { // Tools -pub fn migrate(tx: &Transaction) -> Result<(), String> { +pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components - if let Err(e) = database::init(tx) { - return Err(e.to_string()); - } + database::init(tx)?; // Delegate migration to childs // nothing yet.. diff --git a/src/app/browser/window/tab/item/page/navigation/request/database.rs b/src/app/browser/window/tab/item/page/navigation/request/database.rs index da181106..584d26dd 100644 --- a/src/app/browser/window/tab/item/page/navigation/request/database.rs +++ b/src/app/browser/window/tab/item/page/navigation/request/database.rs @@ -1,4 +1,5 @@ -use sqlite::{Error, Transaction}; +use anyhow::Result; +use sqlite::Transaction; pub struct Table { pub id: i64, @@ -6,8 +7,8 @@ pub struct Table { pub text: Option, // can be stored as NULL } -pub fn init(tx: &Transaction) -> Result { - tx.execute( +pub fn init(tx: &Transaction) -> Result { + Ok( tx.execute( "CREATE TABLE IF NOT EXISTS `app_browser_window_tab_item_page_navigation_request` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, @@ -17,27 +18,28 @@ pub fn init(tx: &Transaction) -> Result { FOREIGN KEY (`app_browser_window_tab_item_page_navigation_id`) REFERENCES `app_browser_window_tab_item_page_navigation`(`id`) )", [], - ) + )?) } pub fn insert( tx: &Transaction, app_browser_window_tab_item_page_navigation_id: &i64, text: Option<&str>, -) -> Result { +) -> Result { tx.execute( "INSERT INTO `app_browser_window_tab_item_page_navigation_request` ( `app_browser_window_tab_item_page_navigation_id`, `text` ) VALUES (?, ?)", (app_browser_window_tab_item_page_navigation_id, text), - ) + )?; + Ok(tx.last_insert_rowid()) } pub fn select( tx: &Transaction, app_browser_window_tab_item_page_navigation_id: &i64, -) -> Result, Error> { +) -> Result> { let mut stmt = tx.prepare( "SELECT `id`, `app_browser_window_tab_item_page_navigation_id`, @@ -64,14 +66,9 @@ pub fn select( Ok(records) } -pub fn delete(tx: &Transaction, id: &i64) -> Result { - tx.execute( +pub fn delete(tx: &Transaction, id: &i64) -> Result { + Ok(tx.execute( "DELETE FROM `app_browser_window_tab_item_page_navigation_request` WHERE `id` = ?", [id], - ) + )?) } - -/* not in use -pub fn last_insert_id(tx: &Transaction) -> i64 { - tx.last_insert_rowid() -} */ diff --git a/src/main.rs b/src/main.rs index 213b2f66..1b6553aa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,7 @@ use std::rc::Rc; fn main() -> ExitCode { match gtk::init() { - Ok(_) => App::build(&Rc::new(Profile::new())).run(), + Ok(_) => App::build(&Rc::new(Profile::new().unwrap())).run(), Err(_) => ExitCode::FAILURE, } } diff --git a/src/profile.rs b/src/profile.rs index 9739650e..69198b64 100644 --- a/src/profile.rs +++ b/src/profile.rs @@ -10,6 +10,7 @@ use history::History; use identity::Identity; use search::Search; +use anyhow::Result; use gtk::glib::{user_config_dir, DateTime}; use sqlite::{Connection, Transaction}; use std::{fs::create_dir_all, path::PathBuf, rc::Rc, sync::RwLock}; @@ -29,16 +30,10 @@ pub struct Profile { pub config_path: PathBuf, } -impl Default for Profile { - fn default() -> Self { - Self::new() - } -} - impl Profile { // Constructors - pub fn new() -> Self { + pub fn new() -> Result { // Init profile path let mut config_path = user_config_dir(); @@ -51,44 +46,26 @@ impl Profile { env!("CARGO_PKG_VERSION_MINOR") )); // @TODO remove after auto-migrate feature implementation - if let Err(e) = create_dir_all(&config_path) { - panic!("{e}") - } + create_dir_all(&config_path)?; // Init database path let mut database_path = config_path.clone(); database_path.push(DB_NAME); // Init database connection - let connection = match Connection::open(database_path.as_path()) { - Ok(connection) => Rc::new(RwLock::new(connection)), - Err(e) => panic!("{e}"), - }; + let connection = Rc::new(RwLock::new(Connection::open(database_path.as_path())?)); // Init profile components { // Init writable connection - let mut connection = match connection.write() { - Ok(connection) => connection, - Err(e) => todo!("{e}"), - }; + let mut connection = connection.write().unwrap(); // @TODO handle // Init new transaction - let transaction = match connection.transaction() { - Ok(transaction) => transaction, - Err(e) => todo!("{e}"), - }; + let transaction = connection.transaction()?; // Begin migration - match migrate(&transaction) { - Ok(_) => { - // Confirm changes - if let Err(e) = transaction.commit() { - todo!("{e}") - } - } - Err(e) => todo!("{e}"), - } + migrate(&transaction)?; + transaction.commit()?; } // unlock database // Init model @@ -104,7 +81,7 @@ impl Profile { }); // Init components - let bookmark = Rc::new(Bookmark::build(&connection, &profile_id)); + let bookmark = Rc::new(Bookmark::build(&connection, &profile_id)?); let history = Rc::new(History::build(&connection, &profile_id)); let search = Rc::new(Search::build(&connection, &profile_id).unwrap()); // @TODO handle let identity = Rc::new(match Identity::build(&connection, &profile_id) { @@ -113,22 +90,20 @@ impl Profile { }); // Result - Self { + Ok(Self { bookmark, database, history, identity, search, config_path, - } + }) } } -pub fn migrate(tx: &Transaction) -> Result<(), String> { +pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components - if let Err(e) = database::init(tx) { - return Err(e.to_string()); - } + database::init(tx)?; // Delegate migration to children components bookmark::migrate(tx)?; diff --git a/src/profile/bookmark.rs b/src/profile/bookmark.rs index cce2fb41..059db8e5 100644 --- a/src/profile/bookmark.rs +++ b/src/profile/bookmark.rs @@ -1,12 +1,10 @@ mod database; -mod error; mod memory; +use anyhow::Result; use database::Database; -use error::Error; -use memory::Memory; - use gtk::glib::DateTime; +use memory::Memory; use sqlite::{Connection, Transaction}; use std::{rc::Rc, sync::RwLock}; @@ -19,48 +17,38 @@ impl Bookmark { // Constructors /// Create new `Self` - pub fn build(connection: &Rc>, profile_id: &Rc) -> Self { + pub fn build(connection: &Rc>, profile_id: &Rc) -> Result { // Init children components let database = Rc::new(Database::new(connection, profile_id)); let memory = Rc::new(Memory::new()); // Build initial index - match database.records(None) { - Ok(records) => { - for record in records { - if let Err(e) = memory.add(record.request, record.id) { - todo!("{}", e.to_string()) - } - } - } - Err(e) => todo!("{}", e.to_string()), + for record in database.records(None)? { + memory.add(record.request, record.id)?; } // Return new `Self` - Self { database, memory } + Ok(Self { database, memory }) } // Actions /// Get record `id` by `request` from memory index - pub fn get(&self, request: &str) -> Result { - match self.memory.get(request) { - Ok(id) => Ok(id), - Err(_) => Err(Error::MemoryNotFound), - } + pub fn get(&self, request: &str) -> Option { + self.memory.get(request) } /// Toggle record in `database` and `memory` index /// * return `true` on bookmark created, `false` on deleted - pub fn toggle(&self, request: &str) -> Result { + pub fn toggle(&self, request: &str) -> Result { // Delete record if exists - if let Ok(id) = self.get(request) { + if let Some(id) = self.get(request) { match self.database.delete(id) { Ok(_) => match self.memory.delete(request) { Ok(_) => Ok(false), - Err(_) => Err(Error::MemoryDelete), + Err(_) => panic!(), // unexpected }, - Err(_) => Err(Error::DatabaseDelete), + Err(_) => panic!(), // unexpected } // Otherwise, create new record } else { @@ -70,9 +58,9 @@ impl Bookmark { { Ok(id) => match self.memory.add(request.into(), id) { Ok(_) => Ok(true), - Err(_) => Err(Error::MemoryAdd), + Err(_) => panic!(), // unexpected }, - Err(_) => Err(Error::DatabaseAdd), + Err(_) => panic!(), // unexpected } } // @TODO return affected rows on success? } @@ -80,11 +68,9 @@ impl Bookmark { // Tools -pub fn migrate(tx: &Transaction) -> Result<(), String> { +pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components - if let Err(e) = database::init(tx) { - return Err(e.to_string()); - } + database::init(tx)?; // Delegate migration to childs // nothing yet.. diff --git a/src/profile/bookmark/database.rs b/src/profile/bookmark/database.rs index 02fe36fd..a8344b49 100644 --- a/src/profile/bookmark/database.rs +++ b/src/profile/bookmark/database.rs @@ -1,5 +1,6 @@ +use anyhow::Result; use gtk::glib::DateTime; -use sqlite::{Connection, Error, Transaction}; +use sqlite::{Connection, Transaction}; use std::{rc::Rc, sync::RwLock}; pub struct Table { @@ -28,7 +29,7 @@ impl Database { // Getters /// Get bookmark records from database with optional filter by `request` - pub fn records(&self, request: Option<&str>) -> Result, Error> { + pub fn records(&self, request: Option<&str>) -> Result> { let readable = self.connection.read().unwrap(); // @TODO let tx = readable.unchecked_transaction()?; select(&tx, *self.profile_id, request) @@ -38,45 +39,28 @@ impl Database { /// Create new bookmark record in database /// * return last insert ID on success - pub fn add(&self, time: DateTime, request: String) -> Result { - // Begin new transaction + pub fn add(&self, time: DateTime, request: String) -> Result { let mut writable = self.connection.write().unwrap(); // @TODO let tx = writable.transaction()?; - - // Create new record - insert(&tx, *self.profile_id, time, request)?; - - // Hold insert ID for result - let id = last_insert_id(&tx); - - // Done - match tx.commit() { - Ok(_) => Ok(id), - Err(e) => Err(e), - } + let id = insert(&tx, *self.profile_id, time, request)?; + tx.commit()?; + Ok(id) } /// Delete bookmark record from database - pub fn delete(&self, id: i64) -> Result<(), Error> { - // Begin new transaction + pub fn delete(&self, id: i64) -> Result { let mut writable = self.connection.write().unwrap(); // @TODO let tx = writable.transaction()?; - - // Delete record by ID - match delete(&tx, id) { - Ok(_) => match tx.commit() { - Ok(_) => Ok(()), - Err(e) => Err(e), - }, - Err(e) => Err(e), - } + let usize = delete(&tx, id)?; + tx.commit()?; + Ok(usize) } } // Low-level DB API -pub fn init(tx: &Transaction) -> Result { - tx.execute( +pub fn init(tx: &Transaction) -> Result { + Ok(tx.execute( "CREATE TABLE IF NOT EXISTS `profile_bookmark` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, @@ -87,15 +71,10 @@ pub fn init(tx: &Transaction) -> Result { FOREIGN KEY (`profile_id`) REFERENCES `profile`(`id`) )", [], - ) + )?) } -pub fn insert( - tx: &Transaction, - profile_id: i64, - time: DateTime, - request: String, -) -> Result { +pub fn insert(tx: &Transaction, profile_id: i64, time: DateTime, request: String) -> Result { tx.execute( "INSERT INTO `profile_bookmark` ( `profile_id`, @@ -103,14 +82,11 @@ pub fn insert( `request` ) VALUES (?, ?, ?)", (profile_id, time.to_unix(), request), - ) + )?; + Ok(tx.last_insert_rowid()) } -pub fn select( - tx: &Transaction, - profile_id: i64, - request: Option<&str>, -) -> Result, Error> { +pub fn select(tx: &Transaction, profile_id: i64, request: Option<&str>) -> Result> { let mut stmt = tx.prepare( "SELECT `id`, `profile_id`, `time`, `request` FROM `profile_bookmark` @@ -136,10 +112,6 @@ pub fn select( Ok(records) } -pub fn delete(tx: &Transaction, id: i64) -> Result { - tx.execute("DELETE FROM `profile_bookmark` WHERE `id` = ?", [id]) -} - -pub fn last_insert_id(tx: &Transaction) -> i64 { - tx.last_insert_rowid() +pub fn delete(tx: &Transaction, id: i64) -> Result { + Ok(tx.execute("DELETE FROM `profile_bookmark` WHERE `id` = ?", [id])?) } diff --git a/src/profile/bookmark/error.rs b/src/profile/bookmark/error.rs deleted file mode 100644 index 2d30227c..00000000 --- a/src/profile/bookmark/error.rs +++ /dev/null @@ -1,8 +0,0 @@ -#[derive(Debug)] -pub enum Error { - DatabaseAdd, - DatabaseDelete, - MemoryAdd, - MemoryDelete, - MemoryNotFound, -} diff --git a/src/profile/bookmark/memory.rs b/src/profile/bookmark/memory.rs index e72f37a8..2ab8eedc 100644 --- a/src/profile/bookmark/memory.rs +++ b/src/profile/bookmark/memory.rs @@ -1,6 +1,4 @@ -mod error; -use error::Error; - +use anyhow::Result; use itertools::Itertools; use std::{cell::RefCell, collections::HashMap}; @@ -29,37 +27,34 @@ impl Memory { /// Add new record with `request` as key and `id` as value /// * validate record with same key does not exist yet - pub fn add(&self, request: String, id: i64) -> Result<(), Error> { + pub fn add(&self, request: String, id: i64) -> Result<()> { // Borrow shared index access let mut index = self.index.borrow_mut(); // Prevent existing key overwrite if index.contains_key(&request) { - return Err(Error::Overwrite(request)); + panic!() // unexpected } // Slot should be free, let check it twice match index.insert(request, id) { - Some(_) => Err(Error::Unexpected), + Some(_) => panic!(), // unexpected None => Ok(()), } } /// Delete record from index by `request` /// * validate record key is exist - pub fn delete(&self, request: &str) -> Result<(), Error> { + pub fn delete(&self, request: &str) -> Result<()> { match self.index.borrow_mut().remove(request) { Some(_) => Ok(()), - None => Err(Error::Unexpected), // @TODO + None => panic!(), // unexpected } } /// Get `id` by `request` from memory index - pub fn get(&self, request: &str) -> Result { - match self.index.borrow().get(request) { - Some(&value) => Ok(value), - None => Err(Error::Unexpected), // @TODO - } + pub fn get(&self, request: &str) -> Option { + self.index.borrow().get(request).copied() } /// Get recent requests vector sorted by `ID` DESC diff --git a/src/profile/bookmark/memory/error.rs b/src/profile/bookmark/memory/error.rs deleted file mode 100644 index 8a91ad46..00000000 --- a/src/profile/bookmark/memory/error.rs +++ /dev/null @@ -1,18 +0,0 @@ -use std::fmt::{Display, Formatter, Result}; - -#[derive(Debug)] -pub enum Error { - Overwrite(String), - Unexpected, -} - -impl Display for Error { - fn fmt(&self, f: &mut Formatter) -> Result { - match self { - Self::Overwrite(key) => { - write!(f, "Overwrite attempt for existing record `{key}`") - } - Self::Unexpected => write!(f, "Unexpected error"), - } - } -} diff --git a/src/profile/database.rs b/src/profile/database.rs index 641d7277..7c0114c8 100644 --- a/src/profile/database.rs +++ b/src/profile/database.rs @@ -1,5 +1,6 @@ +use anyhow::Result; use gtk::glib::DateTime; -use sqlite::{Connection, Error, Transaction}; +use sqlite::{Connection, Transaction}; use std::{rc::Rc, sync::RwLock}; pub struct Table { @@ -26,14 +27,14 @@ impl Database { // Getters /// Get all records - pub fn records(&self) -> Result, Error> { + pub fn records(&self) -> Result> { let readable = self.connection.read().unwrap(); let tx = readable.unchecked_transaction()?; select(&tx) } /// Get active profile record if exist - pub fn active(&self) -> Result, Error> { + pub fn active(&self) -> Result> { let records = self.records()?; Ok(records.into_iter().find(|record| record.is_active)) } @@ -41,36 +42,24 @@ impl Database { // Setters /// Create new record in `Self` database connected - pub fn add(&self, is_active: bool, time: DateTime, name: Option) -> Result { - // Begin new transaction + pub fn add(&self, is_active: bool, time: DateTime, name: Option) -> Result { let mut writable = self.connection.write().unwrap(); let tx = writable.transaction()?; - - // New record has active status if is_active { - // Deactivate other records as only one profile should be active for record in select(&tx)? { update(&tx, record.id, false, record.time, record.name)?; } } - - // Create new record - insert(&tx, is_active, time, name)?; - - // Hold insert ID for result - let id = last_insert_id(&tx); - - // Done + let id = insert(&tx, is_active, time, name)?; tx.commit()?; - Ok(id) } } // Low-level DB API -pub fn init(tx: &Transaction) -> Result { - tx.execute( +pub fn init(tx: &Transaction) -> Result { + Ok(tx.execute( "CREATE TABLE IF NOT EXISTS `profile` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, @@ -79,7 +68,7 @@ pub fn init(tx: &Transaction) -> Result { `name` VARCHAR(255) )", [], - ) + )?) } pub fn insert( @@ -87,7 +76,7 @@ pub fn insert( is_active: bool, time: DateTime, name: Option, -) -> Result { +) -> Result { tx.execute( "INSERT INTO `profile` ( `is_active`, @@ -95,7 +84,8 @@ pub fn insert( `name` ) VALUES (?, ?, ?)", (is_active, time.to_unix(), name), - ) + )?; + Ok(tx.last_insert_rowid()) } pub fn update( @@ -104,14 +94,14 @@ pub fn update( is_active: bool, time: DateTime, name: Option, -) -> Result { - tx.execute( +) -> Result { + Ok(tx.execute( "UPDATE `profile` SET `is_active` = ?, `time` = ?, `name` = ? WHERE `id` = ?", (is_active, time.to_unix(), name, id), - ) + )?) } -pub fn select(tx: &Transaction) -> Result, Error> { +pub fn select(tx: &Transaction) -> Result> { let mut stmt = tx.prepare("SELECT `id`, `is_active`, `time`, `name` FROM `profile`")?; let result = stmt.query_map([], |row| { Ok(Table { @@ -131,7 +121,3 @@ pub fn select(tx: &Transaction) -> Result, Error> { Ok(records) } - -pub fn last_insert_id(tx: &Transaction) -> i64 { - tx.last_insert_rowid() -} diff --git a/src/profile/history/database.rs b/src/profile/history/database.rs deleted file mode 100644 index 51af4663..00000000 --- a/src/profile/history/database.rs +++ /dev/null @@ -1,80 +0,0 @@ -use gtk::glib::DateTime; -use sqlite::{Error, Transaction}; - -pub struct Table { - pub id: i64, - pub profile_id: i64, - pub time: DateTime, - pub request: String, -} - -pub struct Database { - // nothing yet.. -} - -// Low-level DB API - -pub fn init(tx: &Transaction) -> Result { - tx.execute( - "CREATE TABLE IF NOT EXISTS `profile_history` - ( - `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, - `profile_id` INTEGER NOT NULL, - `time` INTEGER NOT NULL, - `request` TEXT NOT NULL, - - FOREIGN KEY (`profile_id`) REFERENCES `profile`(`id`) - )", - [], - ) -} - -pub fn insert( - tx: &Transaction, - profile_id: i64, - time: DateTime, - request: String, -) -> Result { - tx.execute( - "INSERT INTO `history` ( - `profile_id`, - `time`, - `request` - ) VALUES (?, ?, ?)", - (profile_id, time.to_unix(), request), - ) -} - -pub fn select( - tx: &Transaction, - profile_id: i64, - request: Option, -) -> Result, Error> { - let mut stmt = tx.prepare( - "SELECT `id`, `profile_id`, `time`, `request` - FROM `profile_history` - WHERE `profile_id` = ? AND `request` LIKE ?", - )?; - - let result = stmt.query_map((profile_id, request.unwrap_or("%".to_string())), |row| { - Ok(Table { - id: row.get(0)?, - profile_id: row.get(1)?, - time: DateTime::from_unix_local(row.get(2)?).unwrap(), - request: row.get(3)?, - }) - })?; - - let mut records = Vec::new(); - - for record in result { - let table = record?; - records.push(table); - } - - Ok(records) -} - -pub fn delete(tx: &Transaction, id: i64) -> Result { - tx.execute("DELETE FROM `profile_history` WHERE `id` = ?", [id]) -} diff --git a/src/profile/identity.rs b/src/profile/identity.rs index ca8a3a59..f5b45711 100644 --- a/src/profile/identity.rs +++ b/src/profile/identity.rs @@ -1,18 +1,15 @@ mod auth; mod certificate; mod database; -mod error; mod item; mod memory; +use anyhow::{bail, Result}; use auth::Auth; use database::Database; -pub use error::Error; -use item::Item; - -use memory::Memory; - use gtk::glib::DateTime; +use item::Item; +use memory::Memory; use sqlite::{Connection, Transaction}; use std::{rc::Rc, sync::RwLock}; @@ -32,11 +29,11 @@ impl Identity { pub fn build( connection: &Rc>, profile_identity_id: &Rc, - ) -> Result { + ) -> Result { // Init components let auth = match Auth::build(connection) { Ok(auth) => Rc::new(auth), - Err(e) => return Err(Error::Auth(e)), + Err(e) => bail!("Could not create auth: {e}"), }; let database = Rc::new(Database::build(connection, profile_identity_id)); let memory = Rc::new(Memory::new()); @@ -58,33 +55,23 @@ impl Identity { /// Add new record to database, update memory index /// * return new `profile_identity_id` on success - pub fn add(&self, pem: &str) -> Result { - match self.database.add(pem) { - Ok(profile_identity_id) => { - self.index()?; - Ok(profile_identity_id) - } - Err(e) => Err(Error::Database(e)), - } + pub fn add(&self, pem: &str) -> Result { + let profile_identity_id = self.database.add(pem)?; + self.index()?; + Ok(profile_identity_id) } /// Delete record from database including children dependencies, update memory index - pub fn delete(&self, profile_identity_id: i64) -> Result<(), Error> { - match self.auth.remove_ref(profile_identity_id) { - Ok(_) => match self.database.delete(profile_identity_id) { - Ok(_) => { - self.index()?; - Ok(()) - } - Err(e) => Err(Error::Database(e)), - }, - Err(e) => Err(Error::Auth(e)), - } + pub fn delete(&self, profile_identity_id: i64) -> Result<()> { + self.auth.remove_ref(profile_identity_id)?; + self.database.delete(profile_identity_id)?; + self.index()?; + Ok(()) } /// Generate new certificate and insert record to DB, update memory index /// * return new `profile_identity_id` on success - pub fn make(&self, time: Option<(DateTime, DateTime)>, name: &str) -> Result { + pub fn make(&self, time: Option<(DateTime, DateTime)>, name: &str) -> Result { // Generate new certificate match certificate::generate( match time { @@ -97,29 +84,17 @@ impl Identity { name, ) { Ok(pem) => self.add(&pem), - Err(e) => Err(Error::Certificate(e)), + Err(e) => bail!("Could not create certificate: {e}"), } } /// Create new `Memory` index from `Database` for `Self` - pub fn index(&self) -> Result<(), Error> { + pub fn index(&self) -> Result<()> { // Clear previous records - if let Err(e) = self.memory.clear() { - return Err(Error::Memory(e)); + self.memory.clear()?; + for record in self.database.records()? { + self.memory.add(record.id, record.pem)?; } - - // Build new index - match self.database.records() { - Ok(records) => { - for record in records { - if let Err(e) = self.memory.add(record.id, record.pem) { - return Err(Error::Memory(e)); - } - } - } - Err(e) => return Err(Error::Database(e)), - }; - Ok(()) } @@ -144,11 +119,9 @@ impl Identity { // Tools -pub fn migrate(tx: &Transaction) -> Result<(), String> { +pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components - if let Err(e) = database::init(tx) { - return Err(e.to_string()); - } + database::init(tx)?; // Delegate migration to childs auth::migrate(tx)?; diff --git a/src/profile/identity/auth.rs b/src/profile/identity/auth.rs index 3770b8d0..5b54a8a9 100644 --- a/src/profile/identity/auth.rs +++ b/src/profile/identity/auth.rs @@ -1,13 +1,11 @@ //! Controller for children `database` and `memory` components mod database; -mod error; mod memory; +use anyhow::Result; use database::Database; -pub use error::Error; use memory::Memory; - use sqlite::{Connection, Transaction}; use std::{rc::Rc, sync::RwLock}; @@ -21,7 +19,7 @@ impl Auth { // Constructors /// Create new `Self` - pub fn build(connection: &Rc>) -> Result { + pub fn build(connection: &Rc>) -> Result { // Init `Self` let this = Self { database: Rc::new(Database::build(connection)), @@ -41,18 +39,14 @@ impl Auth { /// * deactivate active auth by remove previous records from `Self` database /// * reindex `Self` memory index on success /// * return last insert `profile_identity_auth_id` on success - pub fn apply(&self, profile_identity_id: i64, request: &str) -> Result { + pub fn apply(&self, profile_identity_id: i64, request: &str) -> Result { // Cleanup records match `scope` (unauthorize) self.remove(request)?; // Create new record (auth) - let profile_identity_auth_id = match self + let profile_identity_auth_id = self .database - .add(profile_identity_id, &filter_scope(request)) - { - Ok(id) => id, - Err(e) => return Err(Error::Database(e)), - }; + .add(profile_identity_id, &filter_scope(request))?; // Reindex self.index()?; @@ -62,56 +56,31 @@ impl Auth { } /// Remove all records match request (unauthorize) - pub fn remove(&self, request: &str) -> Result<(), Error> { - match self.database.records_scope(Some(&filter_scope(request))) { - Ok(records) => { - for record in records { - if let Err(e) = self.database.delete(record.id) { - return Err(Error::Database(e)); - } - } - } - Err(e) => return Err(Error::Database(e)), + pub fn remove(&self, request: &str) -> Result<()> { + for record in self.database.records_scope(Some(&filter_scope(request)))? { + self.database.delete(record.id)?; } self.index()?; Ok(()) } /// Remove all records match `profile_identity_id` foreign reference key - pub fn remove_ref(&self, profile_identity_id: i64) -> Result<(), Error> { - match self.database.records_ref(profile_identity_id) { - Ok(records) => { - for record in records { - if let Err(e) = self.database.delete(record.id) { - return Err(Error::Database(e)); - } - } - } - Err(e) => return Err(Error::Database(e)), + pub fn remove_ref(&self, profile_identity_id: i64) -> Result<()> { + for record in self.database.records_ref(profile_identity_id)? { + self.database.delete(record.id)?; } self.index()?; Ok(()) } /// Create new `Memory` index from `Database` for `Self` - pub fn index(&self) -> Result<(), Error> { + pub fn index(&self) -> Result<()> { // Clear previous records - if let Err(e) = self.memory.clear() { - return Err(Error::Memory(e)); - } - + self.memory.clear()?; // Build new index - match self.database.records_scope(None) { - Ok(records) => { - for record in records { - if let Err(e) = self.memory.add(record.scope, record.profile_identity_id) { - return Err(Error::Memory(e)); - } - } - } - Err(e) => return Err(Error::Database(e)), + for record in self.database.records_scope(None)? { + self.memory.add(record.scope, record.profile_identity_id)?; } - Ok(()) } @@ -154,11 +123,9 @@ impl Auth { // Tools -pub fn migrate(tx: &Transaction) -> Result<(), String> { +pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components - if let Err(e) = database::init(tx) { - return Err(e.to_string()); - } + database::init(tx)?; // Delegate migration to childs // nothing yet.. diff --git a/src/profile/identity/auth/database.rs b/src/profile/identity/auth/database.rs index df8351c8..45631178 100644 --- a/src/profile/identity/auth/database.rs +++ b/src/profile/identity/auth/database.rs @@ -1,4 +1,5 @@ -use sqlite::{Connection, Error, Transaction}; +use anyhow::Result; +use sqlite::{Connection, Transaction}; use std::{rc::Rc, sync::RwLock}; pub struct Table { @@ -25,51 +26,34 @@ impl Database { // Actions /// Create new record in database - pub fn add(&self, profile_identity_id: i64, scope: &str) -> Result { - // Begin new transaction + pub fn add(&self, profile_identity_id: i64, scope: &str) -> Result { let mut writable = self.connection.write().unwrap(); // @TODO let tx = writable.transaction()?; - - // Create new record - insert(&tx, profile_identity_id, scope)?; - - // Hold insert ID for result - let id = last_insert_id(&tx); - - // Done - match tx.commit() { - Ok(_) => Ok(id), - Err(e) => Err(e), - } + let id = insert(&tx, profile_identity_id, scope)?; + tx.commit()?; + Ok(id) } /// Delete record with given `id` from database - pub fn delete(&self, id: i64) -> Result<(), Error> { - // Begin new transaction + pub fn delete(&self, id: i64) -> Result<()> { let mut writable = self.connection.write().unwrap(); // @TODO let tx = writable.transaction()?; - - // Create new record delete(&tx, id)?; - - // Done - match tx.commit() { - Ok(_) => Ok(()), - Err(e) => Err(e), - } + tx.commit()?; + Ok(()) } // Getters /// Get records from database match current `profile_id` optionally filtered by `scope` - pub fn records_scope(&self, scope: Option<&str>) -> Result, Error> { + pub fn records_scope(&self, scope: Option<&str>) -> Result> { let readable = self.connection.read().unwrap(); // @TODO let tx = readable.unchecked_transaction()?; select_scope(&tx, scope) } /// Get records from database match current `profile_id` optionally filtered by `scope` - pub fn records_ref(&self, profile_identity_id: i64) -> Result, Error> { + pub fn records_ref(&self, profile_identity_id: i64) -> Result> { let readable = self.connection.read().unwrap(); // @TODO let tx = readable.unchecked_transaction()?; select_ref(&tx, profile_identity_id) @@ -78,8 +62,8 @@ impl Database { // Low-level DB API -pub fn init(tx: &Transaction) -> Result { - tx.execute( +pub fn init(tx: &Transaction) -> Result { + Ok(tx.execute( "CREATE TABLE IF NOT EXISTS `profile_identity_auth` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, @@ -90,24 +74,25 @@ pub fn init(tx: &Transaction) -> Result { UNIQUE (`scope`) )", [], - ) + )?) } -pub fn insert(tx: &Transaction, profile_identity_id: i64, scope: &str) -> Result { +pub fn insert(tx: &Transaction, profile_identity_id: i64, scope: &str) -> Result { tx.execute( "INSERT INTO `profile_identity_auth` ( `profile_identity_id`, `scope` ) VALUES (?, ?)", (profile_identity_id, scope), - ) + )?; + Ok(tx.last_insert_rowid()) } -pub fn delete(tx: &Transaction, id: i64) -> Result { - tx.execute("DELETE FROM `profile_identity_auth` WHERE `id` = ?", [id]) +pub fn delete(tx: &Transaction, id: i64) -> Result { + Ok(tx.execute("DELETE FROM `profile_identity_auth` WHERE `id` = ?", [id])?) } -pub fn select_scope(tx: &Transaction, scope: Option<&str>) -> Result, Error> { +pub fn select_scope(tx: &Transaction, scope: Option<&str>) -> Result> { let mut stmt = tx.prepare( "SELECT `id`, `profile_identity_id`, @@ -135,7 +120,7 @@ pub fn select_scope(tx: &Transaction, scope: Option<&str>) -> Result, Ok(records) } -pub fn select_ref(tx: &Transaction, profile_identity_id: i64) -> Result, Error> { +pub fn select_ref(tx: &Transaction, profile_identity_id: i64) -> Result> { let mut stmt = tx.prepare( "SELECT `id`, `profile_identity_id`, @@ -162,7 +147,3 @@ pub fn select_ref(tx: &Transaction, profile_identity_id: i64) -> Result i64 { - tx.last_insert_rowid() -} diff --git a/src/profile/identity/auth/error.rs b/src/profile/identity/auth/error.rs deleted file mode 100644 index 31c2bcbf..00000000 --- a/src/profile/identity/auth/error.rs +++ /dev/null @@ -1,16 +0,0 @@ -use std::fmt::{Display, Formatter, Result}; - -#[derive(Debug)] -pub enum Error { - Database(sqlite::Error), - Memory(super::memory::Error), -} - -impl Display for Error { - fn fmt(&self, f: &mut Formatter) -> Result { - match self { - Self::Database(e) => write!(f, "Database error: {e}"), - Self::Memory(e) => write!(f, "Memory error: {e}"), - } - } -} diff --git a/src/profile/identity/auth/memory.rs b/src/profile/identity/auth/memory.rs index 9679bce4..ba07b85e 100644 --- a/src/profile/identity/auth/memory.rs +++ b/src/profile/identity/auth/memory.rs @@ -1,9 +1,7 @@ pub mod auth; -pub mod error; +use anyhow::{bail, Result}; pub use auth::Auth; -pub use error::Error; - use std::{cell::RefCell, collections::HashMap}; /// Reduce disk usage by cache Auth index in memory @@ -31,30 +29,30 @@ impl Memory { /// Add new record with `scope` as key and `profile_identity_id` as value /// * validate record with same key does not exist yet - pub fn add(&self, scope: String, profile_identity_id: i64) -> Result<(), Error> { + pub fn add(&self, scope: String, profile_identity_id: i64) -> Result<()> { // Borrow shared index access let mut index = self.index.borrow_mut(); // Prevent existing key overwrite if index.contains_key(&scope) { - return Err(Error::Overwrite(scope)); + bail!("Overwrite attempt for existing record `{scope}`") } // Slot should be free, let check it twice match index.insert(scope, profile_identity_id) { - Some(_) => Err(Error::Unexpected), + Some(_) => bail!("Unexpected error"), None => Ok(()), } } /// Cleanup index - pub fn clear(&self) -> Result<(), Error> { + pub fn clear(&self) -> Result<()> { let mut index = self.index.borrow_mut(); index.clear(); if index.is_empty() { Ok(()) } else { - Err(Error::Clear) + bail!("Could not cleanup memory index") } } diff --git a/src/profile/identity/auth/memory/error.rs b/src/profile/identity/auth/memory/error.rs deleted file mode 100644 index b4124dd5..00000000 --- a/src/profile/identity/auth/memory/error.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::fmt::{Display, Formatter, Result}; - -#[derive(Debug)] -pub enum Error { - Clear, - Overwrite(String), - Unexpected, -} - -impl Display for Error { - fn fmt(&self, f: &mut Formatter) -> Result { - match self { - Self::Clear => write!(f, "Could not cleanup memory index"), - Self::Overwrite(key) => { - write!(f, "Overwrite attempt for existing record `{key}`") - } - Self::Unexpected => write!(f, "Unexpected error"), - } - } -} diff --git a/src/profile/identity/error.rs b/src/profile/identity/error.rs deleted file mode 100644 index 8097a694..00000000 --- a/src/profile/identity/error.rs +++ /dev/null @@ -1,24 +0,0 @@ -use std::fmt::{Display, Formatter, Result}; - -#[derive(Debug)] -pub enum Error { - Auth(super::auth::Error), - Certificate(Box), - Database(sqlite::Error), - Memory(super::memory::Error), -} - -impl Display for Error { - fn fmt(&self, f: &mut Formatter) -> Result { - match self { - Self::Auth(e) => write!(f, "Could not create auth: {e}"), - Self::Certificate(e) => { - write!(f, "Could not create certificate: {e}") - } - Self::Database(e) => { - write!(f, "Database error: {e}") - } - Self::Memory(e) => write!(f, "Memory error: {e}"), - } - } -} diff --git a/src/profile/identity/item.rs b/src/profile/identity/item.rs index 9743250a..615d7f4d 100644 --- a/src/profile/identity/item.rs +++ b/src/profile/identity/item.rs @@ -1,6 +1,4 @@ -mod error; -use error::Error; - +use anyhow::{bail, Result}; use gtk::gio::TlsCertificate; /// Gemini identity holder for cached record in application-wide struct format. @@ -12,10 +10,10 @@ pub struct Item { impl Item { /// Convert `Self` to [TlsCertificate](https://docs.gtk.org/gio/class.TlsCertificate.html) - pub fn to_tls_certificate(&self) -> Result { + pub fn to_tls_certificate(&self) -> Result { match TlsCertificate::from_pem(&self.pem) { Ok(certificate) => Ok(certificate), - Err(e) => Err(Error::TlsCertificate(e)), + Err(e) => bail!("TLS certificate error: {e}"), } } } diff --git a/src/profile/identity/item/error.rs b/src/profile/identity/item/error.rs deleted file mode 100644 index f9ab509a..00000000 --- a/src/profile/identity/item/error.rs +++ /dev/null @@ -1,15 +0,0 @@ -use gtk::glib; -use std::fmt::{Display, Formatter, Result}; - -#[derive(Debug)] -pub enum Error { - TlsCertificate(glib::Error), -} - -impl Display for Error { - fn fmt(&self, f: &mut Formatter) -> Result { - match self { - Self::TlsCertificate(e) => write!(f, "TLS certificate error: {e}"), - } - } -} diff --git a/src/profile/identity/memory.rs b/src/profile/identity/memory.rs index 969762ef..041f76d7 100644 --- a/src/profile/identity/memory.rs +++ b/src/profile/identity/memory.rs @@ -1,6 +1,4 @@ -pub mod error; -pub use error::Error; - +use anyhow::{bail, Result}; use std::{cell::RefCell, collections::HashMap}; /// Reduce disk usage by cache index in memory @@ -28,38 +26,38 @@ impl Memory { /// Add new record with `id` as key and `pem` as value /// * validate record with same key does not exist yet - pub fn add(&self, profile_identity_id: i64, pem: String) -> Result<(), Error> { + pub fn add(&self, profile_identity_id: i64, pem: String) -> Result<()> { // Borrow shared index access let mut index = self.index.borrow_mut(); // Prevent existing key overwrite if index.contains_key(&profile_identity_id) { - return Err(Error::Overwrite(profile_identity_id)); + bail!("Overwrite attempt for existing record `{profile_identity_id}`") } // Slot should be free, let check it twice match index.insert(profile_identity_id, pem) { - Some(_) => Err(Error::Unexpected), + Some(_) => bail!("Unexpected error"), None => Ok(()), } } /// Get `pem` clone by `id` from memory index - pub fn get(&self, id: i64) -> Result { + pub fn get(&self, id: i64) -> Result { match self.index.borrow().get(&id) { Some(pem) => Ok(pem.clone()), - None => Err(Error::NotFound(id)), + None => bail!("Record `{id}` not found in memory index"), } } /// Cleanup index - pub fn clear(&self) -> Result<(), Error> { + pub fn clear(&self) -> Result<()> { let mut index = self.index.borrow_mut(); index.clear(); if index.is_empty() { Ok(()) } else { - Err(Error::Clear) + bail!("Could not cleanup memory index") } } } diff --git a/src/profile/identity/memory/error.rs b/src/profile/identity/memory/error.rs deleted file mode 100644 index 691abaab..00000000 --- a/src/profile/identity/memory/error.rs +++ /dev/null @@ -1,22 +0,0 @@ -use std::fmt::{Display, Formatter, Result}; - -#[derive(Debug)] -pub enum Error { - Clear, - NotFound(i64), - Overwrite(i64), - Unexpected, -} - -impl Display for Error { - fn fmt(&self, f: &mut Formatter) -> Result { - match self { - Self::Clear => write!(f, "Could not cleanup memory index"), - Self::NotFound(key) => { - write!(f, "Record `{key}` not found in memory index") - } - Self::Overwrite(key) => write!(f, "Overwrite attempt for existing record `{key}`"), - Self::Unexpected => write!(f, "Unexpected error"), - } - } -} diff --git a/src/profile/search.rs b/src/profile/search.rs index db892335..ac3651ee 100644 --- a/src/profile/search.rs +++ b/src/profile/search.rs @@ -1,9 +1,8 @@ mod database; -mod error; mod memory; +use anyhow::Result; use database::Database; -use error::Error; use gtk::glib::Uri; use memory::Memory; use sqlite::{Connection, Transaction}; @@ -18,40 +17,30 @@ impl Search { // Constructors /// Create new `Self` - pub fn build(connection: &Rc>, profile_id: &Rc) -> Result { - match Database::init(connection, profile_id) { - Ok(database) => { - // Init fast search index - let memory = Memory::init(); - - // Build initial index - index(&database, &memory)?; - - // Return new `Self` - Ok(Self { database, memory }) - } - Err(e) => Err(Error::Database(e)), - } + pub fn build(connection: &Rc>, profile_id: &Rc) -> Result { + let database = Database::init(connection, profile_id)?; + // Init fast search index + let memory = Memory::init(); + // Build initial index + index(&database, &memory)?; + // Return new `Self` + Ok(Self { database, memory }) } // Actions /// Add new search provider record /// * requires valid [Uri](https://docs.gtk.org/glib/struct.Uri.html) - pub fn add(&self, query: &Uri, is_default: bool) -> Result<(), Error> { - match self.database.add(query.to_string(), is_default) { - Ok(_) => index(&self.database, &self.memory), - Err(e) => Err(Error::Database(e)), - } + pub fn add(&self, query: &Uri, is_default: bool) -> Result<()> { + self.database.add(query.to_string(), is_default)?; + Ok(()) } /// Add new search provider record /// * requires valid [Uri](https://docs.gtk.org/glib/struct.Uri.html) - pub fn set_default(&self, profile_search_id: i64) -> Result<(), Error> { - match self.database.set_default(profile_search_id) { - Ok(_) => index(&self.database, &self.memory), - Err(e) => Err(Error::Database(e)), - } + pub fn set_default(&self, profile_search_id: i64) -> Result<()> { + self.database.set_default(profile_search_id)?; + index(&self.database, &self.memory) } /// Get records from the memory index @@ -60,11 +49,9 @@ impl Search { } /// Delete record from `database` and `memory` index - pub fn delete(&self, id: i64) -> Result<(), Error> { - match self.database.delete(id) { - Ok(_) => index(&self.database, &self.memory), - Err(e) => Err(Error::Database(e)), - } + pub fn delete(&self, id: i64) -> Result<()> { + self.database.delete(id)?; + index(&self.database, &self.memory) } // Getters @@ -77,11 +64,9 @@ impl Search { // Tools -pub fn migrate(tx: &Transaction) -> Result<(), String> { +pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components - if let Err(e) = database::init(tx) { - return Err(e.to_string()); - } + database::init(tx)?; // Delegate migration to childs // nothing yet.. @@ -91,15 +76,10 @@ pub fn migrate(tx: &Transaction) -> Result<(), String> { } /// Sync memory index with database -fn index(database: &Database, memory: &Memory) -> Result<(), Error> { +fn index(database: &Database, memory: &Memory) -> Result<()> { memory.clear(); - match database.records() { - Ok(records) => { - for record in records { - memory.push(record.id, record.query, record.is_default) - } - } - Err(e) => return Err(Error::Database(e)), + for record in database.records()? { + memory.push(record.id, record.query, record.is_default) } Ok(()) } diff --git a/src/profile/search/database.rs b/src/profile/search/database.rs index c4d54dc3..fae11431 100644 --- a/src/profile/search/database.rs +++ b/src/profile/search/database.rs @@ -1,4 +1,5 @@ -use sqlite::{Connection, Error, Transaction}; +use anyhow::Result; +use sqlite::{Connection, Transaction}; use std::{rc::Rc, sync::RwLock}; #[derive(Clone)] @@ -18,7 +19,7 @@ impl Database { // Constructors /// Create new `Self` - pub fn init(connection: &Rc>, profile_id: &Rc) -> Result { + pub fn init(connection: &Rc>, profile_id: &Rc) -> Result { let mut writable = connection.write().unwrap(); // @TODO handle let tx = writable.transaction()?; @@ -38,7 +39,7 @@ impl Database { // Getters /// Get records from database - pub fn records(&self) -> Result, Error> { + pub fn records(&self) -> Result> { let readable = self.connection.read().unwrap(); // @TODO handle let tx = readable.unchecked_transaction()?; select(&tx, *self.profile_id) @@ -48,30 +49,19 @@ impl Database { /// Create new record in database /// * return last insert ID on success - pub fn add(&self, query: String, is_default: bool) -> Result { - // Begin new transaction + pub fn add(&self, query: String, is_default: bool) -> Result { let mut writable = self.connection.write().unwrap(); // @TODO handle let tx = writable.transaction()?; - - // Create new record if is_default { - // make sure only one default provider in set reset(&tx, *self.profile_id, !is_default)?; } - insert(&tx, *self.profile_id, query, is_default)?; - - // Hold insert ID for result - let id = last_insert_id(&tx); - - // Done - match tx.commit() { - Ok(_) => Ok(id), - Err(e) => Err(e), - } + let id = insert(&tx, *self.profile_id, query, is_default)?; + tx.commit()?; + Ok(id) } /// Delete record from database - pub fn delete(&self, id: i64) -> Result<(), Error> { + pub fn delete(&self, id: i64) -> Result<()> { // Begin new transaction let mut writable = self.connection.write().unwrap(); // @TODO let tx = writable.transaction()?; @@ -100,11 +90,12 @@ impl Database { } // Done - tx.commit() + tx.commit()?; + Ok(()) } /// Delete record from database - pub fn set_default(&self, id: i64) -> Result<(), Error> { + pub fn set_default(&self, id: i64) -> Result<()> { // Begin new transaction let mut writable = self.connection.write().unwrap(); // @TODO let tx = writable.transaction()?; @@ -114,14 +105,15 @@ impl Database { // Delete record by ID set_default(&tx, *self.profile_id, id, true)?; - tx.commit() + tx.commit()?; + Ok(()) } } // Low-level DB API -pub fn init(tx: &Transaction) -> Result { - tx.execute( +pub fn init(tx: &Transaction) -> Result { + Ok(tx.execute( "CREATE TABLE IF NOT EXISTS `profile_search` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, @@ -132,15 +124,10 @@ pub fn init(tx: &Transaction) -> Result { FOREIGN KEY (`profile_id`) REFERENCES `profile` (`id`) )", [], - ) + )?) } -fn insert( - tx: &Transaction, - profile_id: i64, - query: String, - is_default: bool, -) -> Result { +fn insert(tx: &Transaction, profile_id: i64, query: String, is_default: bool) -> Result { tx.execute( "INSERT INTO `profile_search` ( `profile_id`, @@ -148,10 +135,11 @@ fn insert( `query` ) VALUES (?, ?, ?)", (profile_id, is_default, query), - ) + )?; + Ok(tx.last_insert_rowid()) } -fn select(tx: &Transaction, profile_id: i64) -> Result, Error> { +fn select(tx: &Transaction, profile_id: i64) -> Result> { let mut stmt = tx.prepare( "SELECT `id`, `profile_id`, `is_default`, `query` FROM `profile_search` @@ -177,35 +165,26 @@ fn select(tx: &Transaction, profile_id: i64) -> Result, Error> { Ok(records) } -fn delete(tx: &Transaction, id: i64) -> Result { - tx.execute("DELETE FROM `profile_search` WHERE `id` = ?", [id]) +fn delete(tx: &Transaction, id: i64) -> Result { + Ok(tx.execute("DELETE FROM `profile_search` WHERE `id` = ?", [id])?) } -fn reset(tx: &Transaction, profile_id: i64, is_default: bool) -> Result { - tx.execute( +fn reset(tx: &Transaction, profile_id: i64, is_default: bool) -> Result { + Ok(tx.execute( "UPDATE `profile_search` SET `is_default` = ? WHERE `profile_id` = ?", (is_default, profile_id), - ) + )?) } -fn set_default( - tx: &Transaction, - profile_id: i64, - id: i64, - is_default: bool, -) -> Result { - tx.execute( +fn set_default(tx: &Transaction, profile_id: i64, id: i64, is_default: bool) -> Result { + Ok(tx.execute( "UPDATE `profile_search` SET `is_default` = ? WHERE `profile_id` = ? AND `id` = ?", (is_default, profile_id, id), - ) -} - -fn last_insert_id(tx: &Transaction) -> i64 { - tx.last_insert_rowid() + )?) } /// Init default search providers list for given profile -fn add_defaults(tx: &Transaction, profile_id: i64) -> Result<(), Error> { +fn add_defaults(tx: &Transaction, profile_id: i64) -> Result<()> { for (provider, is_default) in &[ ("gemini://tlgs.one/search/search", true), ("gemini://kennedy.gemi.dev/search", false), diff --git a/src/profile/search/error.rs b/src/profile/search/error.rs deleted file mode 100644 index a9ab3744..00000000 --- a/src/profile/search/error.rs +++ /dev/null @@ -1,16 +0,0 @@ -use std::fmt::{Display, Formatter, Result}; - -#[derive(Debug)] -pub enum Error { - Database(sqlite::Error), -} - -impl Display for Error { - fn fmt(&self, f: &mut Formatter) -> Result { - match self { - Self::Database(e) => { - write!(f, "Database error: {e}") - } - } - } -}