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)]
153pub struct IndexedDBKeyRange {
154 pub lower: Option<IndexedDBKeyType>,
155 pub upper: Option<IndexedDBKeyType>,
156 pub lower_open: bool,
157 pub upper_open: bool,
158}
159
160impl From<IndexedDBKeyType> for IndexedDBKeyRange {
161 fn from(key: IndexedDBKeyType) -> Self {
162 IndexedDBKeyRange {
163 lower: Some(key.clone()),
164 upper: Some(key),
165 ..Default::default()
166 }
167 }
168}
169
170impl IndexedDBKeyRange {
171 pub fn only(key: IndexedDBKeyType) -> Self {
172 Self::from(key)
173 }
174
175 pub fn new(
176 lower: Option<IndexedDBKeyType>,
177 upper: Option<IndexedDBKeyType>,
178 lower_open: bool,
179 upper_open: bool,
180 ) -> Self {
181 IndexedDBKeyRange {
182 lower,
183 upper,
184 lower_open,
185 upper_open,
186 }
187 }
188
189 pub fn lower_bound(key: IndexedDBKeyType, open: bool) -> Self {
190 IndexedDBKeyRange {
191 lower: Some(key),
192 upper: None,
193 lower_open: open,
194 upper_open: false,
195 }
196 }
197
198 pub fn upper_bound(key: IndexedDBKeyType, open: bool) -> Self {
199 IndexedDBKeyRange {
200 lower: None,
201 upper: Some(key),
202 lower_open: false,
203 upper_open: open,
204 }
205 }
206
207 pub fn contains(&self, key: &IndexedDBKeyType) -> bool {
209 let lower_bound_condition = self
215 .lower
216 .as_ref()
217 .is_none_or(|lower| lower < key || (!self.lower_open && lower == key));
218 let upper_bound_condition = self
219 .upper
220 .as_ref()
221 .is_none_or(|upper| key < upper || (!self.upper_open && key == upper));
222 lower_bound_condition && upper_bound_condition
223 }
224
225 pub fn is_singleton(&self) -> bool {
226 self.lower.is_some() && self.lower == self.upper && !self.lower_open && !self.upper_open
227 }
228
229 pub fn as_singleton(&self) -> Option<&IndexedDBKeyType> {
230 if self.is_singleton() {
231 return Some(self.lower.as_ref().unwrap());
232 }
233 None
234 }
235}
236
237#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
239pub struct IndexedDBRecord {
240 pub key: IndexedDBKeyType,
241 pub primary_key: IndexedDBKeyType,
242 pub value: Vec<u8>,
243}
244
245#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
246pub enum PutItemResult {
247 Success,
248 CannotOverwrite,
249}
250
251#[derive(Debug, Deserialize, Serialize)]
252pub enum AsyncReadOnlyOperation {
253 GetKey {
255 sender: IpcSender<BackendResult<Option<IndexedDBKeyType>>>,
256 key_range: IndexedDBKeyRange,
257 },
258 GetItem {
259 sender: IpcSender<BackendResult<Option<Vec<u8>>>>,
260 key_range: IndexedDBKeyRange,
261 },
262
263 GetAllKeys {
264 sender: IpcSender<BackendResult<Vec<IndexedDBKeyType>>>,
265 key_range: IndexedDBKeyRange,
266 count: Option<u32>,
267 },
268 GetAllItems {
269 sender: IpcSender<BackendResult<Vec<Vec<u8>>>>,
270 key_range: IndexedDBKeyRange,
271 count: Option<u32>,
272 },
273
274 Count {
275 sender: IpcSender<BackendResult<u64>>,
276 key_range: IndexedDBKeyRange,
277 },
278 Iterate {
279 sender: IpcSender<BackendResult<Vec<IndexedDBRecord>>>,
280 key_range: IndexedDBKeyRange,
281 },
282}
283
284#[derive(Debug, Deserialize, Serialize)]
285pub enum AsyncReadWriteOperation {
286 PutItem {
288 sender: IpcSender<BackendResult<PutItemResult>>,
289 key: Option<IndexedDBKeyType>,
290 value: Vec<u8>,
291 should_overwrite: bool,
292 },
293
294 RemoveItem {
296 sender: IpcSender<BackendResult<()>>,
297 key_range: IndexedDBKeyRange,
298 },
299 Clear(IpcSender<BackendResult<()>>),
301}
302
303#[derive(Debug, Deserialize, Serialize)]
306pub enum AsyncOperation {
307 ReadOnly(AsyncReadOnlyOperation),
308 ReadWrite(AsyncReadWriteOperation),
309}
310
311#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
312pub enum CreateObjectResult {
313 Created,
314 AlreadyExists,
315}
316
317#[derive(Debug, Deserialize, Serialize)]
318pub enum SyncOperation {
319 UpgradeVersion(
321 IpcSender<BackendResult<u64>>,
323 ImmutableOrigin,
324 String, u64, u64, ),
328 HasKeyGenerator(
330 IpcSender<BackendResult<bool>>,
331 ImmutableOrigin,
332 String, String, ),
335 KeyPath(
337 IpcSender<BackendResult<Option<KeyPath>>>,
339 ImmutableOrigin,
340 String, String, ),
343
344 Commit(
346 IpcSender<BackendResult<()>>,
347 ImmutableOrigin,
348 String, u64, ),
351
352 CreateIndex(
354 IpcSender<BackendResult<CreateObjectResult>>,
355 ImmutableOrigin,
356 String, String, String, KeyPath, bool, bool, ),
363 DeleteIndex(
365 IpcSender<BackendResult<()>>,
366 ImmutableOrigin,
367 String, String, String, ),
371
372 CreateObjectStore(
374 IpcSender<BackendResult<CreateObjectResult>>,
375 ImmutableOrigin,
376 String, String, Option<KeyPath>, bool,
380 ),
381
382 DeleteObjectStore(
383 IpcSender<BackendResult<()>>,
384 ImmutableOrigin,
385 String, String, ),
388
389 CloseDatabase(
390 IpcSender<BackendResult<()>>,
391 ImmutableOrigin,
392 String, ),
394
395 OpenDatabase(
396 IpcSender<u64>, ImmutableOrigin,
398 String, Option<u64>, ),
401
402 DeleteDatabase(
404 IpcSender<BackendResult<()>>,
405 ImmutableOrigin,
406 String, ),
408
409 RegisterNewTxn(
412 IpcSender<u64>,
414 ImmutableOrigin,
415 String, ),
417
418 StartTransaction(
421 IpcSender<BackendResult<()>>,
422 ImmutableOrigin,
423 String, u64, ),
426
427 Version(
429 IpcSender<BackendResult<u64>>,
430 ImmutableOrigin,
431 String, ),
433
434 Exit(IpcSender<()>),
436}
437
438#[derive(Debug, Deserialize, Serialize)]
439pub enum IndexedDBThreadMsg {
440 Sync(SyncOperation),
441 Async(
442 ImmutableOrigin,
443 String, String, u64, IndexedDBTxnMode,
447 AsyncOperation,
448 ),
449}
450
451#[cfg(test)]
452mod test {
453 use super::*;
454
455 #[test]
456 fn test_as_singleton() {
457 let key = IndexedDBKeyType::Number(1.0);
458 let key2 = IndexedDBKeyType::Number(2.0);
459 let range = IndexedDBKeyRange::only(key.clone());
460 assert!(range.is_singleton());
461 assert!(range.as_singleton().is_some());
462 let range = IndexedDBKeyRange::new(Some(key), Some(key2.clone()), false, false);
463 assert!(!range.is_singleton());
464 assert!(range.as_singleton().is_none());
465 let full_range = IndexedDBKeyRange::new(None, None, false, false);
466 assert!(!full_range.is_singleton());
467 assert!(full_range.as_singleton().is_none());
468 }
469}