Skip to main content

script/dom/indexeddb/
idbkeyrange.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use dom_struct::dom_struct;
6use js::context::JSContext;
7use js::gc::MutableHandleValue;
8use js::rust::HandleValue;
9use script_bindings::codegen::GenericBindings::IDBKeyRangeBinding::IDBKeyRangeMethods;
10use script_bindings::reflector::{Reflector, reflect_dom_object_with_cx};
11use script_bindings::root::DomRoot;
12use storage_traits::indexeddb::IndexedDBKeyRange;
13
14use crate::dom::bindings::error::{Error, Fallible};
15use crate::dom::globalscope::GlobalScope;
16use crate::indexeddb::{convert_value_to_key, key_type_to_jsval};
17
18#[dom_struct]
19pub struct IDBKeyRange {
20    reflector_: Reflector,
21    #[no_trace]
22    inner: IndexedDBKeyRange,
23}
24
25impl IDBKeyRange {
26    pub fn new_inherited(inner: IndexedDBKeyRange) -> Self {
27        IDBKeyRange {
28            reflector_: Reflector::new(),
29            inner,
30        }
31    }
32
33    pub fn new(
34        cx: &mut JSContext,
35        global: &GlobalScope,
36        inner: IndexedDBKeyRange,
37    ) -> DomRoot<Self> {
38        reflect_dom_object_with_cx(Box::new(IDBKeyRange::new_inherited(inner)), global, cx)
39    }
40
41    pub fn inner(&self) -> &IndexedDBKeyRange {
42        &self.inner
43    }
44}
45
46impl IDBKeyRangeMethods<crate::DomTypeHolder> for IDBKeyRange {
47    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-lower>
48    fn Lower(&self, cx: &mut JSContext, answer: MutableHandleValue) {
49        if let Some(lower) = self.inner.lower.as_ref() {
50            key_type_to_jsval(cx, lower, answer);
51        }
52    }
53
54    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-upper>
55    fn Upper(&self, cx: &mut JSContext, answer: MutableHandleValue) {
56        if let Some(upper) = self.inner.upper.as_ref() {
57            key_type_to_jsval(cx, upper, answer);
58        }
59    }
60
61    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-loweropen>
62    fn LowerOpen(&self) -> bool {
63        self.inner.lower_open
64    }
65
66    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-upperopen>
67    fn UpperOpen(&self) -> bool {
68        self.inner.upper_open
69    }
70
71    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-only>
72    fn Only(
73        cx: &mut JSContext,
74        global: &GlobalScope,
75        value: HandleValue,
76    ) -> Fallible<DomRoot<IDBKeyRange>> {
77        // Step 1. Let key be the result of converting a value to a key with value. Rethrow any
78        // exceptions.
79        // Step 2. If key is "invalid value" or "invalid type", throw a "DataError"
80        // DOMException.
81        let key = convert_value_to_key(cx, value, None)?.into_result()?;
82
83        // Step 3. Create and return a new key range containing only key.
84        let inner = IndexedDBKeyRange::only(key);
85        Ok(IDBKeyRange::new(cx, global, inner))
86    }
87
88    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-lowerbound>
89    fn LowerBound(
90        cx: &mut JSContext,
91        global: &GlobalScope,
92        lower: HandleValue,
93        open: bool,
94    ) -> Fallible<DomRoot<IDBKeyRange>> {
95        // Step 1. Let lowerKey be the result of converting a value to a key with lower. Rethrow
96        // any exceptions.
97        // Step 2. If lowerKey is invalid, throw a "DataError" DOMException.
98        let lower_key = convert_value_to_key(cx, lower, None)?.into_result()?;
99
100        // Step 3. Create and return a new key range with lower bound set to lowerKey, lower open
101        // flag set to open, upper bound set to null, and upper open flag set to true.
102        let inner = IndexedDBKeyRange::lower_bound(lower_key, open);
103        Ok(IDBKeyRange::new(cx, global, inner))
104    }
105
106    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-upperbound>
107    fn UpperBound(
108        cx: &mut JSContext,
109        global: &GlobalScope,
110        upper: HandleValue,
111        open: bool,
112    ) -> Fallible<DomRoot<IDBKeyRange>> {
113        // Step 1. Let upperKey be the result of converting a value to a key with upper. Rethrow
114        // any exceptions.
115        // Step 2. If upperKey is "invalid value" or "invalid type", throw a "DataError"
116        // DOMException.
117        let upper_key = convert_value_to_key(cx, upper, None)?.into_result()?;
118
119        // Step 3. Create and return a new key range with lower bound set to null, lower open flag
120        // set to true, upper bound set to upperKey, and upper open flag set to open.
121        let inner = IndexedDBKeyRange::upper_bound(upper_key, open);
122        Ok(IDBKeyRange::new(cx, global, inner))
123    }
124
125    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-bound>
126    fn Bound(
127        cx: &mut JSContext,
128        global: &GlobalScope,
129        lower: HandleValue,
130        upper: HandleValue,
131        lower_open: bool,
132        upper_open: bool,
133    ) -> Fallible<DomRoot<IDBKeyRange>> {
134        // Step 1. Let lowerKey be the result of converting a value to a key with lower. Rethrow
135        // any exceptions.
136        // Step 2. If lowerKey is "invalid value" or "invalid type", throw a "DataError"
137        // DOMException.
138        let lower_key = convert_value_to_key(cx, lower, None)?.into_result()?;
139
140        // Step 3. Let upperKey be the result of converting a value to a key with upper. Rethrow
141        // any exceptions.
142        // Step 4. If upperKey is "invalid value" or "invalid type", throw a "DataError"
143        // DOMException.
144        let upper_key = convert_value_to_key(cx, upper, None)?.into_result()?;
145
146        // Step 5. If lowerKey is greater than upperKey, throw a "DataError" DOMException.
147        if lower_key > upper_key {
148            return Err(Error::Data(None));
149        }
150
151        // Step 6. Create and return a new key range with lower bound set to lowerKey, lower open
152        // flag set to lowerOpen, upper bound set to upperKey and upper open flag set to upperOpen.
153        let inner =
154            IndexedDBKeyRange::new(Some(lower_key), Some(upper_key), lower_open, upper_open);
155        Ok(IDBKeyRange::new(cx, global, inner))
156    }
157
158    /// <https://www.w3.org/TR/IndexedDB-3/#dom-idbkeyrange-_includes>
159    fn Includes(&self, cx: &mut JSContext, key: HandleValue) -> Fallible<bool> {
160        // Step 1. Let k be the result of converting a value to a key with key. Rethrow any
161        // exceptions.
162        // Step 2. If k is "invalid value" or "invalid type", throw a "DataError" DOMException.
163        let k = convert_value_to_key(cx, key, None)?.into_result()?;
164
165        // Step 3. Return true if k is in this range, and false otherwise.
166        Ok(self.inner.contains(&k))
167    }
168}