use crate::{
transaction::transaction_request,
utils::{
array_to_vec, make_key_range, map_count_err, map_count_res, map_get_err, none_if_undefined,
},
CursorBuilder,
};
use futures_util::future::{Either, FutureExt};
use std::{future::Future, marker::PhantomData, ops::RangeBounds};
use web_sys::{wasm_bindgen::JsValue, IdbIndex};
#[cfg(doc)]
use crate::Cursor;
pub struct Index<Err> {
sys: IdbIndex,
_phantom: PhantomData<Err>,
}
impl<Err> Index<Err> {
pub(crate) fn from_sys(sys: IdbIndex) -> Index<Err> {
Index {
sys,
_phantom: PhantomData,
}
}
pub fn contains(&self, key: &JsValue) -> impl Future<Output = crate::Result<bool, Err>> {
match self.sys.count_with_key(key) {
Ok(count_req) => Either::Right(
transaction_request(count_req)
.map(|res| res.map_err(map_count_err).map(|n| map_count_res(n) != 0)),
),
Err(e) => Either::Left(std::future::ready(Err(map_count_err(e)))),
}
}
pub fn count_in(
&self,
range: impl RangeBounds<JsValue>,
) -> impl Future<Output = crate::Result<usize, Err>> {
let range = match make_key_range(range) {
Ok(range) => range,
Err(e) => return Either::Left(std::future::ready(Err(e))),
};
match self.sys.count_with_key(&range) {
Ok(count_req) => Either::Right(
transaction_request(count_req)
.map(|res| res.map_err(map_count_err).map(map_count_res)),
),
Err(e) => Either::Left(std::future::ready(Err(map_count_err(e)))),
}
}
pub fn get(&self, key: &JsValue) -> impl Future<Output = crate::Result<Option<JsValue>, Err>> {
match self.sys.get(key) {
Ok(get_req) => Either::Right(
transaction_request(get_req)
.map(|res| res.map_err(map_get_err).map(none_if_undefined)),
),
Err(err) => Either::Left(std::future::ready(Err(map_get_err(err)))),
}
}
pub fn get_first_in(
&self,
range: impl RangeBounds<JsValue>,
) -> impl Future<Output = crate::Result<Option<JsValue>, Err>> {
let range = match make_key_range(range) {
Ok(range) => range,
Err(e) => return Either::Left(std::future::ready(Err(e))),
};
match self.sys.get(&range) {
Ok(get_req) => Either::Right(
transaction_request(get_req)
.map(|res| res.map_err(map_get_err).map(none_if_undefined)),
),
Err(e) => Either::Left(std::future::ready(Err(map_get_err(e)))),
}
}
pub fn get_all(
&self,
limit: Option<u32>,
) -> impl Future<Output = crate::Result<Vec<JsValue>, Err>> {
let get_req = match limit {
None => self.sys.get_all(),
Some(limit) => self
.sys
.get_all_with_key_and_limit(&JsValue::UNDEFINED, limit),
};
match get_req {
Ok(get_req) => Either::Right(
transaction_request(get_req).map(|res| res.map_err(map_get_err).map(array_to_vec)),
),
Err(err) => Either::Left(std::future::ready(Err(map_get_err(err)))),
}
}
pub fn get_all_in(
&self,
range: impl RangeBounds<JsValue>,
limit: Option<u32>,
) -> impl Future<Output = crate::Result<Vec<JsValue>, Err>> {
let range = match make_key_range(range) {
Ok(range) => range,
Err(e) => return Either::Left(std::future::ready(Err(e))),
};
let get_req = match limit {
None => self.sys.get_all_with_key(&range),
Some(limit) => self.sys.get_all_with_key_and_limit(&range, limit),
};
match get_req {
Ok(get_req) => Either::Right(
transaction_request(get_req).map(|res| res.map_err(map_get_err).map(array_to_vec)),
),
Err(err) => Either::Left(std::future::ready(Err(map_get_err(err)))),
}
}
pub fn get_first_key_in(
&self,
range: impl RangeBounds<JsValue>,
) -> impl Future<Output = crate::Result<Option<JsValue>, Err>> {
let range = match make_key_range(range) {
Ok(range) => range,
Err(e) => return Either::Left(std::future::ready(Err(e))),
};
match self.sys.get_key(&range) {
Ok(get_req) => Either::Right(
transaction_request(get_req)
.map(|res| res.map_err(map_get_err).map(none_if_undefined)),
),
Err(err) => Either::Left(std::future::ready(Err(map_get_err(err)))),
}
}
pub fn get_all_keys(
&self,
limit: Option<u32>,
) -> impl Future<Output = crate::Result<Vec<JsValue>, Err>> {
let get_req = match limit {
None => self.sys.get_all_keys(),
Some(limit) => self
.sys
.get_all_keys_with_key_and_limit(&JsValue::UNDEFINED, limit),
};
match get_req {
Ok(get_req) => Either::Right(
transaction_request(get_req).map(|res| res.map_err(map_get_err).map(array_to_vec)),
),
Err(err) => Either::Left(std::future::ready(Err(map_get_err(err)))),
}
}
pub fn get_all_keys_in(
&self,
range: impl RangeBounds<JsValue>,
limit: Option<u32>,
) -> impl Future<Output = crate::Result<Vec<JsValue>, Err>> {
let range = match make_key_range(range) {
Ok(range) => range,
Err(e) => return Either::Left(std::future::ready(Err(e))),
};
let get_req = match limit {
None => self.sys.get_all_keys_with_key(&range),
Some(limit) => self.sys.get_all_keys_with_key_and_limit(&range, limit),
};
match get_req {
Ok(get_req) => Either::Right(
transaction_request(get_req).map(|res| res.map_err(map_get_err).map(array_to_vec)),
),
Err(err) => Either::Left(std::future::ready(Err(map_get_err(err)))),
}
}
pub fn cursor(&self) -> CursorBuilder<Err> {
CursorBuilder::from_index(self.sys.clone())
}
}