Skip to content

Commit 0aec463

Browse files
touilleManEkleog
andauthored
Use async closure (stabilized in Rust 1.85) (#6)
Co-authored-by: Léo Gaspard <[email protected]>
1 parent 8a7dc6f commit 0aec463

File tree

7 files changed

+45
-50
lines changed

7 files changed

+45
-50
lines changed

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ license = "MIT OR Apache-2.0"
99
repository = "https://github.com/Ekleog/indexed-db"
1010
keywords = ["wasm", "indexeddb", "async", "web", "webassembly"]
1111
categories = ["asynchronous", "database", "wasm", "web-programming"]
12+
rust-version = "1.85"
1213

1314
[dependencies]
1415
futures-channel = "0.3.30"

README.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ async fn example() -> anyhow::Result<()> {
3333

3434
// Open the database, creating it if needed
3535
let db = factory
36-
.open("database", 1, |evt| async move {
36+
.open("database", 1, async move |evt| {
3737
let db = evt.database();
3838
let store = db.build_object_store("store").auto_increment().create()?;
3939

@@ -48,7 +48,7 @@ async fn example() -> anyhow::Result<()> {
4848
// In a transaction, add two records
4949
db.transaction(&["store"])
5050
.rw()
51-
.run(|t| async move {
51+
.run(async move |t| {
5252
let store = t.object_store("store")?;
5353
store.add(&JsString::from("bar")).await?;
5454
store.add(&JsString::from("baz")).await?;
@@ -58,7 +58,7 @@ async fn example() -> anyhow::Result<()> {
5858

5959
// In another transaction, read the first record
6060
db.transaction(&["store"])
61-
.run(|t| async move {
61+
.run(async move |t| {
6262
let data = t.object_store("store")?.get_all(Some(1)).await?;
6363
if data.len() != 1 {
6464
Err(std::io::Error::new(
@@ -73,7 +73,7 @@ async fn example() -> anyhow::Result<()> {
7373
// If we return `Err` (or panic) from a transaction, then it will abort
7474
db.transaction(&["store"])
7575
.rw()
76-
.run(|t| async move {
76+
.run(async move |t| {
7777
let store = t.object_store("store")?;
7878
store.add(&JsString::from("quux")).await?;
7979
if store.count().await? > 3 {
@@ -90,7 +90,7 @@ async fn example() -> anyhow::Result<()> {
9090

9191
// And no write will have happened
9292
db.transaction(&["store"])
93-
.run(|t| async move {
93+
.run(async move |t| {
9494
let num_items = t.object_store("store")?.count().await?;
9595
assert_eq!(num_items, 3);
9696
Ok(())
@@ -99,7 +99,7 @@ async fn example() -> anyhow::Result<()> {
9999

100100
// More complex example: using cursors to iterate over a store
101101
db.transaction(&["store"])
102-
.run(|t| async move {
102+
.run(async move |t| {
103103
let mut all_items = Vec::new();
104104
let mut cursor = t.object_store("store")?.cursor().open().await?;
105105
while let Some(value) = cursor.value() {

examples/basic.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ async fn example() -> anyhow::Result<()> {
1010

1111
// Open the database, creating it if needed
1212
let db = factory
13-
.open("database", 1, |evt| async move {
13+
.open("database", 1, async move |evt| {
1414
let db = evt.database();
1515
let store = db.build_object_store("store").auto_increment().create()?;
1616

@@ -25,7 +25,7 @@ async fn example() -> anyhow::Result<()> {
2525
// In a transaction, add two records
2626
db.transaction(&["store"])
2727
.rw()
28-
.run(|t| async move {
28+
.run(async move |t| {
2929
let store = t.object_store("store")?;
3030
store.add(&JsString::from("bar")).await?;
3131
store.add(&JsString::from("baz")).await?;
@@ -35,7 +35,7 @@ async fn example() -> anyhow::Result<()> {
3535

3636
// In another transaction, read the first record
3737
db.transaction(&["store"])
38-
.run(|t| async move {
38+
.run(async move |t| {
3939
let data = t.object_store("store")?.get_all(Some(1)).await?;
4040
if data.len() != 1 {
4141
Err(std::io::Error::new(
@@ -50,7 +50,7 @@ async fn example() -> anyhow::Result<()> {
5050
// If we return `Err` (or panic) from a transaction, then it will abort
5151
db.transaction(&["store"])
5252
.rw()
53-
.run(|t| async move {
53+
.run(async move |t| {
5454
let store = t.object_store("store")?;
5555
store.add(&JsString::from("quux")).await?;
5656
if store.count().await? > 3 {
@@ -67,7 +67,7 @@ async fn example() -> anyhow::Result<()> {
6767

6868
// And no write will have happened
6969
db.transaction(&["store"])
70-
.run(|t| async move {
70+
.run(async move |t| {
7171
let num_items = t.object_store("store")?.count().await?;
7272
assert_eq!(num_items, 3);
7373
Ok(())
@@ -76,7 +76,7 @@ async fn example() -> anyhow::Result<()> {
7676

7777
// More complex example: using cursors to iterate over a store
7878
db.transaction(&["store"])
79-
.run(|t| async move {
79+
.run(async move |t| {
8080
let mut all_items = Vec::new();
8181
let mut cursor = t.object_store("store")?.cursor().open().await?;
8282
while let Some(value) = cursor.value() {

src/factory.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use futures_util::{
44
future::{self, Either},
55
pin_mut, FutureExt,
66
};
7-
use std::{future::Future, marker::PhantomData};
7+
use std::marker::PhantomData;
88
use web_sys::{
99
js_sys::{self, Function},
1010
wasm_bindgen::{closure::Closure, JsCast, JsValue},
@@ -97,16 +97,12 @@ impl<Err: 'static> Factory<Err> {
9797
///
9898
/// This internally uses [`IDBFactory::open`](https://developer.mozilla.org/en-US/docs/Web/API/IDBFactory/open)
9999
/// as well as the methods from [`IDBOpenDBRequest`](https://developer.mozilla.org/en-US/docs/Web/API/IDBOpenDBRequest)
100-
pub async fn open<Fun, RetFut>(
100+
pub async fn open(
101101
&self,
102102
name: &str,
103103
version: u32,
104-
on_upgrade_needed: Fun,
105-
) -> crate::Result<Database<Err>, Err>
106-
where
107-
Fun: 'static + FnOnce(VersionChangeEvent<Err>) -> RetFut,
108-
RetFut: 'static + Future<Output = crate::Result<(), Err>>,
109-
{
104+
on_upgrade_needed: impl 'static + AsyncFnOnce(VersionChangeEvent<Err>) -> crate::Result<(), Err>,
105+
) -> crate::Result<Database<Err>, Err> {
110106
if version == 0 {
111107
return Err(crate::Error::VersionMustNotBeZero);
112108
}
@@ -117,7 +113,7 @@ impl<Err: 'static> Factory<Err> {
117113
.map_err(crate::Error::from_js_value)?;
118114

119115
let (upgrade_tx, upgrade_rx) = oneshot::channel();
120-
let on_upgrade_needed = Closure::once(|evt: IdbVersionChangeEvent| {
116+
let on_upgrade_needed = Closure::once(move |evt: IdbVersionChangeEvent| {
121117
let evt = VersionChangeEvent::from_sys(evt);
122118
let transaction = evt.transaction().as_sys().clone();
123119
let fut = {

src/transaction.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::{
44
};
55
use futures_channel::oneshot;
66
use futures_util::future::{self, Either};
7-
use std::{future::Future, marker::PhantomData};
7+
use std::marker::PhantomData;
88
use web_sys::{
99
wasm_bindgen::{JsCast, JsValue},
1010
IdbDatabase, IdbRequest, IdbTransaction, IdbTransactionMode,
@@ -98,10 +98,11 @@ impl<Err> TransactionBuilder<Err> {
9898
// - If the `Closure` from `transaction_request` has already been dropped, then the callback
9999
// will panic. Most likely this will lead to the transaction aborting, but this is an
100100
// untested and unsupported code path.
101-
pub async fn run<Fun, RetFut, Ret>(self, transaction: Fun) -> crate::Result<Ret, Err>
101+
pub async fn run<Ret>(
102+
self,
103+
transaction: impl 'static + AsyncFnOnce(Transaction<Err>) -> crate::Result<Ret, Err>,
104+
) -> crate::Result<Ret, Err>
102105
where
103-
Fun: 'static + FnOnce(Transaction<Err>) -> RetFut,
104-
RetFut: 'static + Future<Output = crate::Result<Ret, Err>>,
105106
Ret: 'static,
106107
Err: 'static,
107108
{

tests/common/mod.rs

+19-22
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,12 @@ async fn smoke_test() {
3030

3131
// Factory::open
3232
factory
33-
.open("foo", 0, |_| async move { Ok(()) })
33+
.open("foo", 0, async move |_| Ok(()))
3434
.await
3535
.unwrap_err();
36+
factory.open("foo", 2, async move |_| Ok(())).await.unwrap();
3637
factory
37-
.open("foo", 2, |_| async move { Ok(()) })
38-
.await
39-
.unwrap();
40-
factory
41-
.open("foo", 1, |_| async move { Ok(()) })
38+
.open("foo", 1, async move |_| Ok(()))
4239
.await
4340
.unwrap_err();
4441

@@ -49,7 +46,7 @@ async fn smoke_test() {
4946

5047
// Database::build_object_store
5148
let db = factory
52-
.open("bar", 1, |evt| async move {
49+
.open("bar", 1, async move |evt| {
5350
let db = evt.database();
5451
db.build_object_store("objects").create()?;
5552
db.build_object_store("things")
@@ -67,7 +64,7 @@ async fn smoke_test() {
6764
db.close();
6865

6966
let db = factory
70-
.open("bar", 2, |evt| async move {
67+
.open("bar", 2, async move |evt| {
7168
let db = evt.database();
7269
db.delete_object_store("things")?;
7370
Ok(())
@@ -81,7 +78,7 @@ async fn smoke_test() {
8178
// Transaction
8279
db.transaction(&["objects", "stuffs"])
8380
.rw()
84-
.run(|t| async move {
81+
.run(async move |t| {
8582
let objects = t.object_store("objects")?;
8683
let stuffs = t.object_store("stuffs")?;
8784

@@ -105,7 +102,7 @@ async fn smoke_test() {
105102
.unwrap();
106103
db.transaction(&["objects", "stuffs"])
107104
.rw()
108-
.run(|t| async move {
105+
.run(async move |t| {
109106
let objects = t.object_store("objects")?;
110107
let stuffs = t.object_store("stuffs")?;
111108

@@ -135,7 +132,7 @@ async fn smoke_test() {
135132
.unwrap();
136133
db.transaction(&["objects"])
137134
.rw()
138-
.run(|t| async move {
135+
.run(async move |t| {
139136
let objects = t.object_store("objects")?;
140137

141138
// Get
@@ -171,7 +168,7 @@ async fn smoke_test() {
171168
.unwrap();
172169
db.transaction(&["stuffs"])
173170
.rw()
174-
.run(|t| async move {
171+
.run(async move |t| {
175172
let stuffs = t.object_store("stuffs")?;
176173

177174
// Index
@@ -227,7 +224,7 @@ async fn auto_rollback() {
227224
let factory = Factory::get().unwrap();
228225

229226
let db = factory
230-
.open("baz", 1, |evt| async move {
227+
.open("baz", 1, async move |evt| {
231228
let db = evt.database();
232229
db.build_object_store("data").auto_increment().create()?;
233230
Ok(())
@@ -237,7 +234,7 @@ async fn auto_rollback() {
237234

238235
db.transaction(&["data"])
239236
.rw()
240-
.run(|t| async move {
237+
.run(async move |t| {
241238
t.object_store("data")?.add(&JsString::from("foo")).await?;
242239
t.object_store("data")?.add(&JsString::from("bar")).await?;
243240
if true {
@@ -251,7 +248,7 @@ async fn auto_rollback() {
251248

252249
db.transaction(&["data"])
253250
.rw()
254-
.run(|t| async move {
251+
.run(async move |t| {
255252
t.object_store("data")?.add(&JsString::from("baz")).await?;
256253
Ok::<_, indexed_db::Error<()>>(())
257254
})
@@ -260,7 +257,7 @@ async fn auto_rollback() {
260257

261258
db.transaction(&["data"])
262259
.rw()
263-
.run(|t| async move {
260+
.run(async move |t| {
264261
assert_eq!(t.object_store("data")?.count().await?, 1);
265262
Ok::<_, indexed_db::Error<()>>(())
266263
})
@@ -273,7 +270,7 @@ async fn duplicate_insert_returns_proper_error_and_does_not_abort() {
273270
let factory = Factory::<()>::get().unwrap();
274271

275272
let db = factory
276-
.open("quux", 1, |evt| async move {
273+
.open("quux", 1, async move |evt| {
277274
let db = evt.database();
278275
db.build_object_store("data").create()?;
279276
Ok(())
@@ -283,7 +280,7 @@ async fn duplicate_insert_returns_proper_error_and_does_not_abort() {
283280

284281
db.transaction(&["data"])
285282
.rw()
286-
.run(|t| async move {
283+
.run(async move |t| {
287284
t.object_store("data")?
288285
.add_kv(&JsString::from("key1"), &JsString::from("foo"))
289286
.await?;
@@ -294,7 +291,7 @@ async fn duplicate_insert_returns_proper_error_and_does_not_abort() {
294291

295292
db.transaction(&["data"])
296293
.rw()
297-
.run(|t| async move {
294+
.run(async move |t| {
298295
assert!(matches!(
299296
t.object_store("data")?
300297
.add_kv(&JsString::from("key1"), &JsString::from("bar"))
@@ -312,7 +309,7 @@ async fn duplicate_insert_returns_proper_error_and_does_not_abort() {
312309

313310
db.transaction(&["data"])
314311
.rw()
315-
.run(|t| async move {
312+
.run(async move |t| {
316313
assert_eq!(
317314
t.object_store("data")?.get_all_keys(None).await?,
318315
vec![JsValue::from("key1"), JsValue::from("key2")]
@@ -332,7 +329,7 @@ async fn typed_array_keys() {
332329
let factory = Factory::<()>::get().unwrap();
333330

334331
let db = factory
335-
.open("db12", 1, |evt| async move {
332+
.open("db12", 1, async move |evt| {
336333
let db = evt.database();
337334
db.build_object_store("data").create()?;
338335
Ok(())
@@ -342,7 +339,7 @@ async fn typed_array_keys() {
342339

343340
db.transaction(&["data"])
344341
.rw()
345-
.run(|t| async move {
342+
.run(async move |t| {
346343
let data = t.object_store("data")?;
347344
data.add_kv(&Uint8Array::from(&b"key1"[..]), &JsString::from("foo"))
348345
.await?;

tests/common_panic/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ async fn other_awaits_panic() {
1717
let factory = Factory::<anyhow::Error>::get().unwrap();
1818

1919
let db = factory
20-
.open("baz", 1, |evt| async move {
20+
.open("baz", 1, async move |evt| {
2121
let db = evt.database();
2222
db.build_object_store("data").auto_increment().create()?;
2323
Ok(())
@@ -29,7 +29,7 @@ async fn other_awaits_panic() {
2929

3030
db.transaction(&["data"])
3131
.rw()
32-
.run(|t| async move {
32+
.run(async move |t| {
3333
t.object_store("data")?.add(&JsString::from("foo")).await?;
3434
rx.await.context("awaiting for something external")?;
3535
t.object_store("data")?.add(&JsString::from("bar")).await?;
@@ -52,7 +52,7 @@ async fn await_in_versionchange_panics() {
5252
let (tx, rx) = futures_channel::oneshot::channel();
5353

5454
factory
55-
.open("baz", 1, |evt| async move {
55+
.open("baz", 1, async move |evt| {
5656
let db = evt.database();
5757
db.build_object_store("data").auto_increment().create()?;
5858
rx.await.context("awaiting for something external")?;

0 commit comments

Comments
 (0)