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