1#![deny(missing_docs)]
15
16mod error;
17mod indexed_db;
18
19use kvdb::{DBTransaction, DBValue};
20use kvdb_memorydb::{self as in_memory, InMemory};
21use send_wrapper::SendWrapper;
22use std::io;
23
24pub use error::Error;
25pub use kvdb::KeyValueDB;
26
27use futures::prelude::*;
28
29use web_sys::IdbDatabase;
30
31pub struct Database {
33 name: String,
34 version: u32,
35 columns: u32,
36 in_memory: InMemory,
37 indexed_db: SendWrapper<IdbDatabase>,
38}
39
40parity_util_mem::malloc_size_of_is_0!(Database);
42
43impl Database {
44 pub async fn open(name: String, columns: u32) -> Result<Database, error::Error> {
47 let name_clone = name.clone();
48 let db = indexed_db::open(name.as_str(), None, columns).await?;
50
51 let db = if columns + 1 > db.columns {
57 let next_version = db.version + 1;
58 drop(db);
59 indexed_db::open(name.as_str(), Some(next_version), columns).await?
60 } else {
61 db
62 };
63 let indexed_db::IndexedDB { version, inner, .. } = db;
65 let in_memory = in_memory::create(columns);
66 for column in 0..columns {
68 let mut txn = DBTransaction::new();
69 let mut stream = indexed_db::idb_cursor(&*inner, column);
70 while let Some((key, value)) = stream.next().await {
71 txn.put_vec(column, key.as_ref(), value);
72 }
73 in_memory.write(txn).expect("writing in memory always succeeds; qed");
75 }
76 Ok(Database { name: name_clone, version, columns, in_memory, indexed_db: inner })
77 }
78
79 pub fn name(&self) -> &str {
81 self.name.as_str()
82 }
83
84 pub fn version(&self) -> u32 {
86 self.version
87 }
88}
89
90impl Drop for Database {
91 fn drop(&mut self) {
92 self.indexed_db.close();
93 }
94}
95
96impl KeyValueDB for Database {
97 fn get(&self, col: u32, key: &[u8]) -> io::Result<Option<DBValue>> {
98 self.in_memory.get(col, key)
99 }
100
101 fn get_by_prefix(&self, col: u32, prefix: &[u8]) -> Option<Box<[u8]>> {
102 self.in_memory.get_by_prefix(col, prefix)
103 }
104
105 fn write(&self, transaction: DBTransaction) -> io::Result<()> {
106 let _ = indexed_db::idb_commit_transaction(&*self.indexed_db, &transaction, self.columns);
107 self.in_memory.write(transaction)
108 }
109
110 fn iter<'a>(&'a self, col: u32) -> Box<dyn Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a> {
112 self.in_memory.iter(col)
113 }
114
115 fn iter_with_prefix<'a>(
117 &'a self,
118 col: u32,
119 prefix: &'a [u8],
120 ) -> Box<dyn Iterator<Item = (Box<[u8]>, Box<[u8]>)> + 'a> {
121 self.in_memory.iter_with_prefix(col, prefix)
122 }
123
124 fn restore(&self, _new_db: &str) -> std::io::Result<()> {
126 Err(io::Error::new(io::ErrorKind::Other, "Not supported yet"))
127 }
128}