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#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
247pub enum PutItemResult {
248 Success,
249 CannotOverwrite,
250}
251
252#[derive(Debug, Deserialize, Serialize)]
253pub enum AsyncReadOnlyOperation {
254 GetKey {
256 sender: IpcSender<BackendResult<Option<IndexedDBKeyType>>>,
257 key_range: IndexedDBKeyRange,
258 },
259 GetItem {
260 sender: IpcSender<BackendResult<Option<Vec<u8>>>>,
261 key_range: IndexedDBKeyRange,
262 },
263
264 GetAllKeys {
265 sender: IpcSender<BackendResult<Vec<IndexedDBKeyType>>>,
266 key_range: IndexedDBKeyRange,
267 count: Option<u32>,
268 },
269 GetAllItems {
270 sender: IpcSender<BackendResult<Vec<Vec<u8>>>>,
271 key_range: IndexedDBKeyRange,
272 count: Option<u32>,
273 },
274
275 Count {
276 sender: IpcSender<BackendResult<u64>>,
277 key_range: IndexedDBKeyRange,
278 },
279 Iterate {
280 sender: IpcSender<BackendResult<Vec<IndexedDBRecord>>>,
281 key_range: IndexedDBKeyRange,
282 },
283}
284
285#[derive(Debug, Deserialize, Serialize)]
286pub enum AsyncReadWriteOperation {
287 PutItem {
289 sender: IpcSender<BackendResult<PutItemResult>>,
290 key: Option<IndexedDBKeyType>,
291 value: Vec<u8>,
292 should_overwrite: bool,
293 },
294
295 RemoveItem {
297 sender: IpcSender<BackendResult<()>>,
298 key: IndexedDBKeyType,
299 },
300 Clear(IpcSender<BackendResult<()>>),
302}
303
304#[derive(Debug, Deserialize, Serialize)]
307pub enum AsyncOperation {
308 ReadOnly(AsyncReadOnlyOperation),
309 ReadWrite(AsyncReadWriteOperation),
310}
311
312#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
313pub enum CreateObjectResult {
314 Created,
315 AlreadyExists,
316}
317
318#[derive(Debug, Deserialize, Serialize)]
319pub enum SyncOperation {
320 UpgradeVersion(
322 IpcSender<BackendResult<u64>>,
324 ImmutableOrigin,
325 String, u64, u64, ),
329 HasKeyGenerator(
331 IpcSender<BackendResult<bool>>,
332 ImmutableOrigin,
333 String, String, ),
336 KeyPath(
338 IpcSender<BackendResult<Option<KeyPath>>>,
340 ImmutableOrigin,
341 String, String, ),
344
345 Commit(
347 IpcSender<BackendResult<()>>,
348 ImmutableOrigin,
349 String, u64, ),
352
353 CreateIndex(
355 IpcSender<BackendResult<CreateObjectResult>>,
356 ImmutableOrigin,
357 String, String, String, KeyPath, bool, bool, ),
364 DeleteIndex(
366 IpcSender<BackendResult<()>>,
367 ImmutableOrigin,
368 String, String, String, ),
372
373 CreateObjectStore(
375 IpcSender<BackendResult<CreateObjectResult>>,
376 ImmutableOrigin,
377 String, String, Option<KeyPath>, bool,
381 ),
382
383 DeleteObjectStore(
384 IpcSender<BackendResult<()>>,
385 ImmutableOrigin,
386 String, String, ),
389
390 CloseDatabase(
391 IpcSender<BackendResult<()>>,
392 ImmutableOrigin,
393 String, ),
395
396 OpenDatabase(
397 IpcSender<u64>, ImmutableOrigin,
399 String, Option<u64>, ),
402
403 DeleteDatabase(
405 IpcSender<BackendResult<()>>,
406 ImmutableOrigin,
407 String, ),
409
410 RegisterNewTxn(
413 IpcSender<u64>,
415 ImmutableOrigin,
416 String, ),
418
419 StartTransaction(
422 IpcSender<BackendResult<()>>,
423 ImmutableOrigin,
424 String, u64, ),
427
428 Version(
430 IpcSender<BackendResult<u64>>,
431 ImmutableOrigin,
432 String, ),
434
435 Exit(IpcSender<()>),
437}
438
439#[derive(Debug, Deserialize, Serialize)]
440pub enum IndexedDBThreadMsg {
441 Sync(SyncOperation),
442 Async(
443 ImmutableOrigin,
444 String, String, u64, IndexedDBTxnMode,
448 AsyncOperation,
449 ),
450}
451
452#[cfg(test)]
453mod test {
454 use super::*;
455
456 #[test]
457 fn test_as_singleton() {
458 let key = IndexedDBKeyType::Number(1.0);
459 let key2 = IndexedDBKeyType::Number(2.0);
460 let range = IndexedDBKeyRange::only(key.clone());
461 assert!(range.is_singleton());
462 assert!(range.as_singleton().is_some());
463 let range = IndexedDBKeyRange::new(Some(key), Some(key2.clone()), false, false);
464 assert!(!range.is_singleton());
465 assert!(range.as_singleton().is_none());
466 let full_range = IndexedDBKeyRange::new(None, None, false, false);
467 assert!(!full_range.is_singleton());
468 assert!(full_range.as_singleton().is_none());
469 }
470}