[niepce] engine+rust: Update rusqlite to 0.25.3



commit 411b210e33df0b2dbeff1ac0909ed3749a5608fb
Author: Hubert Figuière <hub figuiere net>
Date:   Fri Jul 2 18:30:26 2021 -0400

    engine+rust: Update rusqlite to 0.25.3
    
    - add source() to Error

 Cargo.lock                                       |  71 +++++--
 crates/npc-engine/Cargo.toml                     |   2 +-
 crates/npc-engine/src/db/keyword.rs              |   6 +-
 crates/npc-engine/src/db/label.rs                |   8 +-
 crates/npc-engine/src/db/libfile.rs              |  24 +--
 crates/npc-engine/src/db/libfolder.rs            |  18 +-
 crates/npc-engine/src/db/libmetadata.rs          |  14 +-
 crates/npc-engine/src/db/library.rs              | 238 +++++++++++++----------
 crates/npc-engine/src/db/mod.rs                  |   4 +-
 crates/npc-engine/src/library/notification.rs    |  11 +-
 crates/npc-engine/src/library/thumbnail_cache.rs |  25 ++-
 crates/npc-fwk/src/toolkit/mod.rs                |  12 +-
 niepce-main/src/libraryclient/mod.rs             |   9 +-
 13 files changed, 247 insertions(+), 195 deletions(-)
---
diff --git a/Cargo.lock b/Cargo.lock
index 2b2afcc..eedfc0b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,17 @@
 # It is not intended for manual editing.
 version = 3
 
+[[package]]
+name = "ahash"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "43bb833f0bf979d8475d38fbf09ed3b8a55e1885fe93ad3f93239fc6a4f17b98"
+dependencies = [
+ "getrandom",
+ "once_cell",
+ "version_check",
+]
+
 [[package]]
 name = "ansi_term"
 version = "0.11.0"
@@ -207,6 +218,18 @@ dependencies = [
  "pkg-config",
 ]
 
+[[package]]
+name = "fallible-iterator"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
+
+[[package]]
+name = "fallible-streaming-iterator"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
+
 [[package]]
 name = "field-offset"
 version = "0.3.4"
@@ -500,6 +523,18 @@ name = "hashbrown"
 version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "hashlink"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf"
+dependencies = [
+ "hashbrown",
+]
 
 [[package]]
 name = "heck"
