1use crate::{
2 transaction::transaction_request,
3 utils::{
4 array_to_vec, make_key_range, map_count_err, map_count_res, map_get_err, none_if_undefined,
5 },
6 CursorBuilder,
7};
8use futures_util::future::{Either, FutureExt};
9use std::{future::Future, marker::PhantomData, ops::RangeBounds};
10use web_sys::{wasm_bindgen::JsValue, IdbIndex};
11
12#[cfg(doc)]
13use crate::Cursor;
14
15pub struct Index<Err> {
22 sys: IdbIndex,
23 _phantom: PhantomData<Err>,
24}
25
26impl<Err> Index<Err> {
27 pub(crate) fn from_sys(sys: IdbIndex) -> Index<Err> {
28 Index {
29 sys,
30 _phantom: PhantomData,
31 }
32 }
33
34 pub fn contains(&self, key: &JsValue) -> impl Future<Output = crate::Result<bool, Err>> {
38 match self.sys.count_with_key(key) {
39 Ok(count_req) => Either::Right(
40 transaction_request(count_req)
41 .map(|res| res.map_err(map_count_err).map(|n| map_count_res(n) != 0)),
42 ),
43 Err(e) => Either::Left(std::future::ready(Err(map_count_err(e)))),
44 }
45 }
46
47 pub fn count_in(
51 &self,
52 range: impl RangeBounds<JsValue>,
53 ) -> impl Future<Output = crate::Result<usize, Err>> {
54 let range = match make_key_range(range) {
55 Ok(range) => range,
56 Err(e) => return Either::Left(std::future::ready(Err(e))),
57 };
58 match self.sys.count_with_key(&range) {
59 Ok(count_req) => Either::Right(
60 transaction_request(count_req)
61 .map(|res| res.map_err(map_count_err).map(map_count_res)),
62 ),
63 Err(e) => Either::Left(std::future::ready(Err(map_count_err(e)))),
64 }
65 }
66
67 pub fn get(&self, key: &JsValue) -> impl Future<Output = crate::Result<Option<JsValue>, Err>> {
71 match self.sys.get(key) {
72 Ok(get_req) => Either::Right(
73 transaction_request(get_req)
74 .map(|res| res.map_err(map_get_err).map(none_if_undefined)),
75 ),
76 Err(err) => Either::Left(std::future::ready(Err(map_get_err(err)))),
77 }
78 }
79
80 pub fn get_first_in(
86 &self,
87 range: impl RangeBounds<JsValue>,
88 ) -> impl Future<Output = crate::Result<Option<JsValue>, Err>> {
89 let range = match make_key_range(range) {
90 Ok(range) => range,
91 Err(e) => return Either::Left(std::future::ready(Err(e))),
92 };
93 match self.sys.get(&range) {
94 Ok(get_req) => Either::Right(
95 transaction_request(get_req)
96 .map(|res| res.map_err(map_get_err).map(none_if_undefined)),
97 ),
98 Err(e) => Either::Left(std::future::ready(Err(map_get_err(e)))),
99 }
100 }
101
102 pub fn get_all(
106 &self,
107 limit: Option<u32>,
108 ) -> impl Future<Output = crate::Result<Vec<JsValue>, Err>> {
109 let get_req = match limit {
110 None => self.sys.get_all(),
111 Some(limit) => self
112 .sys
113 .get_all_with_key_and_limit(&JsValue::UNDEFINED, limit),
114 };
115 match get_req {
116 Ok(get_req) => Either::Right(
117 transaction_request(get_req).map(|res| res.map_err(map_get_err).map(array_to_vec)),
118 ),
119 Err(err) => Either::Left(std::future::ready(Err(map_get_err(err)))),
120 }
121 }
122
123 pub fn get_all_in(
128 &self,
129 range: impl RangeBounds<JsValue>,
130 limit: Option<u32>,
131 ) -> impl Future<Output = crate::Result<Vec<JsValue>, Err>> {
132 let range = match make_key_range(range) {
133 Ok(range) => range,
134 Err(e) => return Either::Left(std::future::ready(Err(e))),
135 };
136 let get_req = match limit {
137 None => self.sys.get_all_with_key(&range),
138 Some(limit) => self.sys.get_all_with_key_and_limit(&range, limit),
139 };
140 match get_req {
141 Ok(get_req) => Either::Right(
142 transaction_request(get_req).map(|res| res.map_err(map_get_err).map(array_to_vec)),
143 ),
144 Err(err) => Either::Left(std::future::ready(Err(map_get_err(err)))),
145 }
146 }
147
148 pub fn get_first_key_in(
152 &self,
153 range: impl RangeBounds<JsValue>,
154 ) -> impl Future<Output = crate::Result<Option<JsValue>, Err>> {
155 let range = match make_key_range(range) {
156 Ok(range) => range,
157 Err(e) => return Either::Left(std::future::ready(Err(e))),
158 };
159 match self.sys.get_key(&range) {
160 Ok(get_req) => Either::Right(
161 transaction_request(get_req)
162 .map(|res| res.map_err(map_get_err).map(none_if_undefined)),
163 ),
164 Err(err) => Either::Left(std::future::ready(Err(map_get_err(err)))),
165 }
166 }
167
168 pub fn get_all_keys(
172 &self,
173 limit: Option<u32>,
174 ) -> impl Future<Output = crate::Result<Vec<JsValue>, Err>> {
175 let get_req = match limit {
176 None => self.sys.get_all_keys(),
177 Some(limit) => self
178 .sys
179 .get_all_keys_with_key_and_limit(&JsValue::UNDEFINED, limit),
180 };
181 match get_req {
182 Ok(get_req) => Either::Right(
183 transaction_request(get_req).map(|res| res.map_err(map_get_err).map(array_to_vec)),
184 ),
185 Err(err) => Either::Left(std::future::ready(Err(map_get_err(err)))),
186 }
187 }
188
189 pub fn get_all_keys_in(
194 &self,
195 range: impl RangeBounds<JsValue>,
196 limit: Option<u32>,
197 ) -> impl Future<Output = crate::Result<Vec<JsValue>, Err>> {
198 let range = match make_key_range(range) {
199 Ok(range) => range,
200 Err(e) => return Either::Left(std::future::ready(Err(e))),
201 };
202 let get_req = match limit {
203 None => self.sys.get_all_keys_with_key(&range),
204 Some(limit) => self.sys.get_all_keys_with_key_and_limit(&range, limit),
205 };
206 match get_req {
207 Ok(get_req) => Either::Right(
208 transaction_request(get_req).map(|res| res.map_err(map_get_err).map(array_to_vec)),
209 ),
210 Err(err) => Either::Left(std::future::ready(Err(map_get_err(err)))),
211 }
212 }
213
214 pub fn cursor(&self) -> CursorBuilder<Err> {
216 CursorBuilder::from_index(self.sys.clone())
217 }
218}