@@ -22,9 +22,16 @@ use indexed_db_futures::database::Database;
22
22
use indexed_db_futures :: prelude :: * ;
23
23
use indexed_db_futures :: transaction :: TransactionMode ;
24
24
25
- #[derive(serde :: Serialize , serde :: Deserialize )]
25
+ #[derive(Serialize , Deserialize )]
26
26
struct MySerdeType (u8 , String );
27
27
28
+ #[derive(Deserialize )]
29
+ #[serde(untagged)]
30
+ enum ObjectOrString {
31
+ Object (MySerdeType ),
32
+ String (String ),
33
+ }
34
+
28
35
async fn main () -> indexed_db_futures :: OpenDbResult <()> {
29
36
let db = Database :: open (" my_db" )
30
37
. with_version (2u8 )
@@ -59,28 +66,47 @@ async fn main() -> indexed_db_futures::OpenDbResult<()> {
59
66
60
67
store
61
68
. put (" a primitive value that doesn't need serde" )
69
+ . with_key (" my_key" )
62
70
. await ? ;
63
71
64
- // awaiting individual requests is optional - they still go out
65
- store . put (MySerdeType (10 , " foos" . into ())). serde ()? ;
72
+ // Awaiting individual requests is optional - they still go out
73
+ store
74
+ . put (MySerdeType (10 , " foos" . into ()))
75
+ . with_key (" my_serde_key" )
76
+ . with_key_type :: <String >() // `serde` keys must be deserialisable; String is, but the &str above isn't
77
+ . serde ()? ;
66
78
67
79
// Unlike JS, transactions ROLL BACK INSTEAD OF COMMITTING BY DEFAULT
68
80
transaction . commit (). await ? ;
69
81
70
82
// Read some data
71
83
let transaction = db . transaction (" my_other_store" ). build ()? ;
72
84
let store = transaction . object_store (" my_other_store" )? ;
73
- let Some (mut cursor ) = store . open_cursor (). await ? else {
74
- // `None` is returned if the cursor is empty
75
- return Ok (());
76
- };
77
-
78
- loop {
79
- match cursor . next_record_ser :: <MySerdeType >(). await {
80
- Ok (Some (record )) => handle_record (record ),
81
- Ok (None ) => break ,
82
- Err (e ) => handle_error (e ),
85
+
86
+ // `None` is returned if the cursor is empty
87
+ if let Some (mut cursor ) = store . open_cursor (). await ? {
88
+ // Use a limited loop in case we made a mistake and result in an infinite loop
89
+ for _ in 0 .. 5 {
90
+ // We inserted a serde record and a primitive one so we need to deserialise as an enum that supports both
91
+ match cursor . next_record_ser :: <ObjectOrString >(). await {
92
+ Ok (Some (record )) => match record {
93
+ ObjectOrString :: Object (serde_record ) => {
94
+ assert_eq! (serde_record . 0 , 10 );
95
+ assert_eq! (serde_record . 1 , " foos" );
96
+ }
97
+ ObjectOrString :: String (string_record ) => {
98
+ assert_eq! (
99
+ string_record . as_str (),
100
+ " a primitive value that doesn't need serde"
101
+ );
102
+ }
103
+ },
104
+ Err (e ) => return Err (e . into ()),
105
+ Ok (None ) => return Ok (()), // reached cursor end
106
+ }
83
107
}
108
+
109
+ panic! (" Got an infinite loop!" );
84
110
}
85
111
86
112
Ok (())
0 commit comments