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,
24 StoreNotFound,
25 DbErr(DbError),
26}
27
28impl From<DbError> for BackendError {
29 fn from(value: DbError) -> Self {
30 BackendError::DbErr(value)
31 }
32}
33
34impl Display for BackendError {
35 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
36 write!(f, "{:?}", self)
37 }
38}
39
40impl Error for BackendError {}
41
42pub type BackendResult<T> = Result<T, BackendError>;
43
44#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
45pub enum KeyPath {
46 String(String),
47 Sequence(Vec<String>),
48}
49
50#[derive(Debug, Deserialize, Eq, PartialEq, Serialize)]
52pub enum IndexedDBTxnMode {
53 Readonly,
54 Readwrite,
55 Versionchange,
56}
57
58#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
60pub enum IndexedDBKeyType {
61 Number(f64),
62 String(String),
63 Binary(Vec<u8>),
64 Date(f64),
65 Array(Vec<IndexedDBKeyType>),
66 }
68
69impl PartialOrd for IndexedDBKeyType {
71 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
72 match (self, other) {
76 (
78 IndexedDBKeyType::Array(_),
79 IndexedDBKeyType::Binary(_) |
80 IndexedDBKeyType::Date(_) |
81 IndexedDBKeyType::Number(_) |
82 IndexedDBKeyType::String(_),
83 ) => Some(Ordering::Greater),
84 (
86 IndexedDBKeyType::Binary(_) |
87 IndexedDBKeyType::Date(_) |
88 IndexedDBKeyType::Number(_) |
89 IndexedDBKeyType::String(_),
90 IndexedDBKeyType::Array(_),
91 ) => Some(Ordering::Less),
92 (
94 IndexedDBKeyType::Binary(_),
95 IndexedDBKeyType::String(_) |
96 IndexedDBKeyType::Date(_) |
97 IndexedDBKeyType::Number(_),
98 ) => Some(Ordering::Greater),
99 (
101 IndexedDBKeyType::String(_) |
102 IndexedDBKeyType::Date(_) |
103 IndexedDBKeyType::Number(_),
104 IndexedDBKeyType::Binary(_),
105 ) => Some(Ordering::Less),
106 (
108 IndexedDBKeyType::String(_),
109 IndexedDBKeyType::Date(_) | IndexedDBKeyType::Number(_),
110 ) => Some(Ordering::Greater),
111 (
113 IndexedDBKeyType::Date(_) | IndexedDBKeyType::Number(_),
114 IndexedDBKeyType::String(_),
115 ) => Some(Ordering::Less),
116 (IndexedDBKeyType::Date(_), IndexedDBKeyType::Number(_)) => Some(Ordering::Greater),
118 (IndexedDBKeyType::Number(_), IndexedDBKeyType::Date(_)) => Some(Ordering::Less),
120 (IndexedDBKeyType::Number(a), IndexedDBKeyType::Number(b)) => a.partial_cmp(b),
123 (IndexedDBKeyType::String(a), IndexedDBKeyType::String(b)) => a.partial_cmp(b),
125 (IndexedDBKeyType::Binary(a), IndexedDBKeyType::Binary(b)) => a.partial_cmp(b),
127 (IndexedDBKeyType::Date(a), IndexedDBKeyType::Date(b)) => a.partial_cmp(b),
128 (IndexedDBKeyType::Array(a), IndexedDBKeyType::Array(b)) => a.partial_cmp(b),
130 }
132 }
133}
134
135impl PartialEq for IndexedDBKeyType {
136 fn eq(&self, other: &Self) -> bool {
137 let cmp = self.partial_cmp(other);
138 match cmp {
139 Some(Ordering::Equal) => true,
140 Some(Ordering::Less) | Some(Ordering::Greater) => false,
141 None => {
142 false
144 },
145 }
146 }
147}
148
149#[derive(Clone, Debug, Default, Deserialize, MallocSizeOf, Serialize)]
151#[allow(unused)]
152pub struct IndexedDBKeyRange {
153 pub lower: Option<IndexedDBKeyType>,
154 pub upper: Option<IndexedDBKeyType>,
155 pub lower_open: bool,
156 pub upper_open: bool,
157}
158
159impl From<IndexedDBKeyType> for IndexedDBKeyRange {
160 fn from(key: IndexedDBKeyType) -> Self {
161 IndexedDBKeyRange {
162 lower: Some(key.clone()),
163 upper: Some(key),
164 ..Default::default()
165 }
166 }
167}
168
169impl IndexedDBKeyRange {
170 pub fn only(key: IndexedDBKeyType) -> Self {
171 Self::from(key)
172 }
173
174 pub fn new(
175 lower: Option<IndexedDBKeyType>,
176 upper: Option<IndexedDBKeyType>,
177 lower_open: bool,
178 upper_open: bool,
179 ) -> Self {
180 IndexedDBKeyRange {
181 lower,
182 upper,
183 lower_open,
184 upper_open,
185 }
186 }
187
188 pub fn lower_bound(key: IndexedDBKeyType, open: bool) -> Self {
189 IndexedDBKeyRange {
190 lower: Some(key),
191 upper: None,
192 lower_open: open,
193 upper_open: false,
194 }
195 }
196
197 pub fn upper_bound(key: IndexedDBKeyType, open: bool) -> Self {
198 IndexedDBKeyRange {
199 lower: None,
200 upper: Some(key),
201 lower_open: false,
202 upper_open: open,
203 }
204 }
205
206 pub fn contains(&self, key: &IndexedDBKeyType) -> bool {
208 let lower_bound_condition = self
214 .lower
215 .as_ref()
216 .is_none_or(|lower| lower < key || (!self.lower_open && lower == key));
217 let upper_bound_condition = self
218 .upper
219 .as_ref()
220 .is_none_or(|upper| key < upper || (!self.upper_open && key == upper));
221 lower_bound_condition && upper_bound_condition
222 }
223
224 pub fn is_singleton(&self) -> bool {
225 self.lower.is_some() && self.lower == self.upper && !self.lower_open && !self.upper_open
226 }
227
228 pub fn as_singleton(&self) -> Option<&IndexedDBKeyType> {
229 if self.is_singleton() {
230 return Some(self.lower.as_ref().unwrap());
231 }
232 None
233 }
234}
235
236#[test]
237fn test_as_singleton() {
238 let key = IndexedDBKeyType::Number(1.0);
239 let key2 = IndexedDBKeyType::Number(2.0);
240 let range = IndexedDBKeyRange::only(key.clone());
241 assert!(range.is_singleton());
242 assert!(range.as_singleton().is_some());
243 let range = IndexedDBKeyRange::new(Some(key), Some(key2.clone()), false, false);
244 assert!(!range.is_singleton());
245 assert!(range.as_singleton().is_none());
246 let full_range = IndexedDBKeyRange::new(None, None, false, false);
247 assert!(!full_range.is_singleton());
248 assert!(full_range.as_singleton().is_none());
249}
250
251#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
252pub enum PutItemResult {
253 Success,
254 CannotOverwrite,
255}
256
257#[derive(Debug, Deserialize, Serialize)]
258pub enum AsyncReadOnlyOperation {
259 GetKey {
261 sender: IpcSender<BackendResult<Option<IndexedDBKeyType>>>,
262 key_range: IndexedDBKeyRange,
263 },
264 GetItem {
265 sender: IpcSender<BackendResult<Option<Vec<u8>>>>,
266 key_range: IndexedDBKeyRange,
267 },
268
269 Count {
270 sender: IpcSender<BackendResult<u64>>,
271 key_range: IndexedDBKeyRange,
272 },
273}
274
275#[derive(Debug, Deserialize, Serialize)]
276pub enum AsyncReadWriteOperation {
277 PutItem {
279 sender: IpcSender<BackendResult<PutItemResult>>,
280 key: Option<IndexedDBKeyType>,
281 value: Vec<u8>,
282 should_overwrite: bool,
283 },
284
285 RemoveItem {
287 sender: IpcSender<BackendResult<()>>,
288 key: IndexedDBKeyType,
289 },
290 Clear(IpcSender<BackendResult<()>>),
292}
293
294#[derive(Debug, Deserialize, Serialize)]
297pub enum AsyncOperation {
298 ReadOnly(AsyncReadOnlyOperation),
299 ReadWrite(AsyncReadWriteOperation),
300}
301
302#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
303pub enum CreateObjectResult {
304 Created,
305 AlreadyExists,
306}
307
308#[derive(Debug, Deserialize, Serialize)]
309pub enum SyncOperation {
310 UpgradeVersion(
312 IpcSender<BackendResult<u64>>,
313 ImmutableOrigin,
314 String, u64, u64, ),
318 HasKeyGenerator(
320 IpcSender<BackendResult<bool>>,
321 ImmutableOrigin,
322 String, String, ),
325 KeyPath(
327 IpcSender<BackendResult<Option<KeyPath>>>,
329 ImmutableOrigin,
330 String, String, ),
333
334 Commit(
336 IpcSender<BackendResult<()>>,
337 ImmutableOrigin,
338 String, u64, ),
341
342 CreateIndex(
344 IpcSender<BackendResult<CreateObjectResult>>,
345 ImmutableOrigin,
346 String, String, String, KeyPath, bool, bool, ),
353 DeleteIndex(
355 IpcSender<BackendResult<()>>,
356 ImmutableOrigin,
357 String, String, String, ),
361
362 CreateObjectStore(
364 IpcSender<BackendResult<CreateObjectResult>>,
365 ImmutableOrigin,
366 String, String, Option<KeyPath>, bool,
370 ),
371
372 DeleteObjectStore(
373 IpcSender<BackendResult<()>>,
374 ImmutableOrigin,
375 String, String, ),
378
379 CloseDatabase(
380 IpcSender<BackendResult<()>>,
381 ImmutableOrigin,
382 String, ),
384
385 OpenDatabase(
386 IpcSender<u64>, ImmutableOrigin,
388 String, Option<u64>, ),
391
392 DeleteDatabase(
394 IpcSender<BackendResult<()>>,
395 ImmutableOrigin,
396 String, ),
398
399 RegisterNewTxn(
402 IpcSender<u64>,
403 ImmutableOrigin,
404 String, ),
406
407 StartTransaction(
410 IpcSender<BackendResult<()>>,
411 ImmutableOrigin,
412 String, u64, ),
415
416 Version(
418 IpcSender<BackendResult<u64>>,
419 ImmutableOrigin,
420 String, ),
422
423 Exit(IpcSender<()>),
425}
426
427#[derive(Debug, Deserialize, Serialize)]
428pub enum IndexedDBThreadMsg {
429 Sync(SyncOperation),
430 Async(
431 ImmutableOrigin,
432 String, String, u64, IndexedDBTxnMode,
436 AsyncOperation,
437 ),
438}