1use std::cmp::{Ordering, PartialEq, PartialOrd};
6use std::error::Error;
7use std::fmt::{Debug, Display, Formatter};
8
9use ipc_channel::ipc::IpcSender;
10use malloc_size_of_derive::MallocSizeOf;
11use serde::{Deserialize, Serialize};
12use servo_url::origin::ImmutableOrigin;
13
14pub type DbError = String;
16pub type DbResult<T> = Result<T, DbError>;
19
20#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
22pub enum BackendError {
23 DbNotFound,
25 StoreNotFound,
27 DbErr(DbError),
28}
29
30impl From<DbError> for BackendError {
31 fn from(value: DbError) -> Self {
32 BackendError::DbErr(value)
33 }
34}
35
36impl Display for BackendError {
37 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
38 write!(f, "{:?}", self)
39 }
40}
41
42impl Error for BackendError {}
43
44pub type BackendResult<T> = Result<T, BackendError>;
45
46#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
47pub enum KeyPath {
48 String(String),
49 Sequence(Vec<String>),
50}
51
52#[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
54pub enum IndexedDBTxnMode {
55 Readonly,
56 Readwrite,
57 Versionchange,
58}
59
60#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
62pub enum IndexedDBKeyType {
63 Number(f64),
64 String(String),
65 Binary(Vec<u8>),
66 Date(f64),
67 Array(Vec<IndexedDBKeyType>),
68 }
70
71impl PartialOrd for IndexedDBKeyType {
73 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
74 match (self, other) {
78 (
80 IndexedDBKeyType::Array(_),
81 IndexedDBKeyType::Binary(_) |
82 IndexedDBKeyType::Date(_) |
83 IndexedDBKeyType::Number(_) |
84 IndexedDBKeyType::String(_),
85 ) => Some(Ordering::Greater),
86 (
88 IndexedDBKeyType::Binary(_) |
89 IndexedDBKeyType::Date(_) |
90 IndexedDBKeyType::Number(_) |
91 IndexedDBKeyType::String(_),
92 IndexedDBKeyType::Array(_),
93 ) => Some(Ordering::Less),
94 (
96 IndexedDBKeyType::Binary(_),
97 IndexedDBKeyType::String(_) |
98 IndexedDBKeyType::Date(_) |
99 IndexedDBKeyType::Number(_),
100 ) => Some(Ordering::Greater),
101 (
103 IndexedDBKeyType::String(_) |
104 IndexedDBKeyType::Date(_) |
105 IndexedDBKeyType::Number(_),
106 IndexedDBKeyType::Binary(_),
107 ) => Some(Ordering::Less),
108 (
110 IndexedDBKeyType::String(_),
111 IndexedDBKeyType::Date(_) | IndexedDBKeyType::Number(_),
112 ) => Some(Ordering::Greater),
113 (
115 IndexedDBKeyType::Date(_) | IndexedDBKeyType::Number(_),
116 IndexedDBKeyType::String(_),
117 ) => Some(Ordering::Less),
118 (IndexedDBKeyType::Date(_), IndexedDBKeyType::Number(_)) => Some(Ordering::Greater),
120 (IndexedDBKeyType::Number(_), IndexedDBKeyType::Date(_)) => Some(Ordering::Less),
122 (IndexedDBKeyType::Number(a), IndexedDBKeyType::Number(b)) => a.partial_cmp(b),
125 (IndexedDBKeyType::String(a), IndexedDBKeyType::String(b)) => a.partial_cmp(b),
127 (IndexedDBKeyType::Binary(a), IndexedDBKeyType::Binary(b)) => a.partial_cmp(b),
129 (IndexedDBKeyType::Date(a), IndexedDBKeyType::Date(b)) => a.partial_cmp(b),
130 (IndexedDBKeyType::Array(a), IndexedDBKeyType::Array(b)) => a.partial_cmp(b),
132 }
134 }
135}
136
137impl PartialEq for IndexedDBKeyType {
138 fn eq(&self, other: &Self) -> bool {
139 let cmp = self.partial_cmp(other);
140 match cmp {
141 Some(Ordering::Equal) => true,
142 Some(Ordering::Less) | Some(Ordering::Greater) => false,
143 None => {
144 false
146 },
147 }
148 }
149}
150
151#[derive(Clone, Debug, Default, Deserialize, MallocSizeOf, Serialize)]
153#[allow(unused)]
154pub struct IndexedDBKeyRange {
155 pub lower: Option<IndexedDBKeyType>,
156 pub upper: Option<IndexedDBKeyType>,
157 pub lower_open: bool,
158 pub upper_open: bool,
159}
160
161impl From<IndexedDBKeyType> for IndexedDBKeyRange {
162 fn from(key: IndexedDBKeyType) -> Self {
163 IndexedDBKeyRange {
164 lower: Some(key.clone()),
165 upper: Some(key),
166 ..Default::default()
167 }
168 }
169}
170
171impl IndexedDBKeyRange {
172 pub fn only(key: IndexedDBKeyType) -> Self {
173 Self::from(key)
174 }
175
176 pub fn new(
177 lower: Option<IndexedDBKeyType>,
178 upper: Option<IndexedDBKeyType>,
179 lower_open: bool,
180 upper_open: bool,
181 ) -> Self {
182 IndexedDBKeyRange {
183 lower,
184 upper,
185 lower_open,
186 upper_open,
187 }
188 }
189
190 pub fn lower_bound(key: IndexedDBKeyType, open: bool) -> Self {
191 IndexedDBKeyRange {
192 lower: Some(key),
193 upper: None,
194 lower_open: open,
195 upper_open: false,
196 }
197 }
198
199 pub fn upper_bound(key: IndexedDBKeyType, open: bool) -> Self {
200 IndexedDBKeyRange {
201 lower: None,
202 upper: Some(key),
203 lower_open: false,
204 upper_open: open,
205 }
206 }
207
208 pub fn contains(&self, key: &IndexedDBKeyType) -> bool {
210 let lower_bound_condition = self
216 .lower
217 .as_ref()
218 .is_none_or(|lower| lower < key || (!self.lower_open && lower == key));
219 let upper_bound_condition = self
220 .upper
221 .as_ref()
222 .is_none_or(|upper| key < upper || (!self.upper_open && key == upper));
223 lower_bound_condition && upper_bound_condition
224 }
225
226 pub fn is_singleton(&self) -> bool {
227 self.lower.is_some() && self.lower == self.upper && !self.lower_open && !self.upper_open
228 }
229
230 pub fn as_singleton(&self) -> Option<&IndexedDBKeyType> {
231 if self.is_singleton() {
232 return Some(self.lower.as_ref().unwrap());
233 }
234 None
235 }
236}
237
238#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
240pub struct IndexedDBRecord {
241 pub key: IndexedDBKeyType,
242 pub primary_key: IndexedDBKeyType,
243 pub value: Vec<u8>,
244}
245
246#[test]
247fn test_as_singleton() {
248 let key = IndexedDBKeyType::Number(1.0);
249 let key2 = IndexedDBKeyType::Number(2.0);
250 let range = IndexedDBKeyRange::only(key.clone());
251 assert!(range.is_singleton());
252 assert!(range.as_singleton().is_some());
253 let range = IndexedDBKeyRange::new(Some(key), Some(key2.clone()), false, false);
254 assert!(!range.is_singleton());
255 assert!(range.as_singleton().is_none());
256 let full_range = IndexedDBKeyRange::new(None, None, false, false);
257 assert!(!full_range.is_singleton());
258 assert!(full_range.as_singleton().is_none());
259}
260
261#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
262pub enum PutItemResult {
263 Success,
264 CannotOverwrite,
265}
266
267#[derive(Debug, Deserialize, Serialize)]
268pub enum AsyncReadOnlyOperation {
269 GetKey {
271 sender: IpcSender<BackendResult<Option<IndexedDBKeyType>>>,
272 key_range: IndexedDBKeyRange,
273 },
274 GetItem {
275 sender: IpcSender<BackendResult<Option<Vec<u8>>>>,
276 key_range: IndexedDBKeyRange,
277 },
278
279 GetAllKeys {
280 sender: IpcSender<BackendResult<Vec<IndexedDBKeyType>>>,
281 key_range: IndexedDBKeyRange,
282 count: Option<u32>,
283 },
284 GetAllItems {
285 sender: IpcSender<BackendResult<Vec<Vec<u8>>>>,
286 key_range: IndexedDBKeyRange,
287 count: Option<u32>,
288 },
289
290 Count {
291 sender: IpcSender<BackendResult<u64>>,
292 key_range: IndexedDBKeyRange,
293 },
294 Iterate {
295 sender: IpcSender<BackendResult<Vec<IndexedDBRecord>>>,
296 key_range: IndexedDBKeyRange,
297 },
298}
299
300#[derive(Debug, Deserialize, Serialize)]
301pub enum AsyncReadWriteOperation {
302 PutItem {
304 sender: IpcSender<BackendResult<PutItemResult>>,
305 key: Option<IndexedDBKeyType>,
306 value: Vec<u8>,
307 should_overwrite: bool,
308 },
309
310 RemoveItem {
312 sender: IpcSender<BackendResult<()>>,
313 key: IndexedDBKeyType,
314 },
315 Clear(IpcSender<BackendResult<()>>),
317}
318
319#[derive(Debug, Deserialize, Serialize)]
322pub enum AsyncOperation {
323 ReadOnly(AsyncReadOnlyOperation),
324 ReadWrite(AsyncReadWriteOperation),
325}
326
327#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
328pub enum CreateObjectResult {
329 Created,
330 AlreadyExists,
331}
332
333#[derive(Debug, Deserialize, Serialize)]
334pub enum SyncOperation {
335 UpgradeVersion(
337 IpcSender<BackendResult<u64>>,
339 ImmutableOrigin,
340 String, u64, u64, ),
344 HasKeyGenerator(
346 IpcSender<BackendResult<bool>>,
347 ImmutableOrigin,
348 String, String, ),
351 KeyPath(
353 IpcSender<BackendResult<Option<KeyPath>>>,
355 ImmutableOrigin,
356 String, String, ),
359
360 Commit(
362 IpcSender<BackendResult<()>>,
363 ImmutableOrigin,
364 String, u64, ),
367
368 CreateIndex(
370 IpcSender<BackendResult<CreateObjectResult>>,
371 ImmutableOrigin,
372 String, String, String, KeyPath, bool, bool, ),
379 DeleteIndex(
381 IpcSender<BackendResult<()>>,
382 ImmutableOrigin,
383 String, String, String, ),
387
388 CreateObjectStore(
390 IpcSender<BackendResult<CreateObjectResult>>,
391 ImmutableOrigin,
392 String, String, Option<KeyPath>, bool,
396 ),
397
398 DeleteObjectStore(
399 IpcSender<BackendResult<()>>,
400 ImmutableOrigin,
401 String, String, ),
404
405 CloseDatabase(
406 IpcSender<BackendResult<()>>,
407 ImmutableOrigin,
408 String, ),
410
411 OpenDatabase(
412 IpcSender<u64>, ImmutableOrigin,
414 String, Option<u64>, ),
417
418 DeleteDatabase(
420 IpcSender<BackendResult<()>>,
421 ImmutableOrigin,
422 String, ),
424
425 RegisterNewTxn(
428 IpcSender<u64>,
430 ImmutableOrigin,
431 String, ),
433
434 StartTransaction(
437 IpcSender<BackendResult<()>>,
438 ImmutableOrigin,
439 String, u64, ),
442
443 Version(
445 IpcSender<BackendResult<u64>>,
446 ImmutableOrigin,
447 String, ),
449
450 Exit(IpcSender<()>),
452}
453
454#[derive(Debug, Deserialize, Serialize)]
455pub enum IndexedDBThreadMsg {
456 Sync(SyncOperation),
457 Async(
458 ImmutableOrigin,
459 String, String, u64, IndexedDBTxnMode,
463 AsyncOperation,
464 ),
465}