@@ -572,20 +607,14 @@ dependencies = [
 
 [[package]]
 name = "libsqlite3-sys"
-version = "0.9.3"
+version = "0.22.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "d3711dfd91a1081d2458ad2d06ea30a8755256e74038be2ad927d94e1c955ca8"
+checksum = "290b64917f8b0cb885d9de0f9959fe1f775d7fa12f1da2db9001c1c8ab60f89d"
 dependencies = [
  "pkg-config",
  "vcpkg",
 ]
 
-[[package]]
-name = "linked-hash-map"
-version = "0.5.4"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
-
 [[package]]
 name = "log"
 version = "0.4.14"
@@ -595,21 +624,18 @@ dependencies = [
  "cfg-if",
 ]
 
-[[package]]
-name = "lru-cache"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
-dependencies = [
- "linked-hash-map",
-]
-
 [[package]]
 name = "maplit"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index";
 checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
 
+[[package]]
+name = "memchr"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index";
+checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc"
+
 [[package]]
 name = "memoffset"
 version = "0.6.4"
@@ -913,14 +939,17 @@ dependencies = [
 
 [[package]]
 name = "rusqlite"
-version = "0.14.0"
+version = "0.25.3"
 source = "registry+https://github.com/rust-lang/crates.io-index";
-checksum = "c9d9118f1ce84d8d0b67f9779936432fb42bb620cef2122409d786892cce9a3c"
+checksum = "57adcf67c8faaf96f3248c2a7b419a0dbc52ebe36ba83dd57fe83827c1ea4eb3"
 dependencies = [
  "bitflags",
+ "fallible-iterator",
+ "fallible-streaming-iterator",
+ "hashlink",
  "libsqlite3-sys",
- "lru-cache",
- "time",
+ "memchr",
+ "smallvec",
 ]
 
 [[package]]
diff --git a/crates/npc-engine/Cargo.toml b/crates/npc-engine/Cargo.toml
index 1386ecf..4a14690 100644
--- a/crates/npc-engine/Cargo.toml
+++ b/crates/npc-engine/Cargo.toml
@@ -17,7 +17,7 @@ glib = "*"
 lazy_static = "^1.2.0"
 libc = "0.2.39"
 maplit = "1.0.2"
-rusqlite = { version = "0.14.0", features = ["functions"] }
+rusqlite = { version = "0.25.3", features = ["functions"] }
 try_opt = "0.1.1"
 
 npc-fwk = { path = "../npc-fwk" }
diff --git a/crates/npc-engine/src/db/keyword.rs b/crates/npc-engine/src/db/keyword.rs
index cfffce8..cd9b158 100644
--- a/crates/npc-engine/src/db/keyword.rs
+++ b/crates/npc-engine/src/db/keyword.rs
@@ -60,9 +60,9 @@ impl FromDb for Keyword {
         "id"
     }
 
-    fn read_from(row: &rusqlite::Row) -> Self {
-        let kw: String = row.get(1);
-        Keyword::new(row.get(0), &kw)
+    fn read_from(row: &rusqlite::Row) -> rusqlite::Result<Self> {
+        let kw: String = row.get(1)?;
+        Ok(Keyword::new(row.get(0)?, &kw))
     }
 }
 
diff --git a/crates/npc-engine/src/db/label.rs b/crates/npc-engine/src/db/label.rs
index bf914ae..1e0feca 100644
--- a/crates/npc-engine/src/db/label.rs
+++ b/crates/npc-engine/src/db/label.rs
@@ -79,10 +79,10 @@ impl FromDb for Label {
         "id"
     }
 
-    fn read_from(row: &rusqlite::Row) -> Self {
-        let label: String = row.get(1);
-        let colour: String = row.get(2);
-        Label::new(row.get(0), &label, &colour)
+    fn read_from(row: &rusqlite::Row) -> rusqlite::Result<Self> {
+        let label: String = row.get(1)?;
+        let colour: String = row.get(2)?;
+        Ok(Label::new(row.get(0)?, &label, &colour))
     }
 }
 
diff --git a/crates/npc-engine/src/db/libfile.rs b/crates/npc-engine/src/db/libfile.rs
index e023fc4..c4b0fa2 100644
--- a/crates/npc-engine/src/db/libfile.rs
+++ b/crates/npc-engine/src/db/libfile.rs
@@ -237,23 +237,23 @@ impl FromDb for LibFile {
         "id"
     }
 
-    fn read_from(row: &rusqlite::Row) -> Self {
+    fn read_from(row: &rusqlite::Row) -> rusqlite::Result<Self> {
         //DBG_ASSERT(dbdrv->get_number_of_columns() == 10, "wrong number of columns");
-        let id = row.get(0);
-        let fid = row.get(1);
-        let path: String = row.get(2);
-        let name: String = row.get(3);
-        let fsfid = row.get(8);
+        let id = row.get(0)?;
+        let fid = row.get(1)?;
+        let path: String = row.get(2)?;
+        let name: String = row.get(3)?;
+        let fsfid = row.get(8)?;
         let mut file = LibFile::new(id, fid, fsfid, PathBuf::from(&path), &name);
 
-        file.set_orientation(row.get(4));
-        file.set_rating(row.get(5));
-        file.set_label(row.get(6));
-        file.set_flag(row.get(9));
-        let file_type: i32 = row.get(7);
+        file.set_orientation(row.get(4)?);
+        file.set_rating(row.get(5)?);
+        file.set_label(row.get(6)?);
+        file.set_flag(row.get(9)?);
+        let file_type: i32 = row.get(7)?;
         file.set_file_type(FileType::from(file_type));
 
-        file
+        Ok(file)
     }
 }
 
diff --git a/crates/npc-engine/src/db/libfolder.rs b/crates/npc-engine/src/db/libfolder.rs
index f5107fe..954da49 100644
--- a/crates/npc-engine/src/db/libfolder.rs
+++ b/crates/npc-engine/src/db/libfolder.rs
@@ -123,14 +123,14 @@ impl FromDb for LibFolder {
         "id"
     }
 
-    fn read_from(row: &rusqlite::Row) -> Self {
-        let id: LibraryId = row.get(0);
-        let name: String = row.get(1);
-        let virt_type: i32 = row.get(2);
-        let locked = row.get(3);
-        let expanded = row.get(4);
-        let path: Option<String> = row.get_checked(5).ok();
-        let parent = row.get(6);
+    fn read_from(row: &rusqlite::Row) -> rusqlite::Result<Self> {
+        let id: LibraryId = row.get(0)?;
+        let name: String = row.get(1)?;
+        let virt_type: i32 = row.get(2)?;
+        let locked = row.get(3)?;
+        let expanded = row.get(4)?;
+        let path: Option<String> = row.get(5).ok();
+        let parent = row.get(6)?;
 
         let mut libfolder = LibFolder::new(id, &name, path);
         libfolder.set_parent(parent);
@@ -138,7 +138,7 @@ impl FromDb for LibFolder {
         libfolder.set_locked(locked);
         libfolder.set_expanded(expanded);
 
-        libfolder
+        Ok(libfolder)
     }
 }
 
diff --git a/crates/npc-engine/src/db/libmetadata.rs b/crates/npc-engine/src/db/libmetadata.rs
index 744d5f7..293da87 100644
--- a/crates/npc-engine/src/db/libmetadata.rs
+++ b/crates/npc-engine/src/db/libmetadata.rs
@@ -277,18 +277,18 @@ impl FromDb for LibMetadata {
         "files.id"
     }
 
-    fn read_from(row: &rusqlite::Row) -> Self {
-        let id: LibraryId = row.get(0);
-        let xmp: String = row.get(1);
+    fn read_from(row: &rusqlite::Row) -> rusqlite::Result<Self> {
+        let id: LibraryId = row.get(0)?;
+        let xmp: String = row.get(1)?;
 
         let mut xmpmeta = XmpMeta::new();
         xmpmeta.unserialize(&xmp);
         let mut libmeta = LibMetadata::new_with_xmp(id, xmpmeta);
-        let col: i32 = row.get(2);
+        let col: i32 = row.get(2)?;
         libmeta.file_type = FileType::from(col);
-        libmeta.name = row.get(3);
-        libmeta.folder = row.get(4);
-        libmeta
+        libmeta.name = row.get(3)?;
+        libmeta.folder = row.get(4)?;
+        Ok(libmeta)
     }
 }
 
diff --git a/crates/npc-engine/src/db/library.rs b/crates/npc-engine/src/db/library.rs
index bc52c17..48e93ad 100644
--- a/crates/npc-engine/src/db/library.rs
+++ b/crates/npc-engine/src/db/library.rs
@@ -1,7 +1,7 @@
 /*
  * niepce - engine/db/library.rs
  *
- * Copyright (C) 2017-2020 Hubert Figuière
+ * Copyright (C) 2017-2021 Hubert Figuière
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@ use std::result;
 
 use chrono::Utc;
 use rusqlite;
+use rusqlite::{functions::FunctionFlags, params};
 
 use super::props::NiepceProperties as Np;
 use super::props::NiepcePropertyIdx::*;
@@ -68,6 +69,21 @@ impl From<rusqlite::Error> for Error {
     }
 }
 
+impl std::fmt::Display for Error {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for Error {
+    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+        match *self {
+            Self::SqlError(ref err) => Some(err),
+            _ => None,
+        }
+    }
+}
+
 pub type Result<T> = result::Result<T, Error>;
 
 pub struct Library {
@@ -128,15 +144,21 @@ impl Library {
     fn init(&mut self) -> Result<()> {
         if let Some(ref conn) = self.dbconn {
             let sender = self.sender.clone();
-            if let Err(err) = conn.create_scalar_function("rewrite_xmp", 0, false, move |_| {
-                if let Err(err) =
-                    toolkit::thread_context().block_on(sender.send(LibNotification::XmpNeedsUpdate)) {
-                    // This not fatal, at least the data should be saved.
-                    // But still, it's not good.
-                    err_out!("Error sending XmpNeedsUpdate notification: {}", err);
-                }
-                Ok(true)
-            }) {
+            if let Err(err) = conn.create_scalar_function(
+                "rewrite_xmp",
+                0,
+                FunctionFlags::SQLITE_UTF8,
+                move |_| {
+                    if let Err(err) = toolkit::thread_context()
+                        .block_on(sender.send(LibNotification::XmpNeedsUpdate))
+                    {
+                        // This not fatal, at least the data should be saved.
+                        // But still, it's not good.
+                        err_out!("Error sending XmpNeedsUpdate notification: {}", err);
+                    }
+                    Ok(true)
+                },
+            ) {
                 err_out!("failed to create scalar function.");
                 return Err(Error::SqlError(err));
             }
@@ -171,9 +193,9 @@ impl Library {
     fn check_database_version(&self) -> Result<i32> {
         if let Some(ref conn) = self.dbconn {
             if let Ok(mut stmt) = conn.prepare("SELECT value FROM admin WHERE key='version'") {
-                let mut rows = stmt.query(&[]).unwrap();
-                if let Some(Ok(row)) = rows.next() {
-                    let value: String = row.get(0);
+                let mut rows = stmt.query([])?;
+                if let Ok(Some(row)) = rows.next() {
+                    let value: String = row.get(0)?;
                     if let Ok(v) = i32::from_str_radix(&value, 10) {
                         return Ok(v);
                     } else {
@@ -191,17 +213,17 @@ impl Library {
 
     fn init_db(&mut self) -> Result<()> {
         if let Some(ref conn) = self.dbconn {
-            conn.execute("CREATE TABLE admin (key TEXT NOT NULL, value TEXT)", &[])
+            conn.execute("CREATE TABLE admin (key TEXT NOT NULL, value TEXT)", [])
                 .unwrap();
             conn.execute(
                 "INSERT INTO admin (key, value) \
                  VALUES ('version', ?1)",
-                &[&DB_SCHEMA_VERSION],
+                params![DB_SCHEMA_VERSION],
             )
             .unwrap();
             conn.execute(
                 "CREATE TABLE vaults (id INTEGER PRIMARY KEY, path TEXT)",
-                &[],
+                [],
             )
             .unwrap();
             conn.execute(
@@ -212,7 +234,7 @@ impl Library {
                  virtual INTEGER DEFAULT 0, \
                  expanded INTEGER DEFAULT 0, \
                  parent_id INTEGER)",
-                &[],
+                [],
             )
             .unwrap();
             // Version 9
@@ -221,7 +243,7 @@ impl Library {
                  BEGIN \
                  DELETE FROM files WHERE parent_id = old.id; \
                  END",
-                &[],
+                [],
             )
             .unwrap();
             //
@@ -229,7 +251,7 @@ impl Library {
             conn.execute(
                 "insert into folders (name, locked, virtual, parent_id, path) \
                  values (?1, 1, ?2, 0, '')",
-                &[&"Trash", &trash_type],
+                params!["Trash", trash_type],
             )
             .unwrap();
 
@@ -242,13 +264,13 @@ impl Library {
                  import_date INTEGER, mod_date INTEGER, \
                  xmp TEXT, xmp_date INTEGER, xmp_file INTEGER,\
                  jpeg_file INTEGER)",
-                &[],
+                [],
             )
             .unwrap();
             conn.execute(
                 "CREATE TABLE fsfiles (id INTEGER PRIMARY KEY,\
                  path TEXT)",
-                &[],
+                [],
             )
             .unwrap();
             // version = 7
@@ -256,7 +278,7 @@ impl Library {
                 "CREATE TABLE sidecars (file_id INTEGER,\
                  fsfile_id INTEGER, type INTEGER, ext TEXT NOT NULL,\
                  UNIQUE(file_id, fsfile_id))",
-                &[],
+                [],
             )
             .unwrap();
             conn.execute_batch(
@@ -278,13 +300,13 @@ impl Library {
             conn.execute(
                 "CREATE TABLE keywords (id INTEGER PRIMARY KEY,\
                  keyword TEXT, parent_id INTEGER DEFAULT 0)",
-                &[],
+                [],
             )
             .unwrap();
             conn.execute(
                 "CREATE TABLE keywording (file_id INTEGER,\
                  keyword_id INTEGER, UNIQUE(file_id, keyword_id))",
-                &[],
+                [],
             )
             .unwrap();
             conn.execute(
@@ -292,23 +314,23 @@ impl Library {
                  BEGIN \
                  DELETE FROM keywording WHERE keyword_id = old.id; \
                  END;",
-                &[],
+                [],
             )
             .unwrap();
             conn.execute(
                 "CREATE TABLE labels (id INTEGER PRIMARY KEY,\
                  name TEXT, color TEXT)",
-                &[],
+                [],
             )
             .unwrap();
-            conn.execute("CREATE TABLE xmp_update_queue (id INTEGER UNIQUE)", &[])
+            conn.execute("CREATE TABLE xmp_update_queue (id INTEGER UNIQUE)", [])
                 .unwrap();
             conn.execute(
                 "CREATE TRIGGER file_update_trigger UPDATE ON files \
                  BEGIN \
                  UPDATE files SET mod_date = strftime('%s','now');\
                  END",
-                &[],
+                [],
             )
             .unwrap();
             conn.execute(
@@ -317,7 +339,7 @@ impl Library {
                  INSERT OR IGNORE INTO xmp_update_queue (id) VALUES(new.id);\
                  SELECT rewrite_xmp();\
                  END",
-                &[],
+                [],
             )
             .unwrap();
 
@@ -337,8 +359,7 @@ impl Library {
         &self,
         notif: LibNotification,
     ) -> std::result::Result<(), async_channel::SendError<LibNotification>> {
-        toolkit::thread_context().block_on(
-            self.sender.send(notif))
+        toolkit::thread_context().block_on(self.sender.send(notif))
     }
 
     pub fn add_jpeg_file_to_bundle(&self, file_id: LibraryId, fsfile_id: LibraryId) -> Result<()> {
@@ -346,7 +367,7 @@ impl Library {
             let filetype: i32 = libfile::FileType::RawJpeg.into();
             let c = conn.execute(
                 "UPDATE files SET jpeg_file=?1, file_type=?3 WHERE id=?2;",
-                &[&fsfile_id, &file_id, &filetype],
+                params![fsfile_id, file_id, filetype],
             )?;
             if c == 1 {
                 return Ok(());
@@ -364,7 +385,7 @@ impl Library {
         if let Some(ref conn) = self.dbconn {
             let c = conn.execute(
                 "UPDATE files SET xmp_file=?1 WHERE id=?2;",
-                &[&fsfile_id, &file_id],
+                params![fsfile_id, file_id],
             )?;
             if c == 1 {
                 return Ok(());
@@ -401,7 +422,7 @@ impl Library {
         if let Some(ref conn) = self.dbconn {
             let c = conn.execute(
                 "INSERT INTO sidecars (file_id, fsfile_id, type, ext) VALUES(?1, ?2, ?3, ?4)",
-                &[&file_id, &fsfile_id, &sidecar_type, &ext],
+                params![file_id, fsfile_id, sidecar_type, ext],
             )?;
             if c == 1 {
                 return Ok(());
@@ -427,10 +448,10 @@ impl Library {
                 sql_where
             );
             let mut stmt = conn.prepare(&sql)?;
-            let mut rows = stmt.query(&[&id])?;
+            let mut rows = stmt.query(params![id])?;
             let mut files: Vec<LibFile> = vec![];
-            while let Some(Ok(row)) = rows.next() {
-                files.push(LibFile::read_from(&row));
+            while let Ok(Some(row)) = rows.next() {
+                files.push(LibFile::read_from(&row)?);
             }
             return Ok(files);
         }
@@ -460,7 +481,7 @@ impl Library {
         if let Some(ref conn) = self.dbconn {
             let c = conn.execute(
                 "INSERT INTO folders (path,name,vault_id,parent_id) VALUES(?1, ?2, '0', ?3)",
-                &[&path, &name, &into],
+                params![path, name, into],
             )?;
             if c != 1 {
                 return Err(Error::InvalidResult);
@@ -476,7 +497,7 @@ impl Library {
 
     pub fn delete_folder(&self, id: LibraryId) -> Result<()> {
         if let Some(ref conn) = self.dbconn {
-            let c = conn.execute("DELETE FROM folders WHERE id=?1", &[&id])?;
+            let c = conn.execute("DELETE FROM folders WHERE id=?1", params![id])?;
             if c == 1 {
                 return Ok(());
             }
@@ -496,14 +517,14 @@ impl Library {
                 LibFolder::read_db_tables()
             );
             let mut stmt = conn.prepare(&sql)?;
-            let mut rows = stmt.query(&[&path])?;
+            let mut rows = stmt.query(params![path])?;
             return match rows.next() {
-                None => Err(Error::NotFound),
-                Some(Err(err)) => {
+                Ok(None) => Err(Error::NotFound),
+                Err(err) => {
                     err_out!("Error {:?}", err);
                     Err(Error::from(err))
                 }
-                Some(Ok(row)) => Ok(LibFolder::read_from(&row)),
+                Ok(Some(row)) => Ok(LibFolder::read_from(&row)?),
             };
         }
         Err(Error::NoSqlDb)
@@ -517,10 +538,10 @@ impl Library {
                 LibFolder::read_db_tables()
             );
             let mut stmt = conn.prepare(&sql)?;
-            let mut rows = stmt.query(&[])?;
+            let mut rows = stmt.query([])?;
             let mut folders: Vec<LibFolder> = vec![];
-            while let Some(Ok(row)) = rows.next() {
-                folders.push(LibFolder::read_from(&row));
+            while let Ok(Some(row)) = rows.next() {
+                folders.push(LibFolder::read_from(&row)?);
             }
             return Ok(folders);
         }
@@ -537,11 +558,11 @@ impl Library {
                 "SELECT COUNT(id) FROM files \
                  WHERE parent_id=?1;",
             )?;
-            let mut rows = stmt.query(&[&folder_id])?;
+            let mut rows = stmt.query(params![folder_id])?;
             return match rows.next() {
-                Some(Ok(row)) => Ok(row.get(0)),
-                Some(Err(err)) => Err(Error::from(err)),
-                None => Err(Error::NotFound),
+                Ok(Some(row)) => Ok(row.get(0)?),
+                Err(err) => Err(Error::from(err)),
+                Ok(None) => Err(Error::NotFound),
             };
         }
         Err(Error::NoSqlDb)
@@ -555,10 +576,10 @@ impl Library {
                 Keyword::read_db_tables()
             );
             let mut stmt = conn.prepare(&sql)?;
-            let mut rows = stmt.query(&[])?;
+            let mut rows = stmt.query([])?;
             let mut keywords: Vec<Keyword> = vec![];
-            while let Some(Ok(row)) = rows.next() {
-                keywords.push(Keyword::read_from(&row));
+            while let Ok(Some(row)) = rows.next() {
+                keywords.push(Keyword::read_from(&row)?);
             }
             return Ok(keywords);
         }
@@ -571,11 +592,11 @@ impl Library {
                 "SELECT COUNT(keyword_id) FROM keywording \
                  WHERE keyword_id=?1;",
             )?;
-            let mut rows = stmt.query(&[&id])?;
+            let mut rows = stmt.query(params![id])?;
             return match rows.next() {
-                Some(Ok(row)) => Ok(row.get(0)),
-                Some(Err(err)) => Err(Error::from(err)),
-                None => Err(Error::NotFound),
+                Ok(Some(row)) => Ok(row.get(0)?),
+                Err(err) => Err(Error::from(err)),
+                Ok(None) => Err(Error::NotFound),
             };
         }
         Err(Error::NoSqlDb)
@@ -584,7 +605,7 @@ impl Library {
     pub fn add_fs_file<P: AsRef<Path>>(&self, f: P) -> Result<LibraryId> {
         if let Some(ref conn) = self.dbconn {
             let file = f.as_ref().to_string_lossy();
-            let c = conn.execute("INSERT INTO fsfiles (path) VALUES(?1)", &[&file])?;
+            let c = conn.execute("INSERT INTO fsfiles (path) VALUES(?1)", params![file])?;
             if c != 1 {
                 return Err(Error::InvalidResult);
             }
@@ -597,11 +618,11 @@ impl Library {
     fn get_fs_file(&self, id: LibraryId) -> Result<String> {
         if let Some(ref conn) = self.dbconn {
             let mut stmt = conn.prepare("SELECT path FROM fsfiles WHERE id=?1")?;
-            let mut rows = stmt.query(&[&id])?;
+            let mut rows = stmt.query(params![id])?;
             return match rows.next() {
-                Some(Ok(row)) => Ok(row.get(0)),
-                Some(Err(err)) => Err(Error::from(err)),
-                None => Err(Error::NotFound),
+                Ok(Some(row)) => Ok(row.get(0)?),
+                Err(err) => Err(Error::from(err)),
+                Ok(None) => Err(Error::NotFound),
             };
         }
         Err(Error::NoSqlDb)
@@ -719,19 +740,19 @@ impl Library {
                  file_type, flag, xmp) \
                  VALUES (\
                  ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12)",
-                &[
-                    &fs_file_id,
-                    &filename,
-                    &folder_id,
-                    &time,
-                    &time,
-                    &orientation,
-                    &creation_date,
-                    &rating,
-                    &label_id,
-                    &ifile_type,
-                    &flag,
-                    &xmp,
+                params![
+                    fs_file_id,
+                    filename,
+                    folder_id,
+                    time,
+                    time,
+                    orientation,
+                    creation_date,
+                    rating,
+                    label_id,
+                    ifile_type,
+                    flag,
+                    xmp,
                 ],
             )?;
 
@@ -760,9 +781,9 @@ impl Library {
                 "SELECT id FROM keywords WHERE \
                  keyword=?1;",
             )?;
-            let mut rows = stmt.query(&[&keyword])?;
-            if let Some(Ok(row)) = rows.next() {
-                let keyword_id = row.get(0);
+            let mut rows = stmt.query(params![keyword])?;
+            if let Ok(Some(row)) = rows.next() {
+                let keyword_id = row.get(0)?;
                 if keyword_id > 0 {
                     return Ok(keyword_id);
                 }
@@ -770,7 +791,7 @@ impl Library {
 
             let c = conn.execute(
                 "INSERT INTO keywords (keyword, parent_id) VALUES(?1, 0);",
-                &[&keyword],
+                params![keyword],
             )?;
             if c != 1 {
                 return Err(Error::InvalidResult);
@@ -795,7 +816,7 @@ impl Library {
                 "INSERT OR IGNORE INTO keywording\
                  (file_id, keyword_id) \
                  VALUES(?1, ?2)",
-                &[&kw_id, &file_id],
+                params![kw_id, file_id],
             )?;
             Ok(())
         } else {
@@ -821,18 +842,18 @@ impl Library {
                 LibMetadata::read_db_where_id()
             );
             let mut stmt = conn.prepare(&sql)?;
-            let mut rows = stmt.query(&[&file_id])?;
+            let mut rows = stmt.query(params![file_id])?;
             return match rows.next() {
-                Some(Err(err)) => Err(Error::from(err)),
-                None => Err(Error::NotFound),
-                Some(Ok(row)) => {
-                    let mut metadata = LibMetadata::read_from(&row);
+                Err(err) => Err(Error::from(err)),
+                Ok(None) => Err(Error::NotFound),
+                Ok(Some(row)) => {
+                    let mut metadata = LibMetadata::read_from(&row)?;
 
                     let sql = "SELECT ext FROM sidecars WHERE file_id=?1";
                     let mut stmt = conn.prepare(&sql)?;
-                    let mut rows = stmt.query(&[&file_id])?;
-                    while let Some(Ok(row)) = rows.next() {
-                        metadata.sidecars.push(row.get(0));
+                    let mut rows = stmt.query(params![file_id])?;
+                    while let Ok(Some(row)) = rows.next() {
+                        metadata.sidecars.push(row.get(0)?);
                     }
                     Ok(metadata)
                 }
@@ -846,7 +867,7 @@ impl Library {
             conn.execute(
                 "DELETE FROM keywording \
                  WHERE file_id=?1;",
-                &[&file_id],
+                params![file_id],
             )?;
             // we don't really know how many rows are supposed to be impacted
             // even 0 is valid.
@@ -859,7 +880,7 @@ impl Library {
         if let Some(ref conn) = self.dbconn {
             let c = conn.execute(
                 format!("UPDATE files SET {}=?1 WHERE id=?2;", column).as_ref(),
-                &[&value, &file_id],
+                params![value, file_id],
             )?;
             if c != 1 {
                 err_out!("error setting internal metadata");
@@ -873,7 +894,10 @@ impl Library {
     fn set_metadata_block(&self, file_id: LibraryId, metablock: &LibMetadata) -> Result<()> {
         let xmp = metablock.serialize_inline();
         if let Some(ref conn) = self.dbconn {
-            let c = conn.execute("UPDATE files SET xmp=?1 WHERE id=?2;", &[&xmp, &file_id])?;
+            let c = conn.execute(
+                "UPDATE files SET xmp=?1 WHERE id=?2;",
+                params![xmp, file_id],
+            )?;
             if c != 1 {
                 err_out!("error setting metadatablock");
                 return Err(Error::InvalidResult);
@@ -940,11 +964,11 @@ impl Library {
     pub fn move_file_to_folder(&self, file_id: LibraryId, folder_id: LibraryId) -> Result<()> {
         if let Some(ref conn) = self.dbconn {
             let mut stmt = conn.prepare("SELECT id FROM folders WHERE id=?1;")?;
-            let mut rows = stmt.query(&[&folder_id])?;
-            if let Some(Ok(_)) = rows.next() {
+            let mut rows = stmt.query(params![folder_id])?;
+            if let Ok(Some(_)) = rows.next() {
                 conn.execute(
                     "UPDATE files SET parent_id = ?1 WHERE id = ?2;",
-                    &[&folder_id, &file_id],
+                    params![folder_id, file_id],
                 )?;
                 return Ok(());
             } else {
@@ -962,10 +986,10 @@ impl Library {
                 Label::read_db_tables()
             );
             let mut stmt = conn.prepare(&sql)?;
-            let mut rows = stmt.query(&[])?;
+            let mut rows = stmt.query([])?;
             let mut labels: Vec<Label> = vec![];
-            while let Some(Ok(row)) = rows.next() {
-                labels.push(Label::read_from(&row));
+            while let Ok(Some(row)) = rows.next() {
+                labels.push(Label::read_from(&row)?);
             }
             return Ok(labels);
         }
@@ -976,7 +1000,7 @@ impl Library {
         if let Some(ref conn) = self.dbconn {
             let c = conn.execute(
                 "INSERT INTO  labels (name,color) VALUES (?1, ?2);",
-                &[&name, &colour],
+                params![name, colour],
             )?;
             if c != 1 {
                 return Err(Error::InvalidResult);
@@ -992,7 +1016,7 @@ impl Library {
         if let Some(ref conn) = self.dbconn {
             let c = conn.execute(
                 "UPDATE labels SET name=?2, color=?3 FROM labels WHERE id=?1;",
-                &[&label_id, &name, &colour],
+                params![label_id, name, colour],
             )?;
             if c != 1 {
                 return Err(Error::InvalidResult);
@@ -1016,10 +1040,10 @@ impl Library {
     fn get_xmp_ids_in_queue(&self) -> Result<Vec<LibraryId>> {
         if let Some(ref conn) = self.dbconn {
             let mut stmt = conn.prepare("SELECT id FROM xmp_update_queue;")?;
-            let mut rows = stmt.query(&[])?;
+            let mut rows = stmt.query([])?;
             let mut ids = Vec::<LibraryId>::new();
-            while let Some(Ok(row)) = rows.next() {
-                let id: i64 = row.get(0);
+            while let Ok(Some(row)) = rows.next() {
+                let id: i64 = row.get(0)?;
                 ids.push(id);
             }
             return Ok(ids);
@@ -1051,11 +1075,11 @@ impl Library {
                     "SELECT xmp, main_file, xmp_file FROM files \
                      WHERE id=?1;",
                 ) {
-                    let mut rows = stmt.query(&[&id]).unwrap();
-                    while let Some(Ok(row)) = rows.next() {
-                        let xmp_buffer: String = row.get(0);
-                        let main_file_id: LibraryId = row.get(1);
-                        let xmp_file_id: LibraryId = row.get(2);
+                    let mut rows = stmt.query(&[&id])?;
+                    while let Ok(Some(row)) = rows.next() {
+                        let xmp_buffer: String = row.get(0)?;
+                        let main_file_id: LibraryId = row.get(1)?;
+                        let xmp_file_id: LibraryId = row.get(2)?;
                         let spath: PathBuf;
                         let p = self.get_fs_file(main_file_id);
                         if let Ok(ref p) = p {
diff --git a/crates/npc-engine/src/db/mod.rs b/crates/npc-engine/src/db/mod.rs
index 2d21ff2..6224837 100644
--- a/crates/npc-engine/src/db/mod.rs
+++ b/crates/npc-engine/src/db/mod.rs
@@ -40,7 +40,7 @@ pub use self::props::NiepcePropertyIdx;
 
 use rusqlite;
 
-pub trait FromDb {
+pub trait FromDb: Sized {
     /// return the columns for reading from the DB.
     fn read_db_columns() -> &'static str;
     /// return the tables for reading from the DB.
@@ -48,5 +48,5 @@ pub trait FromDb {
     /// return the column for the where clause on the id for the DB.
     fn read_db_where_id() -> &'static str;
     /// read a new object from the DB row.
-    fn read_from(row: &rusqlite::Row) -> Self;
+    fn read_from(row: &rusqlite::Row) -> rusqlite::Result<Self>;
 }
diff --git a/crates/npc-engine/src/library/notification.rs b/crates/npc-engine/src/library/notification.rs
index 260c269..c377685 100644
--- a/crates/npc-engine/src/library/notification.rs
+++ b/crates/npc-engine/src/library/notification.rs
@@ -149,14 +149,9 @@ pub unsafe extern "C" fn engine_library_notify_filestatus_changed(
     id: LibraryId,
     status: FileStatus,
 ) -> bool {
-    if let Err(err) = toolkit::thread_context().block_on((*channel)
-        .0
-        .clone()
-        .send(LibNotification::FileStatusChanged(FileStatusChange {
-            id,
-            status,
-        })))
-    {
+    if let Err(err) = toolkit::thread_context().block_on((*channel).0.clone().send(
+        LibNotification::FileStatusChanged(FileStatusChange { id, status }),
+    )) {
         err_out!("Error sending notification: {}", err);
         return false;
     }
diff --git a/crates/npc-engine/src/library/thumbnail_cache.rs 
b/crates/npc-engine/src/library/thumbnail_cache.rs
index 0d15003..0badae2 100644
--- a/crates/npc-engine/src/library/thumbnail_cache.rs
+++ b/crates/npc-engine/src/library/thumbnail_cache.rs
@@ -102,7 +102,11 @@ impl ThumbnailCache {
         }
     }
 
-    fn execute(task: ThumbnailTask, cache_dir: &Path, sender: async_channel::Sender<LibNotification>) {
+    fn execute(
+        task: ThumbnailTask,
+        cache_dir: &Path,
+        sender: async_channel::Sender<LibNotification>,
+    ) {
         let w = task.width;
         let h = task.height;
         let libfile = task.file;
@@ -114,10 +118,12 @@ impl ThumbnailCache {
         let pix = get_thumbnail(&libfile, w, h, &dest);
         if !path.is_file() {
             dbg_out!("file doesn't exist");
-            if let Err(err) = 
toolkit::thread_context().block_on(sender.send(FileStatusChanged(FileStatusChange {
-                id,
-                status: FileStatus::Missing,
-            }))) {
+            if let Err(err) = toolkit::thread_context().block_on(sender.send(FileStatusChanged(
+                FileStatusChange {
+                    id,
+                    status: FileStatus::Missing,
+                },
+            ))) {
                 err_out!("Sending file status change notification failed: {}", err);
             }
         }
@@ -126,17 +132,16 @@ impl ThumbnailCache {
             return;
         }
         // notify the thumbnail
-        if let Err(err) = toolkit::thread_context().block_on(
-            sender.send(ThumbnailLoaded(notification::Thumbnail {
+        if let Err(err) = toolkit::thread_context().block_on(sender.send(ThumbnailLoaded(
+            notification::Thumbnail {
                 id,
                 width: pix.get_width(),
                 height: pix.get_height(),
                 pix,
-            })))
-        {
+            },
+        ))) {
             err_out!("Sending thumbnail notification failed: {}", err);
         }
-
     }
 
     fn main(
diff --git a/crates/npc-fwk/src/toolkit/mod.rs b/crates/npc-fwk/src/toolkit/mod.rs
index 8f43017..f456fd2 100644
--- a/crates/npc-fwk/src/toolkit/mod.rs
+++ b/crates/npc-fwk/src/toolkit/mod.rs
@@ -30,11 +30,9 @@ pub type Sender<T> = async_channel::Sender<T>;
 pub struct PortableChannel<T>(pub Sender<T>);
 
 pub fn thread_context() -> glib::MainContext {
-    glib::MainContext::thread_default()
-        .unwrap_or_else(|| {
-            let ctx = glib::MainContext::new();
-            ctx.push_thread_default();
-            ctx
-        })
+    glib::MainContext::thread_default().unwrap_or_else(|| {
+        let ctx = glib::MainContext::new();
+        ctx.push_thread_default();
+        ctx
+    })
 }
-
diff --git a/niepce-main/src/libraryclient/mod.rs b/niepce-main/src/libraryclient/mod.rs
index ee35477..1016088 100644
--- a/niepce-main/src/libraryclient/mod.rs
+++ b/niepce-main/src/libraryclient/mod.rs
@@ -44,7 +44,10 @@ pub struct LibraryClientWrapper {
 }
 
 impl LibraryClientWrapper {
-    pub fn new(dir: PathBuf, sender: async_channel::Sender<LibNotification>) -> LibraryClientWrapper {
+    pub fn new(
+        dir: PathBuf,
+        sender: async_channel::Sender<LibNotification>,
+    ) -> LibraryClientWrapper {
         LibraryClientWrapper {
             client: Arc::new(LibraryClient::new(dir, sender)),
         }
@@ -183,9 +186,7 @@ pub unsafe extern "C" fn lcchannel_new(
         }
     };
     glib::MainContext::default().spawn_local(event_handler);
-    Box::into_raw(Box::new(PortableChannel::<LibNotification>(
-        sender,
-    )))
+    Box::into_raw(Box::new(PortableChannel::<LibNotification>(sender)))
 }
 
 #[no_mangle]


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]