idb/cursor/
managed_value_cursor.rs

1use js_sys::Object;
2use wasm_bindgen::JsValue;
3
4use crate::{Cursor, CursorDirection, Error};
5
6/// A cursor that is managed by the library (for ease of use).
7#[cfg(feature = "futures")]
8#[cfg_attr(any(docsrs, feature = "doc"), doc(cfg(feature = "futures")))]
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct ManagedCursor {
11    inner: Option<Cursor>,
12}
13
14impl ManagedCursor {
15    /// Returns the [`ObjectStore`](crate::ObjectStore) or [`Index`](crate::Index) the cursor was opened from.
16    // TODO: make return type as enum: (IDBObjectStore or IDBIndex)
17    pub fn source(&self) -> Option<Object> {
18        self.inner.as_ref().map(|cursor| cursor.source())
19    }
20
21    /// Returns the direction of the cursor.
22    pub fn direction(&self) -> Result<Option<CursorDirection>, Error> {
23        self.inner
24            .as_ref()
25            .map(|cursor| cursor.direction())
26            .transpose()
27    }
28
29    /// Returns the key of the cursor. Returns an [`Error`] if the cursor is advancing or is finished.
30    pub fn key(&self) -> Result<Option<JsValue>, Error> {
31        self.inner.as_ref().map(|cursor| cursor.key()).transpose()
32    }
33
34    /// Returns the effective key of the cursor. Returns an [`Error`] if the cursor is advancing or is finished.
35    pub fn primary_key(&self) -> Result<Option<JsValue>, Error> {
36        self.inner
37            .as_ref()
38            .map(|cursor| cursor.primary_key())
39            .transpose()
40    }
41
42    /// Returns the cursor's current value. Returns an [`Error`] if the cursor is advancing or is finished.
43    pub fn value(&self) -> Result<Option<JsValue>, Error> {
44        self.inner.as_ref().map(|cursor| cursor.value()).transpose()
45    }
46
47    /// Advances the cursor through the next count records in range.
48    pub async fn advance(&mut self, count: u32) -> Result<(), Error> {
49        let new_inner = {
50            let inner = self.inner.as_ref().ok_or(Error::CursorFinished)?;
51            inner.advance(count)?.await?
52        };
53
54        self.inner = new_inner;
55
56        Ok(())
57    }
58
59    /// Advances the cursor to the next record in range matching or after key (if provided).
60    pub async fn next(&mut self, key: Option<&JsValue>) -> Result<(), Error> {
61        let new_inner = {
62            let inner = self.inner.as_ref().ok_or(Error::CursorFinished)?;
63            inner.next(key)?.await?
64        };
65
66        self.inner = new_inner;
67
68        Ok(())
69    }
70
71    /// Advances the cursor to the next record in range matching or after key and primary key. Returns an [`Error`] if
72    /// the source is not an [`Index`](crate::Index).
73    pub async fn next_primary_key(
74        &mut self,
75        key: &JsValue,
76        primary_key: &JsValue,
77    ) -> Result<(), Error> {
78        let new_inner = {
79            let inner = self.inner.as_ref().ok_or(Error::CursorFinished)?;
80            inner.next_primary_key(key, primary_key)?.await?
81        };
82
83        self.inner = new_inner;
84
85        Ok(())
86    }
87
88    /// Updated the record pointed at by the cursor with a new value.
89    pub async fn update(&self, value: &JsValue) -> Result<JsValue, Error> {
90        self.inner
91            .as_ref()
92            .ok_or(Error::CursorFinished)?
93            .update(value)?
94            .await
95    }
96
97    /// Delete the record pointed at by the cursor with a new value.
98    pub async fn delete(&self) -> Result<(), Error> {
99        self.inner
100            .as_ref()
101            .ok_or(Error::CursorFinished)?
102            .delete()?
103            .await
104    }
105}
106
107impl From<Cursor> for ManagedCursor {
108    fn from(inner: Cursor) -> Self {
109        Self { inner: Some(inner) }
110    }
111}