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}