1use std::cmp::{Ordering, PartialEq, PartialOrd};
6use std::collections::{HashMap, HashSet};
7use std::error::Error;
8use std::fmt::{Debug, Display, Formatter};
9
10use base::generic_channel::GenericSender;
11use malloc_size_of_derive::MallocSizeOf;
12use profile_traits::generic_callback::GenericCallback;
13use serde::{Deserialize, Serialize};
14use servo_url::origin::ImmutableOrigin;
15use uuid::Uuid;
16
17pub type DbError = String;
19pub type DbResult<T> = Result<T, DbError>;
22
23#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
25pub enum BackendError {
26 DbNotFound,
28 StoreNotFound,
30 QuotaExceeded,
32
33 DbErr(DbError),
34}
35
36impl From<DbError> for BackendError {
37 fn from(value: DbError) -> Self {
38 BackendError::DbErr(value)
39 }
40}
41
42impl Display for BackendError {
43 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
44 match self {
45 BackendError::DbNotFound => write!(f, "DbNotFound"),
46 BackendError::StoreNotFound => write!(f, "StoreNotFound"),
47 BackendError::QuotaExceeded => write!(f, "QuotaExceeded"),
48 BackendError::DbErr(err) => write!(f, "{err}"),
49 }
50 }
51}
52
53impl Error for BackendError {}
54
55pub type BackendResult<T> = Result<T, BackendError>;
56
57#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
58pub enum KeyPath {
59 String(String),
60 Sequence(Vec<String>),
61}
62
63#[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
65pub enum IndexedDBTxnMode {
66 Readonly,
67 Readwrite,
68 Versionchange,
69}
70
71#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
73pub enum IndexedDBKeyType {
74 Number(f64),
75 String(String),
76 Binary(Vec<u8>),
77 Date(f64),
78 Array(Vec<IndexedDBKeyType>),
79 }
81
82impl PartialOrd for IndexedDBKeyType {
84 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
85 match (self, other) {
89 (
91 IndexedDBKeyType::Array(_),
92 IndexedDBKeyType::Binary(_) |
93 IndexedDBKeyType::Date(_) |
94 IndexedDBKeyType::Number(_) |
95 IndexedDBKeyType::String(_),
96 ) => Some(Ordering::Greater),
97 (
99 IndexedDBKeyType::Binary(_) |
100 IndexedDBKeyType::Date(_) |
101 IndexedDBKeyType::Number(_) |
102 IndexedDBKeyType::String(_),
103 IndexedDBKeyType::Array(_),
104 ) => Some(Ordering::Less),
105 (
107 IndexedDBKeyType::Binary(_),
108 IndexedDBKeyType::String(_) |
109 IndexedDBKeyType::Date(_) |
110 IndexedDBKeyType::Number(_),
111 ) => Some(Ordering::Greater),
112 (
114 IndexedDBKeyType::String(_) |
115 IndexedDBKeyType::Date(_) |
116 IndexedDBKeyType::Number(_),
117 IndexedDBKeyType::Binary(_),
118 ) => Some(Ordering::Less),
119 (
121 IndexedDBKeyType::String(_),
122 IndexedDBKeyType::Date(_) | IndexedDBKeyType::Number(_),
123 ) => Some(Ordering::Greater),
124 (
126 IndexedDBKeyType::Date(_) | IndexedDBKeyType::Number(_),
127 IndexedDBKeyType::String(_),
128 ) => Some(Ordering::Less),
129 (IndexedDBKeyType::Date(_), IndexedDBKeyType::Number(_)) => Some(Ordering::Greater),
131 (IndexedDBKeyType::Number(_), IndexedDBKeyType::Date(_)) => Some(Ordering::Less),
133 (IndexedDBKeyType::Number(a), IndexedDBKeyType::Number(b)) => a.partial_cmp(b),
136 (IndexedDBKeyType::String(a), IndexedDBKeyType::String(b)) => a.partial_cmp(b),
138 (IndexedDBKeyType::Binary(a), IndexedDBKeyType::Binary(b)) => a.partial_cmp(b),
140 (IndexedDBKeyType::Date(a), IndexedDBKeyType::Date(b)) => a.partial_cmp(b),
141 (IndexedDBKeyType::Array(a), IndexedDBKeyType::Array(b)) => a.partial_cmp(b),
143 }
145 }
146}
147
148impl PartialEq for IndexedDBKeyType {
149 fn eq(&self, other: &Self) -> bool {
150 let cmp = self.partial_cmp(other);
151 match cmp {
152 Some(Ordering::Equal) => true,
153 Some(Ordering::Less) | Some(Ordering::Greater) => false,
154 None => {
155 false
157 },
158 }
159 }
160}
161
162#[derive(Clone, Debug, Default, Deserialize, MallocSizeOf, Serialize)]
164pub struct IndexedDBKeyRange {
165 pub lower: Option<IndexedDBKeyType>,
166 pub upper: Option<IndexedDBKeyType>,
167 pub lower_open: bool,
168 pub upper_open: bool,
169}
170
171impl From<IndexedDBKeyType> for IndexedDBKeyRange {
172 fn from(key: IndexedDBKeyType) -> Self {
173 IndexedDBKeyRange {
174 lower: Some(key.clone()),
175 upper: Some(key),
176 ..Default::default()
177 }
178 }
179}
180
181impl IndexedDBKeyRange {
182 pub fn only(key: IndexedDBKeyType) -> Self {
183 Self::from(key)
184 }
185
186 pub fn new(
187 lower: Option<IndexedDBKeyType>,
188 upper: Option<IndexedDBKeyType>,
189 lower_open: bool,
190 upper_open: bool,
191 ) -> Self {
192 IndexedDBKeyRange {
193 lower,
194 upper,
195 lower_open,
196 upper_open,
197 }
198 }
199
200 pub fn lower_bound(key: IndexedDBKeyType, open: bool) -> Self {
201 IndexedDBKeyRange {
202 lower: Some(key),
203 upper: None,
204 lower_open: open,
205 upper_open: false,
206 }
207 }
208
209 pub fn upper_bound(key: IndexedDBKeyType, open: bool) -> Self {
210 IndexedDBKeyRange {
211 lower: None,
212 upper: Some(key),
213 lower_open: false,
214 upper_open: open,
215 }
216 }
217
218 pub fn contains(&self, key: &IndexedDBKeyType) -> bool {
220 let lower_bound_condition = self
226 .lower
227 .as_ref()
228 .is_none_or(|lower| lower < key || (!self.lower_open && lower == key));
229 let upper_bound_condition = self
230 .upper
231 .as_ref()
232 .is_none_or(|upper| key < upper || (!self.upper_open && key == upper));
233 lower_bound_condition && upper_bound_condition
234 }
235
236 pub fn is_singleton(&self) -> bool {
237 self.lower.is_some() && self.lower == self.upper && !self.lower_open && !self.upper_open
238 }
239
240 pub fn as_singleton(&self) -> Option<&IndexedDBKeyType> {
241 if self.is_singleton() {
242 return Some(self.lower.as_ref().unwrap());
243 }
244 None
245 }
246}
247
248#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
250pub struct IndexedDBRecord {
251 pub key: IndexedDBKeyType,
252 pub primary_key: IndexedDBKeyType,
253 pub value: Vec<u8>,
254}
255
256#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
257pub enum PutItemResult {
258 Success,
259 CannotOverwrite,
260}
261
262#[derive(Debug, Deserialize, Serialize)]
263pub enum AsyncReadOnlyOperation {
264 GetKey {
266 callback: GenericCallback<BackendResult<Option<IndexedDBKeyType>>>,
267 key_range: IndexedDBKeyRange,
268 },
269 GetItem {
270 callback: GenericCallback<BackendResult<Option<Vec<u8>>>>,
271 key_range: IndexedDBKeyRange,
272 },
273
274 GetAllKeys {
275 callback: GenericCallback<BackendResult<Vec<IndexedDBKeyType>>>,
276 key_range: IndexedDBKeyRange,
277 count: Option<u32>,
278 },
279 GetAllItems {
280 callback: GenericCallback<BackendResult<Vec<Vec<u8>>>>,
281 key_range: IndexedDBKeyRange,
282 count: Option<u32>,
283 },
284
285 Count {
286 callback: GenericCallback<BackendResult<u64>>,
287 key_range: IndexedDBKeyRange,
288 },
289 Iterate {
290 callback: GenericCallback<BackendResult<Vec<IndexedDBRecord>>>,
291 key_range: IndexedDBKeyRange,
292 },
293}
294
295#[derive(Debug, Deserialize, Serialize)]
296pub enum AsyncReadWriteOperation {
297 PutItem {
299 callback: GenericCallback<BackendResult<PutItemResult>>,
300 key: Option<IndexedDBKeyType>,
301 value: Vec<u8>,
302 should_overwrite: bool,
303 },
304
305 RemoveItem {
307 callback: GenericCallback<BackendResult<()>>,
308 key_range: IndexedDBKeyRange,
309 },
310 Clear(GenericCallback<BackendResult<()>>),
312}
313
314#[derive(Debug, Deserialize, Serialize)]
317pub enum AsyncOperation {
318 ReadOnly(AsyncReadOnlyOperation),
319 ReadWrite(AsyncReadWriteOperation),
320}
321
322#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
323pub enum CreateObjectResult {
324 Created,
325 AlreadyExists,
326}
327
328#[derive(Debug, Deserialize, Serialize)]
329pub enum OpenDatabaseResult {
335 VersionError,
336 AbortError,
337 Connection {
339 version: u64,
340 upgraded: bool,
341 },
342 Upgrade {
344 version: u64,
345 old_version: u64,
346 transaction: u64,
347 },
348}
349
350#[derive(Debug, Deserialize, Serialize)]
351pub struct DatabaseInfo {
352 pub name: String,
353 pub version: u64,
354}
355
356#[derive(Debug, Deserialize, Serialize)]
357pub enum SyncOperation {
358 GetDatabases(
360 GenericCallback<BackendResult<Vec<DatabaseInfo>>>,
361 ImmutableOrigin,
362 ),
363 UpgradeVersion(
365 GenericSender<BackendResult<u64>>,
367 ImmutableOrigin,
368 String, u64, u64, ),
372 HasKeyGenerator(
374 GenericSender<BackendResult<bool>>,
375 ImmutableOrigin,
376 String, String, ),
379 KeyPath(
381 GenericSender<BackendResult<Option<KeyPath>>>,
383 ImmutableOrigin,
384 String, String, ),
387
388 Commit(
390 GenericSender<BackendResult<()>>,
391 ImmutableOrigin,
392 String, u64, ),
395
396 CreateIndex(
398 GenericSender<BackendResult<CreateObjectResult>>,
399 ImmutableOrigin,
400 String, String, String, KeyPath, bool, bool, ),
407 DeleteIndex(
409 GenericSender<BackendResult<()>>,
410 ImmutableOrigin,
411 String, String, String, ),
415
416 CreateObjectStore(
418 GenericSender<BackendResult<CreateObjectResult>>,
419 ImmutableOrigin,
420 String, String, Option<KeyPath>, bool,
424 ),
425
426 DeleteObjectStore(
427 GenericSender<BackendResult<()>>,
428 ImmutableOrigin,
429 String, String, ),
432
433 CloseDatabase(
434 GenericSender<BackendResult<()>>,
435 ImmutableOrigin,
436 String, ),
438
439 OpenDatabase(
440 GenericCallback<BackendResult<OpenDatabaseResult>>,
442 ImmutableOrigin,
444 String,
446 Option<u64>,
448 Uuid,
450 ),
451
452 DeleteDatabase(
454 GenericCallback<BackendResult<u64>>,
455 ImmutableOrigin,
456 String, Uuid,
458 ),
459
460 RegisterNewTxn(
463 GenericSender<u64>,
465 ImmutableOrigin,
466 String, ),
468
469 StartTransaction(
472 GenericSender<BackendResult<()>>,
473 ImmutableOrigin,
474 String, u64, ),
477
478 Version(
480 GenericSender<BackendResult<u64>>,
481 ImmutableOrigin,
482 String, ),
484
485 AbortPendingUpgrades {
487 pending_upgrades: HashMap<String, HashSet<Uuid>>,
488 origin: ImmutableOrigin,
489 },
490
491 AbortPendingUpgrade {
493 name: String,
494 id: Uuid,
495 origin: ImmutableOrigin,
496 },
497
498 Exit(GenericSender<()>),
500}
501
502#[derive(Debug, Deserialize, Serialize)]
503pub enum IndexedDBThreadMsg {
504 Sync(SyncOperation),
505 Async(
506 ImmutableOrigin,
507 String, String, u64, IndexedDBTxnMode,
511 AsyncOperation,
512 ),
513 OpenTransactionInactive {
514 name: String,
515 origin: ImmutableOrigin,
516 },
517}
518
519#[cfg(test)]
520mod test {
521 use super::*;
522
523 #[test]
524 fn test_as_singleton() {
525 let key = IndexedDBKeyType::Number(1.0);
526 let key2 = IndexedDBKeyType::Number(2.0);
527 let range = IndexedDBKeyRange::only(key.clone());
528 assert!(range.is_singleton());
529 assert!(range.as_singleton().is_some());
530 let range = IndexedDBKeyRange::new(Some(key), Some(key2.clone()), false, false);
531 assert!(!range.is_singleton());
532 assert!(range.as_singleton().is_none());
533 let full_range = IndexedDBKeyRange::new(None, None, false, false);
534 assert!(!full_range.is_singleton());
535 assert!(full_range.as_singleton().is_none());
536 }
537}