diff --git a/Cargo.toml b/Cargo.toml index 4f890de..aab66ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ license = "MIT OR Apache-2.0" repository = "https://github.com/Ekleog/indexed-db" keywords = ["wasm", "indexeddb", "async", "web", "webassembly"] categories = ["asynchronous", "database", "wasm", "web-programming"] +rust-version = "1.85" [dependencies] futures-channel = "0.3.30" diff --git a/README.md b/README.md index 6da357a..16e1e30 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ async fn example() -> anyhow::Result<()> { // Open the database, creating it if needed let db = factory - .open("database", 1, |evt| async move { + .open("database", 1, async move |evt| { let db = evt.database(); let store = db.build_object_store("store").auto_increment().create()?; @@ -48,7 +48,7 @@ async fn example() -> anyhow::Result<()> { // In a transaction, add two records db.transaction(&["store"]) .rw() - .run(|t| async move { + .run(async move |t| { let store = t.object_store("store")?; store.add(&JsString::from("bar")).await?; store.add(&JsString::from("baz")).await?; @@ -58,7 +58,7 @@ async fn example() -> anyhow::Result<()> { // In another transaction, read the first record db.transaction(&["store"]) - .run(|t| async move { + .run(async move |t| { let data = t.object_store("store")?.get_all(Some(1)).await?; if data.len() != 1 { Err(std::io::Error::new( @@ -73,7 +73,7 @@ async fn example() -> anyhow::Result<()> { // If we return `Err` (or panic) from a transaction, then it will abort db.transaction(&["store"]) .rw() - .run(|t| async move { + .run(async move |t| { let store = t.object_store("store")?; store.add(&JsString::from("quux")).await?; if store.count().await? > 3 { @@ -90,7 +90,7 @@ async fn example() -> anyhow::Result<()> { // And no write will have happened db.transaction(&["store"]) - .run(|t| async move { + .run(async move |t| { let num_items = t.object_store("store")?.count().await?; assert_eq!(num_items, 3); Ok(()) @@ -99,7 +99,7 @@ async fn example() -> anyhow::Result<()> { // More complex example: using cursors to iterate over a store db.transaction(&["store"]) - .run(|t| async move { + .run(async move |t| { let mut all_items = Vec::new(); let mut cursor = t.object_store("store")?.cursor().open().await?; while let Some(value) = cursor.value() { diff --git a/examples/basic.rs b/examples/basic.rs index 86142a3..928775b 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -10,7 +10,7 @@ async fn example() -> anyhow::Result<()> { // Open the database, creating it if needed let db = factory - .open("database", 1, |evt| async move { + .open("database", 1, async move |evt| { let db = evt.database(); let store = db.build_object_store("store").auto_increment().create()?; @@ -25,7 +25,7 @@ async fn example() -> anyhow::Result<()> { // In a transaction, add two records db.transaction(&["store"]) .rw() - .run(|t| async move { + .run(async move |t| { let store = t.object_store("store")?; store.add(&JsString::from("bar")).await?; store.add(&JsString::from("baz")).await?; @@ -35,7 +35,7 @@ async fn example() -> anyhow::Result<()> { // In another transaction, read the first record db.transaction(&["store"]) - .run(|t| async move { + .run(async move |t| { let data = t.object_store("store")?.get_all(Some(1)).await?; if data.len() != 1 { Err(std::io::Error::new( @@ -50,7 +50,7 @@ async fn example() -> anyhow::Result<()> { // If we return `Err` (or panic) from a transaction, then it will abort db.transaction(&["store"]) .rw() - .run(|t| async move { + .run(async move |t| { let store = t.object_store("store")?; store.add(&JsString::from("quux")).await?; if store.count().await? > 3 { @@ -67,7 +67,7 @@ async fn example() -> anyhow::Result<()> { // And no write will have happened db.transaction(&["store"]) - .run(|t| async move { + .run(async move |t| { let num_items = t.object_store("store")?.count().await?; assert_eq!(num_items, 3); Ok(()) @@ -76,7 +76,7 @@ async fn example() -> anyhow::Result<()> { // More complex example: using cursors to iterate over a store db.transaction(&["store"]) - .run(|t| async move { + .run(async move |t| { let mut all_items = Vec::new(); let mut cursor = t.object_store("store")?.cursor().open().await?; while let Some(value) = cursor.value() { diff --git a/src/factory.rs b/src/factory.rs index b5f55fc..cfcbe73 100644 --- a/src/factory.rs +++ b/src/factory.rs @@ -4,7 +4,7 @@ use futures_util::{ future::{self, Either}, pin_mut, FutureExt, }; -use std::{future::Future, marker::PhantomData}; +use std::marker::PhantomData; use web_sys::{ js_sys::{self, Function}, wasm_bindgen::{closure::Closure, JsCast, JsValue}, @@ -97,16 +97,12 @@ impl Factory { /// /// This internally uses [`IDBFactory::open`](https://developer.mozilla.org/en-US/docs/Web/API/IDBFactory/open) /// as well as the methods from [`IDBOpenDBRequest`](https://developer.mozilla.org/en-US/docs/Web/API/IDBOpenDBRequest) - pub async fn open( + pub async fn open( &self, name: &str, version: u32, - on_upgrade_needed: Fun, - ) -> crate::Result, Err> - where - Fun: 'static + FnOnce(VersionChangeEvent) -> RetFut, - RetFut: 'static + Future>, - { + on_upgrade_needed: impl 'static + AsyncFnOnce(VersionChangeEvent) -> crate::Result<(), Err>, + ) -> crate::Result, Err> { if version == 0 { return Err(crate::Error::VersionMustNotBeZero); } @@ -117,7 +113,7 @@ impl Factory { .map_err(crate::Error::from_js_value)?; let (upgrade_tx, upgrade_rx) = oneshot::channel(); - let on_upgrade_needed = Closure::once(|evt: IdbVersionChangeEvent| { + let on_upgrade_needed = Closure::once(move |evt: IdbVersionChangeEvent| { let evt = VersionChangeEvent::from_sys(evt); let transaction = evt.transaction().as_sys().clone(); let fut = { diff --git a/src/transaction.rs b/src/transaction.rs index 4780997..5a43bcd 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -4,7 +4,7 @@ use crate::{ }; use futures_channel::oneshot; use futures_util::future::{self, Either}; -use std::{future::Future, marker::PhantomData}; +use std::marker::PhantomData; use web_sys::{ wasm_bindgen::{JsCast, JsValue}, IdbDatabase, IdbRequest, IdbTransaction, IdbTransactionMode, @@ -98,10 +98,11 @@ impl TransactionBuilder { // - If the `Closure` from `transaction_request` has already been dropped, then the callback // will panic. Most likely this will lead to the transaction aborting, but this is an // untested and unsupported code path. - pub async fn run(self, transaction: Fun) -> crate::Result + pub async fn run( + self, + transaction: impl 'static + AsyncFnOnce(Transaction) -> crate::Result, + ) -> crate::Result where - Fun: 'static + FnOnce(Transaction) -> RetFut, - RetFut: 'static + Future>, Ret: 'static, Err: 'static, { diff --git a/tests/common/mod.rs b/tests/common/mod.rs index bce5646..2cc7fd6 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -30,15 +30,12 @@ async fn smoke_test() { // Factory::open factory - .open("foo", 0, |_| async move { Ok(()) }) + .open("foo", 0, async move |_| Ok(())) .await .unwrap_err(); + factory.open("foo", 2, async move |_| Ok(())).await.unwrap(); factory - .open("foo", 2, |_| async move { Ok(()) }) - .await - .unwrap(); - factory - .open("foo", 1, |_| async move { Ok(()) }) + .open("foo", 1, async move |_| Ok(())) .await .unwrap_err(); @@ -49,7 +46,7 @@ async fn smoke_test() { // Database::build_object_store let db = factory - .open("bar", 1, |evt| async move { + .open("bar", 1, async move |evt| { let db = evt.database(); db.build_object_store("objects").create()?; db.build_object_store("things") @@ -67,7 +64,7 @@ async fn smoke_test() { db.close(); let db = factory - .open("bar", 2, |evt| async move { + .open("bar", 2, async move |evt| { let db = evt.database(); db.delete_object_store("things")?; Ok(()) @@ -81,7 +78,7 @@ async fn smoke_test() { // Transaction db.transaction(&["objects", "stuffs"]) .rw() - .run(|t| async move { + .run(async move |t| { let objects = t.object_store("objects")?; let stuffs = t.object_store("stuffs")?; @@ -105,7 +102,7 @@ async fn smoke_test() { .unwrap(); db.transaction(&["objects", "stuffs"]) .rw() - .run(|t| async move { + .run(async move |t| { let objects = t.object_store("objects")?; let stuffs = t.object_store("stuffs")?; @@ -135,7 +132,7 @@ async fn smoke_test() { .unwrap(); db.transaction(&["objects"]) .rw() - .run(|t| async move { + .run(async move |t| { let objects = t.object_store("objects")?; // Get @@ -171,7 +168,7 @@ async fn smoke_test() { .unwrap(); db.transaction(&["stuffs"]) .rw() - .run(|t| async move { + .run(async move |t| { let stuffs = t.object_store("stuffs")?; // Index @@ -227,7 +224,7 @@ async fn auto_rollback() { let factory = Factory::get().unwrap(); let db = factory - .open("baz", 1, |evt| async move { + .open("baz", 1, async move |evt| { let db = evt.database(); db.build_object_store("data").auto_increment().create()?; Ok(()) @@ -237,7 +234,7 @@ async fn auto_rollback() { db.transaction(&["data"]) .rw() - .run(|t| async move { + .run(async move |t| { t.object_store("data")?.add(&JsString::from("foo")).await?; t.object_store("data")?.add(&JsString::from("bar")).await?; if true { @@ -251,7 +248,7 @@ async fn auto_rollback() { db.transaction(&["data"]) .rw() - .run(|t| async move { + .run(async move |t| { t.object_store("data")?.add(&JsString::from("baz")).await?; Ok::<_, indexed_db::Error<()>>(()) }) @@ -260,7 +257,7 @@ async fn auto_rollback() { db.transaction(&["data"]) .rw() - .run(|t| async move { + .run(async move |t| { assert_eq!(t.object_store("data")?.count().await?, 1); Ok::<_, indexed_db::Error<()>>(()) }) @@ -273,7 +270,7 @@ async fn duplicate_insert_returns_proper_error_and_does_not_abort() { let factory = Factory::<()>::get().unwrap(); let db = factory - .open("quux", 1, |evt| async move { + .open("quux", 1, async move |evt| { let db = evt.database(); db.build_object_store("data").create()?; Ok(()) @@ -283,7 +280,7 @@ async fn duplicate_insert_returns_proper_error_and_does_not_abort() { db.transaction(&["data"]) .rw() - .run(|t| async move { + .run(async move |t| { t.object_store("data")? .add_kv(&JsString::from("key1"), &JsString::from("foo")) .await?; @@ -294,7 +291,7 @@ async fn duplicate_insert_returns_proper_error_and_does_not_abort() { db.transaction(&["data"]) .rw() - .run(|t| async move { + .run(async move |t| { assert!(matches!( t.object_store("data")? .add_kv(&JsString::from("key1"), &JsString::from("bar")) @@ -312,7 +309,7 @@ async fn duplicate_insert_returns_proper_error_and_does_not_abort() { db.transaction(&["data"]) .rw() - .run(|t| async move { + .run(async move |t| { assert_eq!( t.object_store("data")?.get_all_keys(None).await?, vec![JsValue::from("key1"), JsValue::from("key2")] @@ -332,7 +329,7 @@ async fn typed_array_keys() { let factory = Factory::<()>::get().unwrap(); let db = factory - .open("db12", 1, |evt| async move { + .open("db12", 1, async move |evt| { let db = evt.database(); db.build_object_store("data").create()?; Ok(()) @@ -342,7 +339,7 @@ async fn typed_array_keys() { db.transaction(&["data"]) .rw() - .run(|t| async move { + .run(async move |t| { let data = t.object_store("data")?; data.add_kv(&Uint8Array::from(&b"key1"[..]), &JsString::from("foo")) .await?; diff --git a/tests/common_panic/mod.rs b/tests/common_panic/mod.rs index 484b3fb..6f27572 100644 --- a/tests/common_panic/mod.rs +++ b/tests/common_panic/mod.rs @@ -17,7 +17,7 @@ async fn other_awaits_panic() { let factory = Factory::::get().unwrap(); let db = factory - .open("baz", 1, |evt| async move { + .open("baz", 1, async move |evt| { let db = evt.database(); db.build_object_store("data").auto_increment().create()?; Ok(()) @@ -29,7 +29,7 @@ async fn other_awaits_panic() { db.transaction(&["data"]) .rw() - .run(|t| async move { + .run(async move |t| { t.object_store("data")?.add(&JsString::from("foo")).await?; rx.await.context("awaiting for something external")?; t.object_store("data")?.add(&JsString::from("bar")).await?; @@ -52,7 +52,7 @@ async fn await_in_versionchange_panics() { let (tx, rx) = futures_channel::oneshot::channel(); factory - .open("baz", 1, |evt| async move { + .open("baz", 1, async move |evt| { let db = evt.database(); db.build_object_store("data").auto_increment().create()?; rx.await.context("awaiting for something external")?;