@@ -22,21 +22,32 @@ use indexed_db_futures::database::Database;
2222use indexed_db_futures :: prelude :: * ;
2323use indexed_db_futures :: transaction :: TransactionMode ;
2424
25- #[derive(serde :: Serialize , serde :: Deserialize )]
25+ #[derive(Serialize , Deserialize )]
2626struct MySerdeType (u8 , String );
2727
28+ #[derive(Deserialize )]
29+ #[serde(untagged)]
30+ enum ObjectOrString {
31+ Object (MySerdeType ),
32+ String (String ),
33+ }
34+
2835async fn main () -> indexed_db_futures :: OpenDbResult <()> {
2936 let db = Database :: open (" my_db" )
3037 . with_version (2u8 )
3138 . 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+
3243 match (event . old_version (), event . new_version ()) {
33- (0.0 , Some (1.0 )) => {
44+ (0 , Some (1 )) => {
3445 db . create_object_store (" my_store" )
3546 . with_auto_increment (true )
3647 . build ()? ;
3748 }
38- (prev , Some (2.0 )) => {
39- if prev == 1.0 {
49+ (prev , Some (2 )) => {
50+ if prev == 1 {
4051 let _ = db . delete_object_store (" my_store" );
4152 }
4253
@@ -59,28 +70,47 @@ async fn main() -> indexed_db_futures::OpenDbResult<()> {
5970
6071 store
6172 . put (" a primitive value that doesn't need serde" )
73+ . with_key (" my_key" )
6274 . await ? ;
6375
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 ()? ;
6682
6783 // Unlike JS, transactions ROLL BACK INSTEAD OF COMMITTING BY DEFAULT
6884 transaction . commit (). await ? ;
6985
7086 // Read some data
7187 let transaction = db . transaction (" my_other_store" ). build ()? ;
7288 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+ }
83111 }
112+
113+ panic! (" Got an infinite loop!" );
84114 }
85115
86116 Ok (())
0 commit comments