@@ -22,21 +22,32 @@ 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 )
31
38
. with_on_upgrade_needed (| event , db | {
39
+ // Convert versions from floats to integers to allow using them in match expressions
40
+ let old_version = event . old_version () as u64 ;
41
+ let new_version = event . new_version (). map (| v | v as u64 );
42
+
32
43
match (event . old_version (), event . new_version ()) {
33
- (0.0 , Some (1.0 )) => {
44
+ (0 , Some (1 )) => {
34
45
db . create_object_store (" my_store" )
35
46
. with_auto_increment (true )
36
47
. build ()? ;
37
48
}
38
- (prev , Some (2.0 )) => {
39
- if prev == 1.0 {
49
+ (prev , Some (2 )) => {
50
+ if prev == 1 {
40
51
let _ = db . delete_object_store (" my_store" );
41
52
}
42
53
@@ -59,28 +70,47 @@ async fn main() -> indexed_db_futures::OpenDbResult<()> {
59
70
60
71
store
61
72
. put (" a primitive value that doesn't need serde" )
73
+ . with_key (" my_key" )
62
74
. await ? ;
63
75
64
- // awaiting individual requests is optional - they still go out
65
- store . put (MySerdeType (10 , " foos" . into ())). serde ()? ;
76
+ // Awaiting individual requests is optional - they still go out
77
+ store
78
+ . put (MySerdeType (10 , " foos" . into ()))
79
+ . with_key (" my_serde_key" )
80
+ . with_key_type :: <String >() // `serde` keys must be deserialisable; String is, but the &str above isn't
81
+ . serde ()? ;
66
82
67
83
// Unlike JS, transactions ROLL BACK INSTEAD OF COMMITTING BY DEFAULT
68
84
transaction . commit (). await ? ;
69
85
70
86
// Read some data
71
87
let transaction = db . transaction (" my_other_store" ). build ()? ;
72
88
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 ),
89
+
90
+ // `None` is returned if the cursor is empty
91
+ if let Some (mut cursor ) = store . open_cursor (). await ? {
92
+ // Use a limited loop in case we made a mistake and result in an infinite loop
93
+ for _ in 0 .. 5 {
94
+ // We inserted a serde record and a primitive one so we need to deserialise as an enum that supports both
95
+ match cursor . next_record_ser :: <ObjectOrString >(). await {
96
+ Ok (Some (record )) => match record {
97
+ ObjectOrString :: Object (serde_record ) => {
98
+ assert_eq! (serde_record . 0 , 10 );
99
+ assert_eq! (serde_record . 1 , " foos" );
100
+ }
101
+ ObjectOrString :: String (string_record ) => {
102
+ assert_eq! (
103
+ string_record . as_str (),
104
+ " a primitive value that doesn't need serde"
105
+ );
106
+ }
107
+ },
108
+ Err (e ) => return Err (e . into ()),
109
+ Ok (None ) => return Ok (()), // reached cursor end
110
+ }
83
111
}
112
+
113
+ panic! (" Got an infinite loop!" );
84
114
}
85
115
86
116
Ok (())
0 commit comments