1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
use js_sys::Object;
use wasm_bindgen::{prelude::Closure, JsCast, JsValue};
use web_sys::{DomException, Event, EventTarget, IdbOpenDbRequest, IdbVersionChangeEvent};
use crate::{Database, Error, Request, RequestReadyState, Transaction, VersionChangeEvent};
#[derive(Debug)]
pub struct DatabaseRequest {
inner: IdbOpenDbRequest,
success_callback: Option<Closure<dyn FnMut(Event)>>,
error_callback: Option<Closure<dyn FnMut(Event)>>,
blocked_callback: Option<Closure<dyn FnMut(IdbVersionChangeEvent)>>,
upgrade_needed_callback: Option<Closure<dyn FnMut(IdbVersionChangeEvent)>>,
}
impl DatabaseRequest {
pub fn database(&self) -> Result<Database, Error> {
self.result().map(TryInto::try_into)?
}
pub fn on_blocked<F>(&mut self, callback: F)
where
F: FnOnce(VersionChangeEvent) + 'static,
{
let f = move |event: IdbVersionChangeEvent| {
let event = VersionChangeEvent::from(event);
callback(event);
};
let closure = Closure::once(f);
self.inner
.set_onblocked(Some(closure.as_ref().unchecked_ref()));
self.blocked_callback = Some(closure);
}
pub fn on_upgrade_needed<F>(&mut self, callback: F)
where
F: FnOnce(VersionChangeEvent) + 'static,
{
let f = move |event: IdbVersionChangeEvent| {
let event = VersionChangeEvent::from(event);
callback(event);
};
let closure = Closure::once(f);
self.inner
.set_onupgradeneeded(Some(closure.as_ref().unchecked_ref()));
self.upgrade_needed_callback = Some(closure);
}
}
impl Request for DatabaseRequest {
fn result(&self) -> Result<JsValue, Error> {
self.inner.result().map_err(Error::RequestResultNotFound)
}
fn error(&self) -> Result<Option<DomException>, Error> {
self.inner.error().map_err(Error::RequestErrorNotFound)
}
fn source(&self) -> Result<Object, Error> {
self.inner.source().ok_or(Error::RequestSourceNotFound)
}
fn transaction(&self) -> Option<Transaction> {
self.inner.transaction().map(Into::into)
}
fn ready_state(&self) -> Result<RequestReadyState, Error> {
self.inner.ready_state().try_into()
}
fn on_success<F>(&mut self, callback: F)
where
F: FnOnce(Event) + 'static,
{
let closure = Closure::once(callback);
self.inner
.set_onsuccess(Some(closure.as_ref().unchecked_ref()));
self.success_callback = Some(closure);
}
fn on_error<F>(&mut self, callback: F)
where
F: FnOnce(Event) + 'static,
{
let closure = Closure::once(callback);
self.inner
.set_onerror(Some(closure.as_ref().unchecked_ref()));
self.error_callback = Some(closure);
}
}
impl TryFrom<EventTarget> for DatabaseRequest {
type Error = Error;
fn try_from(target: EventTarget) -> Result<Self, Self::Error> {
let target: JsValue = target.into();
target
.dyn_into::<IdbOpenDbRequest>()
.map(Into::into)
.map_err(|value| Error::UnexpectedJsType("IdbOpenDbRequest", value))
}
}
impl From<IdbOpenDbRequest> for DatabaseRequest {
fn from(inner: IdbOpenDbRequest) -> Self {
Self {
inner,
success_callback: None,
error_callback: None,
blocked_callback: None,
upgrade_needed_callback: None,
}
}
}
impl From<DatabaseRequest> for IdbOpenDbRequest {
fn from(request: DatabaseRequest) -> Self {
request.inner
}
}
impl TryFrom<JsValue> for DatabaseRequest {
type Error = Error;
fn try_from(value: JsValue) -> Result<Self, Self::Error> {
value
.dyn_into::<IdbOpenDbRequest>()
.map(Into::into)
.map_err(|value| Error::UnexpectedJsType("IdbOpenDbRequest", value))
}
}
impl From<DatabaseRequest> for JsValue {
fn from(value: DatabaseRequest) -> Self {
value.inner.into()
}
}