1
use std::borrow::Borrow;
2
use std::convert::Infallible;
3
use std::marker::PhantomData;
4
use std::ops::{Deref, DerefMut};
5
use std::string::FromUtf8Error;
6
use std::sync::Arc;
7

            
8
use actionable::{Action, Identifier};
9
use arc_bytes::serde::Bytes;
10
use async_trait::async_trait;
11
use futures::future::BoxFuture;
12
use futures::{Future, FutureExt};
13
use serde::{Deserialize, Serialize};
14
use zeroize::Zeroize;
15

            
16
use crate::admin::{Role, User};
17
use crate::document::{
18
    CollectionDocument, CollectionHeader, Document, HasHeader, Header, OwnedDocument,
19
};
20
use crate::key::{ByteSource, IntoPrefixRange, Key, KeyEncoding, KeyKind, KeyVisitor};
21
use crate::permissions::Permissions;
22
use crate::schema::view::map::{MappedDocuments, ViewMappings as ViewMappingsCurrent};
23
use crate::schema::{
24
    self, MappedValue, Nameable, NamedReference, Schema, SchemaName, SchemaSummary,
25
    SerializedCollection,
26
};
27
use crate::{transaction, Error};
28

            
29
mod has_session;
30
mod lowlevel;
31

            
32
pub use self::has_session::HasSession;
33
pub use self::lowlevel::{AsyncLowLevelConnection, HasSchema, LowLevelConnection};
34

            
35
/// A connection to a database's [`Schema`](schema::Schema), giving access to
36
/// [`Collection`s](crate::schema::Collection) and
37
/// [`Views`s](crate::schema::View). This trait is not safe to use within async
38
/// contexts and will block the current thread. For async access, use
39
/// [`AsyncConnection`].
40
pub trait Connection: LowLevelConnection + Sized + Send + Sync {
41
    /// The [`StorageConnection`] type that is paired with this type.
42
    type Storage: StorageConnection<Database = Self>;
43

            
44
    /// Returns the [`StorageConnection`] implementor that this database belongs to.
45
    fn storage(&self) -> Self::Storage;
46

            
47
    /// Accesses a collection for the connected [`Schema`](schema::Schema).
48
36962
    fn collection<C: schema::Collection>(&self) -> Collection<'_, Self, C> {
49
36962
        Collection::new(self)
50
36962
    }
51

            
52
    /// Accesses a [`schema::View`] from this connection.
53
24441
    fn view<V: schema::SerializedView>(&'_ self) -> View<'_, Self, V, V::Key> {
54
24441
        View::new(self)
55
24441
    }
56

            
57
    /// Lists [executed transactions](transaction::Executed) from this
58
    /// [`Schema`](schema::Schema). By default, a maximum of 1000 entries will
59
    /// be returned, but that limit can be overridden by setting `result_limit`.
60
    /// A hard limit of 100,000 results will be returned. To begin listing after
61
    /// another known `transaction_id`, pass `transaction_id + 1` into
62
    /// `starting_id`.
63
    fn list_executed_transactions(
64
        &self,
65
        starting_id: Option<u64>,
66
        result_limit: Option<u32>,
67
    ) -> Result<Vec<transaction::Executed>, Error>;
68

            
69
    /// Fetches the last transaction id that has been committed, if any.
70
    fn last_transaction_id(&self) -> Result<Option<u64>, Error>;
71

            
72
    /// Compacts the entire database to reclaim unused disk space.
73
    ///
74
    /// This process is done by writing data to a new file and swapping the file
75
    /// once the process completes. This ensures that if a hardware failure,
76
    /// power outage, or crash occurs that the original collection data is left
77
    /// untouched.
78
    ///
79
    /// ## Errors
80
    ///
81
    /// * [`Error::Other`]: an error occurred while compacting the database.
82
    fn compact(&self) -> Result<(), crate::Error>;
83

            
84
    /// Compacts the collection to reclaim unused disk space.
85
    ///
86
    /// This process is done by writing data to a new file and swapping the file
87
    /// once the process completes. This ensures that if a hardware failure,
88
    /// power outage, or crash occurs that the original collection data is left
89
    /// untouched.
90
    ///
91
    /// ## Errors
92
    ///
93
    /// * [`Error::CollectionNotFound`]: database `name` does not exist.
94
    /// * [`Error::Other`]: an error occurred while compacting the database.
95
6
    fn compact_collection<C: schema::Collection>(&self) -> Result<(), crate::Error> {
96
6
        self.compact_collection_by_name(C::collection_name())
97
6
    }
98

            
99
    /// Compacts the key value store to reclaim unused disk space.
100
    ///
101
    /// This process is done by writing data to a new file and swapping the file
102
    /// once the process completes. This ensures that if a hardware failure,
103
    /// power outage, or crash occurs that the original collection data is left
104
    /// untouched.
105
    ///
106
    /// ## Errors
107
    ///
108
    /// * [`Error::Other`]: an error occurred while compacting the database.
109
    fn compact_key_value_store(&self) -> Result<(), crate::Error>;
110
}
111

            
112
/// Interacts with a collection over a `Connection`.
113
///
114
/// These examples in this type use this basic collection definition:
115
///
116
/// ```rust
117
/// use bonsaidb_core::schema::Collection;
118
/// use bonsaidb_core::Error;
119
/// use serde::{Deserialize, Serialize};
120
///
121
/// #[derive(Debug, Serialize, Deserialize, Default, Collection)]
122
/// #[collection(name = "MyCollection")]
123
/// # #[collection(core = bonsaidb_core)]
124
/// pub struct MyCollection {
125
///     pub rank: u32,
126
///     pub score: f32,
127
/// }
128
/// ```
129
pub struct Collection<'a, Cn, Cl> {
130
    connection: &'a Cn,
131
    _phantom: PhantomData<Cl>, /* allows for extension traits to be written for collections of specific types */
132
}
133

            
134
impl<'a, Cn, Cl> Clone for Collection<'a, Cn, Cl> {
135
    fn clone(&self) -> Self {
136
        Self {
137
            connection: self.connection,
138
            _phantom: PhantomData,
139
        }
140
    }
141
}
142

            
143
impl<'a, Cn, Cl> Collection<'a, Cn, Cl>
144
where
145
    Cn: Connection,
146
    Cl: schema::Collection,
147
{
148
    /// Creates a new instance using `connection`.
149
36962
    fn new(connection: &'a Cn) -> Self {
150
36962
        Self {
151
36962
            connection,
152
36962
            _phantom: PhantomData,
153
36962
        }
154
36962
    }
155

            
156
    /// Adds a new `Document<Cl>` with the contents `item`.
157
    ///
158
    /// ## Automatic ID Assignment
159
    ///
160
    /// This function calls [`SerializedCollection::natural_id()`] to try to
161
    /// retrieve a primary key value from `item`. If an id is returned, the item
162
    /// is inserted with that id. If an id is not returned, an id will be
163
    /// automatically assigned, if possible, by the storage backend, which uses the [`Key`]
164
    /// trait to assign ids.
165
    ///
166
    /// ```rust
167
    /// # bonsaidb_core::__doctest_prelude!();
168
    /// # use bonsaidb_core::connection::Connection;
169
    /// # fn test_fn<C: Connection>(db: &C) -> Result<(), Error> {
170
    /// let inserted_header = db
171
    ///     .collection::<MyCollection>()
172
    ///     .push(&MyCollection::default())?;
173
    /// println!(
174
    ///     "Inserted id {} with revision {}",
175
    ///     inserted_header.id, inserted_header.revision
176
    /// );
177
    /// # Ok(())
178
    /// # }
179
    /// ```
180
37800
    pub fn push(
181
37800
        &self,
182
37800
        item: &<Cl as SerializedCollection>::Contents,
183
37800
    ) -> Result<CollectionHeader<Cl::PrimaryKey>, crate::Error>
184
37800
    where
185
37800
        Cl: schema::SerializedCollection,
186
37800
    {
187
37800
        let contents = Cl::serialize(item)?;
188
37800
        if let Some(natural_id) = Cl::natural_id(item) {
189
1
            self.insert_bytes(&natural_id, contents)
190
        } else {
191
37799
            self.push_bytes(contents)
192
        }
193
37800
    }
194

            
195
    /// Adds a new `Document<Cl>` with the `contents`.
196
    ///
197
    /// ## Automatic ID Assignment
198
    ///
199
    /// An id will be automatically assigned, if possible, by the storage backend, which uses
200
    /// the [`Key`] trait to assign ids.
201
    ///
202
    /// ```rust
203
    /// # bonsaidb_core::__doctest_prelude!();
204
    /// # use bonsaidb_core::connection::Connection;
205
    /// # fn test_fn<C: Connection>(db: &C) -> Result<(), Error> {
206
    /// let inserted_header = db.collection::<MyCollection>().push_bytes(vec![])?;
207
    /// println!(
208
    ///     "Inserted id {} with revision {}",
209
    ///     inserted_header.id, inserted_header.revision
210
    /// );
211
    /// # Ok(())
212
    /// # }
213
    /// ```
214
37799
    pub fn push_bytes<B: Into<Bytes> + Send>(
215
37799
        &self,
216
37799
        contents: B,
217
37799
    ) -> Result<CollectionHeader<Cl::PrimaryKey>, crate::Error> {
218
37799
        self.connection
219
37799
            .insert::<Cl, _, B>(Option::<&Cl::PrimaryKey>::None, contents)
220
37799
    }
221

            
222
    /// Adds a new `Document<Cl>` with the given `id` and contents `item`.
223
    ///
224
    /// ```rust
225
    /// # bonsaidb_core::__doctest_prelude!();
226
    /// # use bonsaidb_core::connection::Connection;
227
    /// # fn test_fn<C: Connection>(db: &C) -> Result<(), Error> {
228
    /// let inserted_header = db
229
    ///     .collection::<MyCollection>()
230
    ///     .insert(&42, &MyCollection::default())?;
231
    /// println!(
232
    ///     "Inserted id {} with revision {}",
233
    ///     inserted_header.id, inserted_header.revision
234
    /// );
235
    /// # Ok(())
236
    /// # }
237
    /// ```
238
16
    pub fn insert<PrimaryKey>(
239
16
        &self,
240
16
        id: &PrimaryKey,
241
16
        item: &<Cl as SerializedCollection>::Contents,
242
16
    ) -> Result<CollectionHeader<Cl::PrimaryKey>, crate::Error>
243
16
    where
244
16
        Cl: schema::SerializedCollection,
245
16
        PrimaryKey: KeyEncoding<Cl::PrimaryKey> + ?Sized,
246
16
    {
247
16
        let contents = Cl::serialize(item)?;
248
16
        self.connection.insert::<Cl, _, _>(Some(id), contents)
249
16
    }
250

            
251
    /// Adds a new `Document<Cl>` with the the given `id` and `contents`.
252
    ///
253
    /// ```rust
254
    /// # bonsaidb_core::__doctest_prelude!();
255
    /// # use bonsaidb_core::connection::Connection;
256
    /// # fn test_fn<C: Connection>(db: &C) -> Result<(), Error> {
257
    /// let inserted_header = db.collection::<MyCollection>().insert_bytes(&42, vec![])?;
258
    /// println!(
259
    ///     "Inserted id {} with revision {}",
260
    ///     inserted_header.id, inserted_header.revision
261
    /// );
262
    /// # Ok(())
263
    /// # }
264
    /// ```
265
1
    pub fn insert_bytes<PrimaryKey, B: Into<Bytes> + Send>(
266
1
        &self,
267
1
        id: &PrimaryKey,
268
1
        contents: B,
269
1
    ) -> Result<CollectionHeader<Cl::PrimaryKey>, crate::Error>
270
1
    where
271
1
        PrimaryKey: KeyEncoding<Cl::PrimaryKey> + ?Sized,
272
1
    {
273
1
        self.connection.insert::<Cl, _, B>(Some(id), contents)
274
1
    }
275

            
276
    /// Updates an existing document. Upon success, `doc.revision` will be
277
    /// updated with the new revision.
278
    ///
279
    /// ```rust
280
    /// # bonsaidb_core::__doctest_prelude!();
281
    /// # use bonsaidb_core::connection::Connection;
282
    /// # fn test_fn<C: Connection>(db: &C) -> Result<(), Error> {
283
    /// if let Some(mut document) = db.collection::<MyCollection>().get(&42)? {
284
    ///     // modify the document
285
    ///     db.collection::<MyCollection>().update(&mut document);
286
    ///     println!("Updated revision: {:?}", document.header.revision);
287
    /// }
288
    /// # Ok(())
289
    /// # }
290
    /// ```
291
    pub fn update<D: Document<Cl> + Send + Sync>(&self, doc: &mut D) -> Result<(), Error> {
292
        self.connection.update::<Cl, D>(doc)
293
    }
294

            
295
    /// Overwrites an existing document, or inserts a new document. Upon success,
296
    /// `doc.revision` will be updated with the new revision information.
297
    ///
298
    /// ```rust
299
    /// # bonsaidb_core::__doctest_prelude!();
300
    /// # use bonsaidb_core::connection::Connection;
301
    /// # fn test_fn<C: Connection>(db: &C) -> Result<(), Error> {
302
    /// if let Some(mut document) = db.collection::<MyCollection>().get(&42)? {
303
    ///     // modify the document
304
    ///     db.collection::<MyCollection>().overwrite(&mut document);
305
    ///     println!("Updated revision: {:?}", document.header.revision);
306
    /// }
307
    /// # Ok(())
308
    /// # }
309
    /// ```
310
3
    pub fn overwrite<D: Document<Cl> + Send + Sync>(&self, doc: &mut D) -> Result<(), Error> {
311
3
        let contents = doc.bytes()?;
312
3
        doc.set_collection_header(self.connection.overwrite::<Cl, _>(doc.id(), contents)?)
313
3
    }
314

            
315
    /// Retrieves a `Document<Cl>` with `id` from the connection.
316
    ///
317
    /// ```rust
318
    /// # bonsaidb_core::__doctest_prelude!();
319
    /// # use bonsaidb_core::connection::Connection;
320
    /// # fn test_fn<C: Connection>(db: &C) -> Result<(), Error> {
321
    /// if let Some(doc) = db.collection::<MyCollection>().get(&42)? {
322
    ///     println!(
323
    ///         "Retrieved bytes {:?} with revision {}",
324
    ///         doc.contents, doc.header.revision
325
    ///     );
326
    ///     let deserialized = MyCollection::document_contents(&doc)?;
327
    ///     println!("Deserialized contents: {:?}", deserialized);
328
    /// }
329
    /// # Ok(())
330
    /// # }
331
    /// ```
332
1350
    pub fn get<PrimaryKey>(&self, id: &PrimaryKey) -> Result<Option<OwnedDocument>, Error>
333
1350
    where
334
1350
        PrimaryKey: KeyEncoding<Cl::PrimaryKey> + ?Sized,
335
1350
    {
336
1350
        self.connection.get::<Cl, _>(id)
337
1350
    }
338

            
339
    /// Retrieves all documents matching `ids`. Documents that are not found
340
    /// are not returned, but no error will be generated.
341
    ///
342
    /// ```rust
343
    /// # bonsaidb_core::__doctest_prelude!();
344
    /// # use bonsaidb_core::connection::Connection;
345
    /// # fn test_fn<C: Connection>(db: &C) -> Result<(), Error> {
346
    /// for doc in db.collection::<MyCollection>().get_multiple(&[42, 43])? {
347
    ///     println!("Retrieved #{} with bytes {:?}", doc.header.id, doc.contents);
348
    ///     let deserialized = MyCollection::document_contents(&doc)?;
349
    ///     println!("Deserialized contents: {:?}", deserialized);
350
    /// }
351
    /// # Ok(())
352
    /// # }
353
    /// ```
354
645
    pub fn get_multiple<'id, DocumentIds, PrimaryKey, I>(
355
645
        &self,
356
645
        ids: DocumentIds,
357
645
    ) -> Result<Vec<OwnedDocument>, Error>
358
645
    where
359
645
        DocumentIds: IntoIterator<Item = &'id PrimaryKey, IntoIter = I> + Send + Sync,
360
645
        I: Iterator<Item = &'id PrimaryKey> + Send + Sync,
361
645
        PrimaryKey: KeyEncoding<Cl::PrimaryKey> + 'id + ?Sized,
362
645
    {
363
645
        self.connection.get_multiple::<Cl, _, _, _>(ids)
364
645
    }
365

            
366
    /// Retrieves all documents matching the range of `ids`.
367
    ///
368
    /// ```rust
369
    /// # bonsaidb_core::__doctest_prelude!();
370
    /// # use bonsaidb_core::connection::Connection;
371
    /// # fn test_fn<C: Connection>(db: &C) -> Result<(), Error> {
372
    /// for doc in db
373
    ///     .collection::<MyCollection>()
374
    ///     .list(&42..)
375
    ///     .descending()
376
    ///     .limit(20)
377
    ///     .query()?
378
    /// {
379
    ///     println!("Retrieved #{} with bytes {:?}", doc.header.id, doc.contents);
380
    ///     let deserialized = MyCollection::document_contents(&doc)?;
381
    ///     println!("Deserialized contents: {:?}", deserialized);
382
    /// }
383
    /// # Ok(())
384
    /// # }
385
    /// ```
386
    pub fn list<PrimaryKey, R>(&'a self, ids: R) -> List<'a, Cn, Cl, PrimaryKey>
387
    where
388
        R: Into<Range<&'a PrimaryKey>>,
389
        PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + 'a + ?Sized,
390
        Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
391
    {
392
        List::new(MaybeOwned::Borrowed(self), RangeRef::borrowed(ids.into()))
393
    }
394

            
395
    /// Retrieves all documents with ids that start with `prefix`.
396
    ///
397
    /// ```rust
398
    /// use bonsaidb_core::connection::Connection;
399
    /// use bonsaidb_core::document::OwnedDocument;
400
    /// use bonsaidb_core::schema::{Collection, Schematic, SerializedCollection};
401
    /// use bonsaidb_core::Error;
402
    /// use serde::{Deserialize, Serialize};
403
    ///
404
    /// #[derive(Debug, Serialize, Deserialize, Default, Collection)]
405
    /// #[collection(name = "MyCollection", primary_key = String)]
406
    /// # #[collection(core = bonsaidb_core)]
407
    /// pub struct MyCollection;
408
    ///
409
    /// fn starts_with_a<C: Connection>(db: &C) -> Result<Vec<OwnedDocument>, Error> {
410
    ///     db.collection::<MyCollection>()
411
    ///         .list_with_prefix("a")
412
    ///         .query()
413
    /// }
414
    /// ```
415
    pub fn list_with_prefix<PrimaryKey>(
416
        &'a self,
417
        prefix: &'a PrimaryKey,
418
    ) -> List<'a, Cn, Cl, PrimaryKey>
419
    where
420
        PrimaryKey:
421
            IntoPrefixRange<'a, Cl::PrimaryKey> + KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized,
422
        Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
423
    {
424
        List::new(MaybeOwned::Borrowed(self), prefix.to_prefix_range())
425
    }
426

            
427
    /// Retrieves all documents.
428
    ///
429
    /// ```rust
430
    /// # bonsaidb_core::__doctest_prelude!();
431
    /// # use bonsaidb_core::connection::Connection;
432
    /// # fn test_fn<C: Connection>(db: &C) -> Result<(), Error> {
433
    /// for doc in db.collection::<MyCollection>().all().query()? {
434
    ///     println!("Retrieved #{} with bytes {:?}", doc.header.id, doc.contents);
435
    ///     let deserialized = MyCollection::document_contents(&doc)?;
436
    ///     println!("Deserialized contents: {:?}", deserialized);
437
    /// }
438
    /// # Ok(())
439
    /// # }
440
    /// ```
441
    pub fn all(&'a self) -> List<'a, Cn, Cl, Cl::PrimaryKey> {
442
        List::new(
443
            MaybeOwned::Borrowed(self),
444
            RangeRef::borrowed(Range::from(..)),
445
        )
446
    }
447

            
448
    /// Removes a `Document` from the database.
449
    ///
450
    /// ```rust
451
    /// # bonsaidb_core::__doctest_prelude!();
452
    /// # use bonsaidb_core::connection::Connection;
453
    /// # fn test_fn<C: Connection>(db: &C) -> Result<(), Error> {
454
    /// if let Some(doc) = db.collection::<MyCollection>().get(&42)? {
455
    ///     db.collection::<MyCollection>().delete(&doc)?;
456
    /// }
457
    /// # Ok(())
458
    /// # }
459
    /// ```
460
17
    pub fn delete<H: HasHeader + Send + Sync>(&self, doc: &H) -> Result<(), Error> {
461
17
        self.connection.delete::<Cl, H>(doc)
462
17
    }
463
}
464

            
465
/// Retrieves a list of documents from a collection. This structure also offers
466
/// functions to customize the options for the operation.
467
#[must_use]
468
pub struct List<'a, Cn, Cl, PrimaryKey>
469
where
470
    Cl: schema::Collection,
471
    PrimaryKey: PartialEq + ?Sized,
472
    Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
473
{
474
    collection: MaybeOwned<'a, Collection<'a, Cn, Cl>>,
475
    range: RangeRef<'a, Cl::PrimaryKey, PrimaryKey>,
476
    sort: Sort,
477
    limit: Option<u32>,
478
}
479

            
480
impl<'a, Cn, Cl, PrimaryKey> List<'a, Cn, Cl, PrimaryKey>
481
where
482
    Cl: schema::Collection,
483
    Cn: Connection,
484
    PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + 'a + ?Sized,
485
    Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
486
{
487
33
    pub(crate) const fn new(
488
33
        collection: MaybeOwned<'a, Collection<'a, Cn, Cl>>,
489
33
        range: RangeRef<'a, Cl::PrimaryKey, PrimaryKey>,
490
33
    ) -> Self {
491
33
        Self {
492
33
            collection,
493
33
            range,
494
33
            sort: Sort::Ascending,
495
33
            limit: None,
496
33
        }
497
33
    }
498

            
499
    /// Lists documents by id in ascending order.
500
    pub const fn ascending(mut self) -> Self {
501
        self.sort = Sort::Ascending;
502
        self
503
    }
504

            
505
    /// Lists documents by id in descending order.
506
3
    pub const fn descending(mut self) -> Self {
507
3
        self.sort = Sort::Descending;
508
3
        self
509
3
    }
510

            
511
    /// Sets the maximum number of results to return.
512
3
    pub const fn limit(mut self, maximum_results: u32) -> Self {
513
3
        self.limit = Some(maximum_results);
514
3
        self
515
3
    }
516

            
517
    /// Returns the number of documents contained within the range.
518
    ///
519
    /// Order and limit are ignored if they were set.
520
    ///
521
    /// ```rust
522
    /// # bonsaidb_core::__doctest_prelude!();
523
    /// # use bonsaidb_core::connection::Connection;
524
    /// # fn test_fn<C: Connection>(db: &C) -> Result<(), Error> {
525
    /// println!(
526
    ///     "Number of documents with id 42 or larger: {}",
527
    ///     db.collection::<MyCollection>().list(&42..).count()?
528
    /// );
529
    /// println!(
530
    ///     "Number of documents in MyCollection: {}",
531
    ///     db.collection::<MyCollection>().all().count()?
532
    /// );
533
    /// # Ok(())
534
    /// # }
535
    /// ```
536
6
    pub fn count(self) -> Result<u64, Error> {
537
6
        let Self {
538
6
            collection, range, ..
539
6
        } = self;
540
6
        collection.connection.count::<Cl, _, _>(range)
541
6
    }
542

            
543
    /// Returns the list of headers for documents contained within the range.
544
    ///
545
    /// ```rust
546
    /// # bonsaidb_core::__doctest_prelude!();
547
    /// # use bonsaidb_core::connection::Connection;
548
    /// # fn test_fn<C: Connection>(db: &C) -> Result<(), Error> {
549
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
550
    /// println!(
551
    ///     "Headers with id 42 or larger: {:?}",
552
    ///     db.collection::<MyCollection>().list(&42..).headers()?
553
    /// );
554
    /// println!(
555
    ///     "Headers in MyCollection: {:?}",
556
    ///     db.collection::<MyCollection>().all().headers()?
557
    /// );
558
    /// # Ok(())
559
    /// # })
560
    /// # }
561
    /// ```
562
3
    pub fn headers(self) -> Result<Vec<Header>, Error> {
563
3
        let Self {
564
3
            collection,
565
3
            range,
566
3
            sort,
567
3
            limit,
568
3
            ..
569
3
        } = self;
570
3
        collection
571
3
            .connection
572
3
            .list_headers::<Cl, _, PrimaryKey>(range, sort, limit)
573
3
    }
574

            
575
    /// Retrieves the matching documents.
576
    ///
577
    /// ```rust
578
    /// # bonsaidb_core::__doctest_prelude!();
579
    /// # use bonsaidb_core::connection::Connection;
580
    /// # fn test_fn<C: Connection>(db: &C) -> Result<(), Error> {
581
    /// for doc in db.collection::<MyCollection>().all().query()? {
582
    ///     println!("Retrieved #{} with bytes {:?}", doc.header.id, doc.contents);
583
    ///     let deserialized = MyCollection::document_contents(&doc)?;
584
    ///     println!("Deserialized contents: {:?}", deserialized);
585
    /// }
586
    /// # Ok(())
587
    /// # }
588
    /// ```
589
24
    pub fn query(self) -> Result<Vec<OwnedDocument>, Error> {
590
24
        let Self {
591
24
            collection,
592
24
            range,
593
24
            sort,
594
24
            limit,
595
24
        } = self;
596
24
        collection.connection.list::<Cl, _, _>(range, sort, limit)
597
24
    }
598
}
599

            
600
/// Parameters to query a [`schema::View`].
601
///
602
/// The examples for this type use this view definition:
603
///
604
/// ```rust
605
/// # mod collection {
606
/// # bonsaidb_core::__doctest_prelude!();
607
/// # }
608
/// # use collection::MyCollection;
609
/// use bonsaidb_core::define_basic_unique_mapped_view;
610
/// use bonsaidb_core::document::{CollectionDocument, Emit};
611
/// use bonsaidb_core::schema::{
612
///     CollectionMapReduce, DefaultViewSerialization, Name, ReduceResult, View, ViewMapResult,
613
///     ViewMappedValue, ViewSchema,
614
/// };
615
///
616
/// #[derive(Debug, Clone, View, ViewSchema)]
617
/// #[view(collection = MyCollection, key = u32, value = f32, name = "scores-by-rank")]
618
/// # #[view(core = bonsaidb_core)]
619
/// # #[view_schema(core = bonsaidb_core)]
620
/// pub struct ScoresByRank;
621
///
622
/// impl CollectionMapReduce for ScoresByRank {
623
///     fn map<'doc>(
624
///         &self,
625
///         document: CollectionDocument<<Self::View as View>::Collection>,
626
///     ) -> ViewMapResult<'doc, Self::View> {
627
///         document
628
///             .header
629
///             .emit_key_and_value(document.contents.rank, document.contents.score)
630
///     }
631
///
632
///     fn reduce(
633
///         &self,
634
///         mappings: &[ViewMappedValue<'_, Self::View>],
635
///         rereduce: bool,
636
///     ) -> ReduceResult<Self::View> {
637
///         if mappings.is_empty() {
638
///             Ok(0.)
639
///         } else {
640
///             Ok(mappings.iter().map(|map| map.value).sum::<f32>() / mappings.len() as f32)
641
///         }
642
///     }
643
/// }
644
/// ```
645
#[must_use]
646
pub struct View<'a, Cn, V: schema::SerializedView, Key>
647
where
648
    V::Key: Borrow<Key> + PartialEq<Key>,
649
    Key: PartialEq + ?Sized,
650
{
651
    connection: &'a Cn,
652

            
653
    /// Key filtering criteria.
654
    pub key: Option<QueryKey<'a, V::Key, Key>>,
655

            
656
    /// The view's data access policy. The default value is [`AccessPolicy::UpdateBefore`].
657
    pub access_policy: AccessPolicy,
658

            
659
    /// The sort order of the query.
660
    pub sort: Sort,
661

            
662
    /// The maximum number of results to return.
663
    pub limit: Option<u32>,
664

            
665
    _view: PhantomData<V>,
666
}
667

            
668
impl<'a, Cn, V, Key> View<'a, Cn, V, Key>
669
where
670
    V::Key: Borrow<Key> + PartialEq<Key>,
671
    V: schema::SerializedView,
672
    Cn: Connection,
673
    Key: KeyEncoding<V::Key> + PartialEq + ?Sized,
674
{
675
24441
    const fn new(connection: &'a Cn) -> Self {
676
24441
        Self {
677
24441
            connection,
678
24441
            key: None,
679
24441
            access_policy: AccessPolicy::UpdateBefore,
680
24441
            sort: Sort::Ascending,
681
24441
            limit: None,
682
24441
            _view: PhantomData,
683
24441
        }
684
24441
    }
685

            
686
    /// Filters for entries in the view with `key`.
687
    ///
688
    /// ```rust
689
    /// # bonsaidb_core::__doctest_prelude!();
690
    /// # use bonsaidb_core::connection::Connection;
691
    /// # fn test_fn<C: Connection>(db: C) -> Result<(), Error> {
692
    /// // score is an f32 in this example
693
    /// for mapping in ScoresByRank::entries(&db).with_key(&42).query()? {
694
    ///     assert_eq!(mapping.key, 42);
695
    ///     println!("Rank {} has a score of {:3}", mapping.key, mapping.value);
696
    /// }
697
    /// # Ok(())
698
    /// # }
699
    /// ```
700
    #[allow(clippy::missing_const_for_fn)] // false positive, destructors
701
19230
    pub fn with_key<K>(self, key: &'a K) -> View<'a, Cn, V, K>
702
19230
    where
703
19230
        K: KeyEncoding<V::Key> + PartialEq + ?Sized,
704
19230
        V::Key: Borrow<K> + PartialEq<K>,
705
19230
    {
706
19230
        View {
707
19230
            connection: self.connection,
708
19230
            key: Some(QueryKey::Matches(MaybeOwned::Borrowed(key))),
709
19230
            access_policy: self.access_policy,
710
19230
            sort: self.sort,
711
19230
            limit: self.limit,
712
19230
            _view: PhantomData,
713
19230
        }
714
19230
    }
715

            
716
    /// Filters for entries in the view with `keys`.
717
    ///
718
    /// ```rust
719
    /// # bonsaidb_core::__doctest_prelude!();
720
    /// # use bonsaidb_core::connection::Connection;
721
    /// # fn test_fn<C: Connection>(db: C) -> Result<(), Error> {
722
    /// // score is an f32 in this example
723
    /// for mapping in ScoresByRank::entries(&db).with_keys(&[42, 43]).query()? {
724
    ///     println!("Rank {} has a score of {:3}", mapping.key, mapping.value);
725
    /// }
726
    /// # Ok(())
727
    /// # }
728
    /// ```
729
12
    pub fn with_keys<K, IntoIter: IntoIterator<Item = &'a K>>(
730
12
        self,
731
12
        keys: IntoIter,
732
12
    ) -> View<'a, Cn, V, K>
733
12
    where
734
12
        V::Key: Borrow<K> + PartialEq<K>,
735
12
        K: PartialEq + ?Sized,
736
12
    {
737
12
        View {
738
12
            connection: self.connection,
739
12
            key: Some(QueryKey::Multiple(
740
12
                keys.into_iter().map(MaybeOwned::Borrowed).collect(),
741
12
            )),
742
12
            access_policy: self.access_policy,
743
12
            sort: self.sort,
744
12
            limit: self.limit,
745
12
            _view: PhantomData,
746
12
        }
747
12
    }
748

            
749
    /// Filters for entries in the view with the range `keys`.
750
    ///
751
    /// ```rust
752
    /// # bonsaidb_core::__doctest_prelude!();
753
    /// # use bonsaidb_core::connection::Connection;
754
    /// # fn test_fn<C: Connection>(db: C) -> Result<(), Error> {
755
    /// // score is an f32 in this example
756
    /// for mapping in ScoresByRank::entries(&db).with_key_range(42..).query()? {
757
    ///     assert!(mapping.key >= 42);
758
    ///     println!("Rank {} has a score of {:3}", mapping.key, mapping.value);
759
    /// }
760
    /// # Ok(())
761
    /// # }
762
    /// ```
763
9
    pub fn with_key_range<K, R>(self, range: R) -> View<'a, Cn, V, K>
764
9
    where
765
9
        R: Into<RangeRef<'a, V::Key, K>>,
766
9
        K: PartialEq,
767
9
        V::Key: Borrow<K> + PartialEq<K>,
768
9
    {
769
9
        View {
770
9
            connection: self.connection,
771
9
            key: Some(QueryKey::Range(range.into())),
772
9
            access_policy: self.access_policy,
773
9
            sort: self.sort,
774
9
            limit: self.limit,
775
9
            _view: PhantomData,
776
9
        }
777
9
    }
778

            
779
    /// Filters for entries in the view with keys that begin with `prefix`.
780
    ///
781
    /// ```rust
782
    /// # bonsaidb_core::__doctest_prelude!();
783
    /// # use bonsaidb_core::connection::Connection;
784
    /// # fn test_fn<C: Connection>(db: C) -> Result<(), Error> {
785
    /// #[derive(View, Debug, Clone)]
786
    /// #[view(name = "by-name", key = String, collection = MyCollection)]
787
    /// # #[view(core = bonsaidb_core)]
788
    /// struct ByName;
789
    ///
790
    /// // score is an f32 in this example
791
    /// for mapping in ByName::entries(&db).with_key_prefix("a").query()? {
792
    ///     assert!(mapping.key.starts_with("a"));
793
    ///     println!("{} in document {:?}", mapping.key, mapping.source);
794
    /// }
795
    /// # Ok(())
796
    /// # }
797
    /// ```
798
14
    pub fn with_key_prefix<K>(self, prefix: &'a K) -> View<'a, Cn, V, K>
799
14
    where
800
14
        K: KeyEncoding<V::Key> + IntoPrefixRange<'a, V::Key> + PartialEq + ?Sized,
801
14
        V::Key: Borrow<K> + PartialEq<K>,
802
14
    {
803
14
        View {
804
14
            connection: self.connection,
805
14
            key: Some(QueryKey::Range(prefix.to_prefix_range())),
806
14
            access_policy: self.access_policy,
807
14
            sort: self.sort,
808
14
            limit: self.limit,
809
14
            _view: PhantomData,
810
14
        }
811
14
    }
812

            
813
    /// Sets the access policy for queries.
814
    ///
815
    /// ```rust
816
    /// # bonsaidb_core::__doctest_prelude!();
817
    /// # use bonsaidb_core::connection::Connection;
818
    /// # fn test_fn<C: Connection>(db: C) -> Result<(), Error> {
819
    /// // score is an f32 in this example
820
    /// for mapping in ScoresByRank::entries(&db)
821
    ///     .with_access_policy(AccessPolicy::UpdateAfter)
822
    ///     .query()?
823
    /// {
824
    ///     println!("Rank {} has a score of {:3}", mapping.key, mapping.value);
825
    /// }
826
    /// # Ok(())
827
    /// # }
828
    /// ```
829
23
    pub const fn with_access_policy(mut self, policy: AccessPolicy) -> Self {
830
23
        self.access_policy = policy;
831
23
        self
832
23
    }
833

            
834
    /// Returns the matching mappings in ascending key order. This is the
835
    /// default sorting behavior.
836
    ///
837
    /// When more than one mapping exists for a single key, all matching
838
    /// mappings are returned as a unique entry. The resulting mappings are
839
    /// sorted only by the key, and as such, the order of mappings with the same
840
    /// key is undefined.
841
    ///
842
    /// ```rust
843
    /// # bonsaidb_core::__doctest_prelude!();
844
    /// # use bonsaidb_core::connection::Connection;
845
    /// # fn test_fn<C: Connection>(db: C) -> Result<(), Error> {
846
    /// // score is an f32 in this example
847
    /// for mapping in ScoresByRank::entries(&db).ascending().query()? {
848
    ///     println!("Rank {} has a score of {:3}", mapping.key, mapping.value);
849
    /// }
850
    /// # Ok(())
851
    /// # }
852
    /// ```
853
    pub const fn ascending(mut self) -> Self {
854
        self.sort = Sort::Ascending;
855
        self
856
    }
857

            
858
    /// Returns the matching mappings in descending key order.
859
    ///
860
    /// When more than one mapping exists for a single key, all matching
861
    /// mappings are returned as a unique entry. The resulting mappings are
862
    /// sorted only by the key, and as such, the order of mappings with the same
863
    /// key is undefined.
864
    ///
865
    /// ```rust
866
    /// # bonsaidb_core::__doctest_prelude!();
867
    /// # use bonsaidb_core::connection::Connection;
868
    /// # fn test_fn<C: Connection>(db: C) -> Result<(), Error> {
869
    /// // score is an f32 in this example
870
    /// for mapping in ScoresByRank::entries(&db).descending().query()? {
871
    ///     println!("Rank {} has a score of {:3}", mapping.key, mapping.value);
872
    /// }
873
    /// # Ok(())
874
    /// # }
875
    /// ```
876
3
    pub const fn descending(mut self) -> Self {
877
3
        self.sort = Sort::Descending;
878
3
        self
879
3
    }
880

            
881
    /// Sets the maximum number of results to return.
882
    ///
883
    /// ```rust
884
    /// # bonsaidb_core::__doctest_prelude!();
885
    /// # use bonsaidb_core::connection::Connection;
886
    /// # fn test_fn<C: Connection>(db: C) -> Result<(), Error> {
887
    /// // score is an f32 in this example
888
    /// let mappings = ScoresByRank::entries(&db).limit(10).query()?;
889
    /// assert!(mappings.len() <= 10);
890
    /// # Ok(())
891
    /// # }
892
    /// ```
893
3
    pub const fn limit(mut self, maximum_results: u32) -> Self {
894
3
        self.limit = Some(maximum_results);
895
3
        self
896
3
    }
897

            
898
    /// Executes the query and retrieves the results.
899
    ///
900
    /// ```rust
901
    /// # bonsaidb_core::__doctest_prelude!();
902
    /// # use bonsaidb_core::connection::Connection;
903
    /// # fn test_fn<C: Connection>(db: C) -> Result<(), Error> {
904
    /// // score is an f32 in this example
905
    /// for mapping in ScoresByRank::entries(&db).query()? {
906
    ///     println!("Rank {} has a score of {:3}", mapping.key, mapping.value);
907
    /// }
908
    /// # Ok(())
909
    /// # }
910
    /// ```
911
23674
    pub fn query(self) -> Result<ViewMappingsCurrent<V>, Error> {
912
23674
        self.connection
913
23674
            .query::<V, Key>(self.key, self.sort, self.limit, self.access_policy)
914
23674
    }
915

            
916
    /// Executes the query and retrieves the results with the associated [`Document`s](crate::document::OwnedDocument).
917
    ///
918
    /// ```rust
919
    /// # bonsaidb_core::__doctest_prelude!();
920
    /// # use bonsaidb_core::connection::Connection;
921
    /// # fn test_fn<C: Connection>(db: C) -> Result<(), Error> {
922
    /// for mapping in &ScoresByRank::entries(&db)
923
    ///     .with_key_range(42..=44)
924
    ///     .query_with_docs()?
925
    /// {
926
    ///     println!(
927
    ///         "Mapping from #{} with rank: {} and score: {}. Document bytes: {:?}",
928
    ///         mapping.document.header.id, mapping.key, mapping.value, mapping.document.contents
929
    ///     );
930
    /// }
931
    /// # Ok(())
932
    /// # }
933
    /// ```
934
673
    pub fn query_with_docs(self) -> Result<MappedDocuments<OwnedDocument, V>, Error> {
935
673
        self.connection.query_with_docs::<V, Key>(
936
673
            self.key,
937
673
            self.sort,
938
673
            self.limit,
939
673
            self.access_policy,
940
673
        )
941
673
    }
942

            
943
    /// Executes the query and retrieves the results with the associated [`CollectionDocument`s](crate::document::CollectionDocument).
944
    ///
945
    /// ```rust
946
    /// # bonsaidb_core::__doctest_prelude!();
947
    /// # use bonsaidb_core::connection::Connection;
948
    /// # fn test_fn<C: Connection>(db: C) -> Result<(), Error> {
949
    /// for mapping in &ScoresByRank::entries(&db)
950
    ///     .with_key_range(42..=44)
951
    ///     .query_with_collection_docs()?
952
    /// {
953
    ///     println!(
954
    ///         "Mapping from #{} with rank: {} and score: {}. Deserialized Contents: {:?}",
955
    ///         mapping.document.header.id, mapping.key, mapping.value, mapping.document.contents
956
    ///     );
957
    /// }
958
    /// # Ok(())
959
    /// # }
960
    /// ```
961
25
    pub fn query_with_collection_docs(
962
25
        self,
963
25
    ) -> Result<MappedDocuments<CollectionDocument<V::Collection>, V>, Error>
964
25
    where
965
25
        V::Collection: SerializedCollection,
966
25
        <V::Collection as SerializedCollection>::Contents: std::fmt::Debug,
967
25
    {
968
25
        self.connection.query_with_collection_docs::<V, Key>(
969
25
            self.key,
970
25
            self.sort,
971
25
            self.limit,
972
25
            self.access_policy,
973
25
        )
974
25
    }
975

            
976
    /// Executes a reduce over the results of the query
977
    ///
978
    /// ```rust
979
    /// # bonsaidb_core::__doctest_prelude!();
980
    /// # use bonsaidb_core::connection::Connection;
981
    /// # fn test_fn<C: Connection>(db: C) -> Result<(), Error> {
982
    /// // score is an f32 in this example
983
    /// let score = ScoresByRank::entries(&db).reduce()?;
984
    /// println!("Average score: {:3}", score);
985
    /// # Ok(())
986
    /// # }
987
    /// ```
988
42
    pub fn reduce(self) -> Result<V::Value, Error> {
989
42
        self.connection
990
42
            .reduce::<V, Key>(self.key, self.access_policy)
991
42
    }
992

            
993
    /// Executes a reduce over the results of the query, grouping by key.
994
    ///
995
    /// ```rust
996
    /// # bonsaidb_core::__doctest_prelude!();
997
    /// # use bonsaidb_core::connection::Connection;
998
    /// # fn test_fn<C: Connection>(db: C) -> Result<(), Error> {
999
    /// // score is an f32 in this example
    /// for mapping in ScoresByRank::entries(&db).reduce_grouped()? {
    ///     println!(
    ///         "Rank {} has an average score of {:3}",
    ///         mapping.key, mapping.value
    ///     );
    /// }
    /// # Ok(())
    /// # }
    /// ```
18
    pub fn reduce_grouped(self) -> Result<GroupedReductions<V>, Error> {
18
        self.connection
18
            .reduce_grouped::<V, Key>(self.key, self.access_policy)
18
    }

            
    /// Deletes all of the associated documents that match this view query.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::Connection;
    /// # fn test_fn<C: Connection>(db: C) -> Result<(), Error> {
    /// ScoresByRank::entries(&db).delete_docs()?;
    /// # Ok(())
    /// # }
    /// ```
9
    pub fn delete_docs(self) -> Result<u64, Error> {
9
        self.connection
9
            .delete_docs::<V, Key>(self.key, self.access_policy)
9
    }
}

            
/// This type is the result of `reduce_grouped()`. It is a list of all matching
/// keys and the reduced value of all mapped entries for that key.
pub type GroupedReductions<V> =
    Vec<MappedValue<<V as schema::View>::Key, <V as schema::View>::Value>>;

            
/// A connection to a database's [`Schema`](schema::Schema), giving access to
/// [`Collection`s](crate::schema::Collection) and
/// [`Views`s](crate::schema::View). All functions on this trait are safe to use
/// in an asynchronous context.
#[async_trait]
pub trait AsyncConnection: AsyncLowLevelConnection + Sized + Send + Sync {
    /// The [`AsyncStorageConnection`] type that is paired with this type.
    type Storage: AsyncStorageConnection<Database = Self>;

            
    /// Returns the [`StorageConnection`] implementor that this database belongs
    /// to.
    fn storage(&self) -> Self::Storage;

            
    /// Accesses a collection for the connected [`Schema`](schema::Schema).
6182
    fn collection<C: schema::Collection>(&self) -> AsyncCollection<'_, Self, C> {
6182
        AsyncCollection::new(self)
6182
    }

            
    /// Accesses a [`schema::View`] from this connection.
29123
    fn view<V: schema::SerializedView>(&'_ self) -> AsyncView<'_, Self, V, V::Key> {
29123
        AsyncView::new(self)
29123
    }

            
    /// Lists [executed transactions](transaction::Executed) from this [`Schema`](schema::Schema). By default, a maximum of
    /// 1000 entries will be returned, but that limit can be overridden by
    /// setting `result_limit`. A hard limit of 100,000 results will be
    /// returned. To begin listing after another known `transaction_id`, pass
    /// `transaction_id + 1` into `starting_id`.
    async fn list_executed_transactions(
        &self,
        starting_id: Option<u64>,
        result_limit: Option<u32>,
    ) -> Result<Vec<transaction::Executed>, Error>;

            
    /// Fetches the last transaction id that has been committed, if any.
    async fn last_transaction_id(&self) -> Result<Option<u64>, Error>;

            
    /// Compacts the entire database to reclaim unused disk space.
    ///
    /// This process is done by writing data to a new file and swapping the file
    /// once the process completes. This ensures that if a hardware failure,
    /// power outage, or crash occurs that the original collection data is left
    /// untouched.
    ///
    /// ## Errors
    ///
    /// * [`Error::Other`]: an error occurred while compacting the database.
    async fn compact(&self) -> Result<(), crate::Error>;

            
    /// Compacts the collection to reclaim unused disk space.
    ///
    /// This process is done by writing data to a new file and swapping the file
    /// once the process completes. This ensures that if a hardware failure,
    /// power outage, or crash occurs that the original collection data is left
    /// untouched.
    ///
    /// ## Errors
    ///
    /// * [`Error::CollectionNotFound`]: database `name` does not exist.
    /// * [`Error::Other`]: an error occurred while compacting the database.
2
    async fn compact_collection<C: schema::Collection>(&self) -> Result<(), crate::Error> {
2
        self.compact_collection_by_name(C::collection_name()).await
4
    }

            
    /// Compacts the key value store to reclaim unused disk space.
    ///
    /// This process is done by writing data to a new file and swapping the file
    /// once the process completes. This ensures that if a hardware failure,
    /// power outage, or crash occurs that the original collection data is left
    /// untouched.
    ///
    /// ## Errors
    ///
    /// * [`Error::Other`]: an error occurred while compacting the database.
    async fn compact_key_value_store(&self) -> Result<(), crate::Error>;
}

            
/// Interacts with a collection over a `Connection`.
///
/// These examples in this type use this basic collection definition:
///
/// ```rust
/// use bonsaidb_core::schema::Collection;
/// use bonsaidb_core::Error;
/// use serde::{Deserialize, Serialize};
///
/// #[derive(Debug, Serialize, Deserialize, Default, Collection)]
/// #[collection(name = "MyCollection")]
/// # #[collection(core = bonsaidb_core)]
/// pub struct MyCollection {
///     pub rank: u32,
///     pub score: f32,
/// }
/// ```
pub struct AsyncCollection<'a, Cn, Cl> {
    connection: &'a Cn,
    _phantom: PhantomData<Cl>, /* allows for extension traits to be written for collections of specific types */
}

            
impl<'a, Cn, Cl> Clone for AsyncCollection<'a, Cn, Cl> {
    fn clone(&self) -> Self {
        Self {
            connection: self.connection,
            _phantom: PhantomData,
        }
    }
}

            
impl<'a, Cn, Cl> AsyncCollection<'a, Cn, Cl>
where
    Cn: AsyncConnection,
    Cl: schema::Collection,
{
    /// Creates a new instance using `connection`.
6182
    fn new(connection: &'a Cn) -> Self {
6182
        Self {
6182
            connection,
6182
            _phantom: PhantomData,
6182
        }
6182
    }

            
    /// Adds a new `Document<Cl>` with the contents `item`.
    ///
    /// ## Automatic ID Assignment
    ///
    /// This function calls [`SerializedCollection::natural_id()`] to try to
    /// retrieve a primary key value from `item`. If an id is returned, the item
    /// is inserted with that id. If an id is not returned, an id will be
    /// automatically assigned, if possible, by the storage backend, which uses the [`Key`]
    /// trait to assign ids.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: &C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// let inserted_header = db
    ///     .collection::<MyCollection>()
    ///     .push(&MyCollection::default())
    ///     .await?;
    /// println!(
    ///     "Inserted id {} with revision {}",
    ///     inserted_header.id, inserted_header.revision
    /// );
    /// # Ok(())
    /// # })
    /// # }
    /// ```
9120
    pub async fn push(
9120
        &self,
9120
        item: &<Cl as SerializedCollection>::Contents,
9120
    ) -> Result<CollectionHeader<Cl::PrimaryKey>, crate::Error>
9120
    where
9120
        Cl: schema::SerializedCollection,
9120
    {
9120
        let contents = Cl::serialize(item)?;
9120
        if let Some(natural_id) = Cl::natural_id(item) {
            self.insert_bytes(&natural_id, contents).await
        } else {
16099
            self.push_bytes(contents).await
        }
9120
    }

            
    /// Adds a new `Document<Cl>` with the `contents`.
    ///
    /// ## Automatic ID Assignment
    ///
    /// An id will be automatically assigned, if possible, by the storage backend, which uses
    /// the [`Key`] trait to assign ids.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: &C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// let inserted_header = db.collection::<MyCollection>().push_bytes(vec![]).await?;
    /// println!(
    ///     "Inserted id {} with revision {}",
    ///     inserted_header.id, inserted_header.revision
    /// );
    /// # Ok(())
    /// # })
    /// # }
    /// ```
9120
    pub async fn push_bytes<B: Into<Bytes> + Send>(
9120
        &self,
9120
        contents: B,
9120
    ) -> Result<CollectionHeader<Cl::PrimaryKey>, crate::Error> {
9120
        self.connection
9120
            .insert::<Cl, _, B>(Option::<&Cl::PrimaryKey>::None, contents)
16096
            .await
9120
    }

            
    /// Adds a new `Document<Cl>` with the given `id` and contents `item`.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: &C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// let inserted_header = db
    ///     .collection::<MyCollection>()
    ///     .insert(&42, &MyCollection::default())
    ///     .await?;
    /// println!(
    ///     "Inserted id {} with revision {}",
    ///     inserted_header.id, inserted_header.revision
    /// );
    /// # Ok(())
    /// # })
    /// # }
    /// ```
1027
    pub async fn insert<PrimaryKey>(
1027
        &self,
1027
        id: &PrimaryKey,
1027
        item: &<Cl as SerializedCollection>::Contents,
1027
    ) -> Result<CollectionHeader<Cl::PrimaryKey>, crate::Error>
1027
    where
1027
        Cl: schema::SerializedCollection,
1027
        PrimaryKey: KeyEncoding<Cl::PrimaryKey> + ?Sized,
1027
    {
1027
        let contents = Cl::serialize(item)?;
5075
        self.connection.insert::<Cl, _, _>(Some(id), contents).await
1027
    }

            
    /// Adds a new `Document<Cl>` with the the given `id` and `contents`.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: &C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// let inserted_header = db
    ///     .collection::<MyCollection>()
    ///     .insert_bytes(&42, vec![])
    ///     .await?;
    /// println!(
    ///     "Inserted id {} with revision {}",
    ///     inserted_header.id, inserted_header.revision
    /// );
    /// # Ok(())
    /// # })
    /// # }
    /// ```
    pub async fn insert_bytes<PrimaryKey, B: Into<Bytes> + Send>(
        &self,
        id: &PrimaryKey,
        contents: B,
    ) -> Result<CollectionHeader<Cl::PrimaryKey>, crate::Error>
    where
        PrimaryKey: KeyEncoding<Cl::PrimaryKey> + ?Sized,
    {
        self.connection.insert::<Cl, _, B>(Some(id), contents).await
    }

            
    /// Updates an existing document. Upon success, `doc.revision` will be
    /// updated with the new revision.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: &C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// if let Some(mut document) = db.collection::<MyCollection>().get(&42).await? {
    ///     // modify the document
    ///     db.collection::<MyCollection>().update(&mut document);
    ///     println!("Updated revision: {:?}", document.header.revision);
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
    pub async fn update<D: Document<Cl> + Send + Sync>(&self, doc: &mut D) -> Result<(), Error> {
        self.connection.update::<Cl, D>(doc).await
    }

            
    /// Overwrites an existing document, or inserts a new document. Upon success,
    /// `doc.revision` will be updated with the new revision information.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: &C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// if let Some(mut document) = db.collection::<MyCollection>().get(&42).await? {
    ///     // modify the document
    ///     db.collection::<MyCollection>().overwrite(&mut document);
    ///     println!("Updated revision: {:?}", document.header.revision);
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
5
    pub async fn overwrite<D: Document<Cl> + Send + Sync>(&self, doc: &mut D) -> Result<(), Error> {
5
        let contents = doc.bytes()?;
        doc.set_collection_header(
5
            self.connection
5
                .overwrite::<Cl, _>(doc.id(), contents)
5
                .await?,
        )
5
    }

            
    /// Retrieves a `Document<Cl>` with `id` from the connection.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: &C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// if let Some(doc) = db.collection::<MyCollection>().get(&42).await? {
    ///     println!(
    ///         "Retrieved bytes {:?} with revision {}",
    ///         doc.contents, doc.header.revision
    ///     );
    ///     let deserialized = MyCollection::document_contents(&doc)?;
    ///     println!("Deserialized contents: {:?}", deserialized);
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
1543
    pub async fn get<PrimaryKey>(&self, id: &PrimaryKey) -> Result<Option<OwnedDocument>, Error>
1543
    where
1543
        PrimaryKey: KeyEncoding<Cl::PrimaryKey> + ?Sized,
1543
    {
5101
        self.connection.get::<Cl, _>(id).await
1543
    }

            
    /// Retrieves all documents matching `ids`. Documents that are not found
    /// are not returned, but no error will be generated.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: &C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// for doc in db
    ///     .collection::<MyCollection>()
    ///     .get_multiple(&[42, 43])
    ///     .await?
    /// {
    ///     println!("Retrieved #{} with bytes {:?}", doc.header.id, doc.contents);
    ///     let deserialized = MyCollection::document_contents(&doc)?;
    ///     println!("Deserialized contents: {:?}", deserialized);
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
28
    pub async fn get_multiple<'id, DocumentIds, PrimaryKey, I>(
28
        &self,
28
        ids: DocumentIds,
28
    ) -> Result<Vec<OwnedDocument>, Error>
28
    where
28
        DocumentIds: IntoIterator<Item = &'id PrimaryKey, IntoIter = I> + Send + Sync,
28
        I: Iterator<Item = &'id PrimaryKey> + Send + Sync,
28
        PrimaryKey: KeyEncoding<Cl::PrimaryKey> + 'id + ?Sized,
28
    {
28
        self.connection.get_multiple::<Cl, _, _, _>(ids).await
28
    }

            
    /// Retrieves all documents matching the range of `ids`.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: &C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// for doc in db
    ///     .collection::<MyCollection>()
    ///     .list(42..)
    ///     .descending()
    ///     .limit(20)
    ///     .await?
    /// {
    ///     println!("Retrieved #{} with bytes {:?}", doc.header.id, doc.contents);
    ///     let deserialized = MyCollection::document_contents(&doc)?;
    ///     println!("Deserialized contents: {:?}", deserialized);
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
    pub fn list<PrimaryKey, R>(&'a self, ids: R) -> AsyncList<'a, Cn, Cl, PrimaryKey>
    where
        R: Into<RangeRef<'a, Cl::PrimaryKey, PrimaryKey>>,
        PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized,
        Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
    {
        AsyncList::new(MaybeOwned::Borrowed(self), ids.into())
    }

            
    /// Retrieves all documents with ids that start with `prefix`.
    ///
    /// ```rust
    /// use bonsaidb_core::connection::AsyncConnection;
    /// use bonsaidb_core::document::OwnedDocument;
    /// use bonsaidb_core::schema::{Collection, Schematic, SerializedCollection};
    /// use bonsaidb_core::Error;
    /// use serde::{Deserialize, Serialize};
    ///
    /// #[derive(Debug, Serialize, Deserialize, Default, Collection)]
    /// #[collection(name = "MyCollection", primary_key = String)]
    /// # #[collection(core = bonsaidb_core)]
    /// pub struct MyCollection;
    ///
    /// async fn starts_with_a<C: AsyncConnection>(db: &C) -> Result<Vec<OwnedDocument>, Error> {
    ///     db.collection::<MyCollection>().list_with_prefix("a").await
    /// }
    /// ```
    pub fn list_with_prefix<PrimaryKey>(
        &'a self,
        prefix: &'a PrimaryKey,
    ) -> AsyncList<'a, Cn, Cl, PrimaryKey>
    where
        PrimaryKey:
            IntoPrefixRange<'a, Cl::PrimaryKey> + KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized,
        Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
    {
        AsyncList::new(MaybeOwned::Borrowed(self), prefix.to_prefix_range())
    }

            
    /// Retrieves all documents.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: &C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// for doc in db.collection::<MyCollection>().all().await? {
    ///     println!("Retrieved #{} with bytes {:?}", doc.header.id, doc.contents);
    ///     let deserialized = MyCollection::document_contents(&doc)?;
    ///     println!("Deserialized contents: {:?}", deserialized);
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
    pub fn all(&'a self) -> AsyncList<'a, Cn, Cl, Cl::PrimaryKey> {
        AsyncList::new(MaybeOwned::Borrowed(self), RangeRef::from(..))
    }

            
    /// Removes a `Document` from the database.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: &C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// if let Some(doc) = db.collection::<MyCollection>().get(&42).await? {
    ///     db.collection::<MyCollection>().delete(&doc).await?;
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
1002
    pub async fn delete<H: HasHeader + Send + Sync>(&self, doc: &H) -> Result<(), Error> {
3647
        self.connection.delete::<Cl, H>(doc).await
1002
    }
}

            
pub(crate) struct AsyncListBuilder<'a, Cn, Cl, PrimaryKey>
where
    Cl: schema::Collection,
    PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized,
    Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
{
    collection: MaybeOwned<'a, AsyncCollection<'a, Cn, Cl>>,
    range: RangeRef<'a, Cl::PrimaryKey, PrimaryKey>,
    sort: Sort,
    limit: Option<u32>,
}

            
/// A value that may be owned or not. Similar to [`std::borrow::Cow`] but does
/// not require `Clone`.
#[derive(Debug)]
pub enum MaybeOwned<'a, TOwned, TBorrowed: ?Sized = TOwned> {
    /// An owned value.
    Owned(TOwned),
    /// A borrowed value.
    Borrowed(&'a TBorrowed),
}

            
impl<'a, TOwned, TBorrowed> Clone for MaybeOwned<'a, TOwned, TBorrowed>
where
    TOwned: Clone,
    TBorrowed: ?Sized,
{
    fn clone(&self) -> Self {
        match self {
            Self::Owned(value) => Self::Owned(value.clone()),
            Self::Borrowed(value) => Self::Borrowed(value),
        }
    }
}

            
impl<'a, TOwned, TBorrowed> Deref for MaybeOwned<'a, TOwned, TBorrowed>
where
    TOwned: Borrow<TBorrowed>,
    TBorrowed: ?Sized,
{
    type Target = TBorrowed;

            
392812
    fn deref(&self) -> &TBorrowed {
392812
        self.borrow()
392812
    }
}

            
impl<'a, TOwned, TBorrowed> Borrow<TBorrowed> for MaybeOwned<'a, TOwned, TBorrowed>
where
    TOwned: Borrow<TBorrowed>,
    TBorrowed: ?Sized,
{
392812
    fn borrow(&self) -> &TBorrowed {
392812
        match self {
236
            MaybeOwned::Owned(value) => value.borrow(),
392576
            MaybeOwned::Borrowed(value) => value,
        }
392812
    }
}

            
impl<'a, TOwned, TBorrowed> PartialEq for MaybeOwned<'a, TOwned, TBorrowed>
where
    TOwned: Borrow<TBorrowed>,
    TBorrowed: PartialEq + ?Sized,
{
    fn eq(&self, other: &Self) -> bool {
        <Self as Borrow<TBorrowed>>::borrow(self).eq(other.borrow())
    }
}

            
impl<'a, TOwned, TBorrowed> PartialOrd for MaybeOwned<'a, TOwned, TBorrowed>
where
    TOwned: Borrow<TBorrowed>,
    TBorrowed: PartialOrd + ?Sized,
{
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        <Self as Borrow<TBorrowed>>::borrow(self).partial_cmp(other.borrow())
    }
}

            
impl<'a, TOwned, TBorrowed> PartialEq<TBorrowed> for MaybeOwned<'a, TOwned, TBorrowed>
where
    TOwned: Borrow<TBorrowed>,
    TBorrowed: PartialEq + ?Sized,
{
    fn eq(&self, other: &TBorrowed) -> bool {
        <Self as Borrow<TBorrowed>>::borrow(self).eq(other)
    }
}

            
impl<'a, TOwned, TBorrowed> PartialOrd<TBorrowed> for MaybeOwned<'a, TOwned, TBorrowed>
where
    TOwned: Borrow<TBorrowed>,
    TBorrowed: PartialOrd + ?Sized,
{
    fn partial_cmp(&self, other: &TBorrowed) -> Option<std::cmp::Ordering> {
        <Self as Borrow<TBorrowed>>::borrow(self).partial_cmp(other)
    }
}

            
pub(crate) enum ListState<'a, Cn, Cl, PrimaryKey>
where
    Cl: schema::Collection,
    PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized,
    Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
{
    Pending(Option<AsyncListBuilder<'a, Cn, Cl, PrimaryKey>>),
    Executing(BoxFuture<'a, Result<Vec<OwnedDocument>, Error>>),
}

            
/// Retrieves a list of documents from a collection, when awaited. This
/// structure also offers functions to customize the options for the operation.
#[must_use]
pub struct AsyncList<'a, Cn, Cl, PrimaryKey>
where
    Cl: schema::Collection,
    PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized,
    Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
{
    state: ListState<'a, Cn, Cl, PrimaryKey>,
}

            
impl<'a, Cn, Cl, PrimaryKey> AsyncList<'a, Cn, Cl, PrimaryKey>
where
    Cl: schema::Collection,
    Cn: AsyncConnection,
    PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized,
    Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
{
35
    pub(crate) const fn new(
35
        collection: MaybeOwned<'a, AsyncCollection<'a, Cn, Cl>>,
35
        range: RangeRef<'a, Cl::PrimaryKey, PrimaryKey>,
35
    ) -> Self {
35
        Self {
35
            state: ListState::Pending(Some(AsyncListBuilder {
35
                collection,
35
                range,
35
                sort: Sort::Ascending,
35
                limit: None,
35
            })),
35
        }
35
    }

            
10
    fn builder(&mut self) -> &mut AsyncListBuilder<'a, Cn, Cl, PrimaryKey> {
10
        if let ListState::Pending(Some(builder)) = &mut self.state {
10
            builder
        } else {
            unreachable!("Attempted to use after retrieving the result")
        }
10
    }

            
    /// Lists documents by id in ascending order.
    pub fn ascending(mut self) -> Self {
        self.builder().sort = Sort::Ascending;
        self
    }

            
    /// Lists documents by id in descending order.
5
    pub fn descending(mut self) -> Self {
5
        self.builder().sort = Sort::Descending;
5
        self
5
    }

            
    /// Sets the maximum number of results to return.
5
    pub fn limit(mut self, maximum_results: u32) -> Self {
5
        self.builder().limit = Some(maximum_results);
5
        self
5
    }

            
    /// Returns the list of headers for documents contained within the range.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: &C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// println!(
    ///     "Number of documents with id 42 or larger: {:?}",
    ///     db.collection::<MyCollection>().list(42..).headers().await?
    /// );
    /// println!(
    ///     "Number of documents in MyCollection: {:?}",
    ///     db.collection::<MyCollection>().all().headers().await?
    /// );
    /// # Ok(())
    /// # })
    /// # }
    /// ```
5
    pub async fn headers(self) -> Result<Vec<Header>, Error> {
5
        match self.state {
            ListState::Pending(Some(AsyncListBuilder {
5
                collection,
5
                range,
5
                sort,
5
                limit,
5
                ..
5
            })) => {
5
                collection
5
                    .connection
5
                    .list_headers::<Cl, _, _>(range, sort, limit)
5
                    .await
            }
            _ => unreachable!("Attempted to use after retrieving the result"),
        }
5
    }

            
    /// Returns the number of documents contained within the range.
    ///
    /// Order and limit are ignored if they were set.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: &C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// println!(
    ///     "Number of documents with id 42 or larger: {}",
    ///     db.collection::<MyCollection>().list(42..).count().await?
    /// );
    /// println!(
    ///     "Number of documents in MyCollection: {}",
    ///     db.collection::<MyCollection>().all().count().await?
    /// );
    /// # Ok(())
    /// # })
    /// # }
    /// ```
10
    pub async fn count(self) -> Result<u64, Error> {
10
        match self.state {
            ListState::Pending(Some(AsyncListBuilder {
10
                collection, range, ..
10
            })) => collection.connection.count::<Cl, _, _>(range).await,
            _ => unreachable!("Attempted to use after retrieving the result"),
        }
10
    }
}

            
#[allow(clippy::type_repetition_in_bounds)]
impl<'a, Cn, Cl, PrimaryKey> Future for AsyncList<'a, Cn, Cl, PrimaryKey>
where
    Cn: AsyncConnection,
    Cl: schema::Collection + Unpin,
    PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized + Unpin,
    Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey> + Unpin,
{
    type Output = Result<Vec<OwnedDocument>, Error>;

            
60
    fn poll(
60
        mut self: std::pin::Pin<&mut Self>,
60
        cx: &mut std::task::Context<'_>,
60
    ) -> std::task::Poll<Self::Output> {
60
        match &mut self.state {
40
            ListState::Executing(future) => future.as_mut().poll(cx),
20
            ListState::Pending(builder) => {
20
                let AsyncListBuilder {
20
                    collection,
20
                    range,
20
                    sort,
20
                    limit,
20
                } = builder.take().unwrap();
20

            
20
                let future = async move {
20
                    collection
20
                        .connection
20
                        .list::<Cl, _, _>(range, sort, limit)
20
                        .await
20
                }
20
                .boxed();
20

            
20
                self.state = ListState::Executing(future);
20
                self.poll(cx)
            }
        }
60
    }
}

            
/// Parameters to query a [`schema::View`].
///
/// The examples for this type use this view definition:
///
/// ```rust
/// # mod collection {
/// # bonsaidb_core::__doctest_prelude!();
/// # }
/// # use collection::MyCollection;
/// use bonsaidb_core::define_basic_unique_mapped_view;
/// use bonsaidb_core::document::{CollectionDocument, Emit};
/// use bonsaidb_core::schema::{
///     CollectionMapReduce, DefaultViewSerialization, Name, ReduceResult, View, ViewMapResult,
///     ViewMappedValue, ViewSchema,
/// };
///
/// #[derive(Debug, Clone, View, ViewSchema)]
/// #[view(collection = MyCollection, key = u32, value = f32, name = "scores-by-rank")]
/// # #[view(core = bonsaidb_core)]
/// # #[view_schema(core = bonsaidb_core)]
/// pub struct ScoresByRank;
///
/// impl CollectionMapReduce for ScoresByRank {
///     fn map<'doc>(
///         &self,
///         document: CollectionDocument<<Self::View as View>::Collection>,
///     ) -> ViewMapResult<'doc, Self::View> {
///         document
///             .header
///             .emit_key_and_value(document.contents.rank, document.contents.score)
///     }
///
///     fn reduce(
///         &self,
///         mappings: &[ViewMappedValue<'_, Self::View>],
///         rereduce: bool,
///     ) -> ReduceResult<Self::View> {
///         if mappings.is_empty() {
///             Ok(0.)
///         } else {
///             Ok(mappings.iter().map(|map| map.value).sum::<f32>() / mappings.len() as f32)
///         }
///     }
/// }
/// ```
#[must_use]
pub struct AsyncView<'a, Cn, V: schema::SerializedView, Key>
where
    V::Key: Borrow<Key> + PartialEq<Key>,
    Key: PartialEq + ?Sized,
{
    connection: &'a Cn,

            
    /// Key filtering criteria.
    pub key: Option<QueryKey<'a, V::Key, Key>>,

            
    /// The view's data access policy. The default value is [`AccessPolicy::UpdateBefore`].
    pub access_policy: AccessPolicy,

            
    /// The sort order of the query.
    pub sort: Sort,

            
    /// The maximum number of results to return.
    pub limit: Option<u32>,

            
    _view: PhantomData<V>,
}

            
impl<'a, Cn, V, Key> AsyncView<'a, Cn, V, Key>
where
    V: schema::SerializedView,
    Cn: AsyncConnection,
    Key: KeyEncoding<V::Key> + PartialEq + ?Sized,
    V::Key: Borrow<Key> + PartialEq<Key>,
{
29123
    const fn new(connection: &'a Cn) -> Self {
29123
        Self {
29123
            connection,
29123
            key: None,
29123
            access_policy: AccessPolicy::UpdateBefore,
29123
            sort: Sort::Ascending,
29123
            limit: None,
29123
            _view: PhantomData,
29123
        }
29123
    }

            
    /// Filters for entries in the view with `key`.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// // score is an f32 in this example
    /// for mapping in ScoresByRank::entries_async(&db)
    ///     .with_key(&42)
    ///     .query()
    ///     .await?
    /// {
    ///     assert_eq!(mapping.key, 42);
    ///     println!("Rank {} has a score of {:3}", mapping.key, mapping.value);
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
    #[allow(clippy::missing_const_for_fn)] // false positive, destructors
29029
    pub fn with_key<K>(self, key: &'a K) -> AsyncView<'a, Cn, V, K>
29029
    where
29029
        K: KeyEncoding<V::Key> + PartialEq + ?Sized,
29029
        V::Key: Borrow<K> + PartialEq<K>,
29029
    {
29029
        AsyncView {
29029
            connection: self.connection,
29029
            key: Some(QueryKey::Matches(MaybeOwned::Borrowed(key))),
29029
            access_policy: self.access_policy,
29029
            sort: self.sort,
29029
            limit: self.limit,
29029
            _view: PhantomData,
29029
        }
29029
    }

            
    /// Filters for entries in the view with `keys`.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// // score is an f32 in this example
    /// for mapping in ScoresByRank::entries_async(&db)
    ///     .with_keys(&[42, 43])
    ///     .query()
    ///     .await?
    /// {
    ///     println!("Rank {} has a score of {:3}", mapping.key, mapping.value);
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
16
    pub fn with_keys<K, IntoIter: IntoIterator<Item = &'a K>>(
16
        self,
16
        keys: IntoIter,
16
    ) -> AsyncView<'a, Cn, V, K>
16
    where
16
        K: PartialEq + ?Sized,
16
        V::Key: Borrow<K> + PartialEq<K>,
16
    {
16
        AsyncView {
16
            connection: self.connection,
16
            key: Some(QueryKey::Multiple(
16
                keys.into_iter().map(MaybeOwned::Borrowed).collect(),
16
            )),
16
            access_policy: self.access_policy,
16
            sort: self.sort,
16
            limit: self.limit,
16
            _view: PhantomData,
16
        }
16
    }

            
    /// Filters for entries in the view with the range `keys`.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// // score is an f32 in this example
    /// for mapping in ScoresByRank::entries_async(&db)
    ///     .with_key_range(42..)
    ///     .query()
    ///     .await?
    /// {
    ///     assert!(mapping.key >= 42);
    ///     println!("Rank {} has a score of {:3}", mapping.key, mapping.value);
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
11
    pub fn with_key_range<K, R: Into<RangeRef<'a, V::Key, K>>>(
11
        self,
11
        range: R,
11
    ) -> AsyncView<'a, Cn, V, K>
11
    where
11
        K: KeyEncoding<V::Key> + PartialEq + ?Sized,
11
        V::Key: Borrow<K> + PartialEq<K>,
11
    {
11
        AsyncView {
11
            connection: self.connection,
11
            key: Some(QueryKey::Range(range.into())),
11
            access_policy: self.access_policy,
11
            sort: self.sort,
11
            limit: self.limit,
11
            _view: PhantomData,
11
        }
11
    }

            
    /// Filters for entries in the view with keys that begin with `prefix`.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// #[derive(View, Debug, Clone)]
    /// #[view(name = "by-name", key = String, collection = MyCollection)]
    /// # #[view(core = bonsaidb_core)]
    /// struct ByName;
    ///
    /// // score is an f32 in this example
    /// for mapping in ByName::entries_async(&db)
    ///     .with_key_prefix("a")
    ///     .query()
    ///     .await?
    /// {
    ///     assert!(mapping.key.starts_with("a"));
    ///     println!("{} in document {:?}", mapping.key, mapping.source);
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
13
    pub fn with_key_prefix<K>(self, prefix: &'a K) -> AsyncView<'a, Cn, V, K>
13
    where
13
        K: KeyEncoding<V::Key> + IntoPrefixRange<'a, V::Key> + PartialEq + ?Sized,
13
        V::Key: Borrow<K> + PartialEq<K>,
13
    {
13
        AsyncView {
13
            connection: self.connection,
13
            key: Some(QueryKey::Range(prefix.to_prefix_range())),
13
            access_policy: self.access_policy,
13
            sort: self.sort,
13
            limit: self.limit,
13
            _view: PhantomData,
13
        }
13
    }

            
    /// Sets the access policy for queries.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// // score is an f32 in this example
    /// for mapping in ScoresByRank::entries_async(&db)
    ///     .with_access_policy(AccessPolicy::UpdateAfter)
    ///     .query()
    ///     .await?
    /// {
    ///     println!("Rank {} has a score of {:3}", mapping.key, mapping.value);
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
18687
    pub const fn with_access_policy(mut self, policy: AccessPolicy) -> Self {
18687
        self.access_policy = policy;
18687
        self
18687
    }

            
    /// Returns the matching mappings in ascending key order. This is the
    /// default sorting behavior.
    ///
    /// When more than one mapping exists for a single key, all matching
    /// mappings are returned as a unique entry. The resulting mappings are
    /// sorted only by the key, and as such, the order of mappings with the same
    /// key is undefined.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// // score is an f32 in this example
    /// for mapping in ScoresByRank::entries_async(&db).ascending().query().await? {
    ///     println!("Rank {} has a score of {:3}", mapping.key, mapping.value);
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
    pub const fn ascending(mut self) -> Self {
        self.sort = Sort::Ascending;
        self
    }

            
    /// Returns the matching mappings in descending key order.
    ///
    /// When more than one mapping exists for a single key, all matching
    /// mappings are returned as a unique entry. The resulting mappings are
    /// sorted only by the key, and as such, the order of mappings with the same
    /// key is undefined.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// // score is an f32 in this example
    /// for mapping in ScoresByRank::entries_async(&db)
    ///     .descending()
    ///     .query()
    ///     .await?
    /// {
    ///     println!("Rank {} has a score of {:3}", mapping.key, mapping.value);
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
5
    pub const fn descending(mut self) -> Self {
5
        self.sort = Sort::Descending;
5
        self
5
    }

            
    /// Sets the maximum number of results to return.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// // score is an f32 in this example
    /// let mappings = ScoresByRank::entries_async(&db).limit(10).query().await?;
    /// assert!(mappings.len() <= 10);
    /// # Ok(())
    /// # })
    /// # }
    /// ```
5
    pub const fn limit(mut self, maximum_results: u32) -> Self {
5
        self.limit = Some(maximum_results);
5
        self
5
    }

            
    /// Executes the query and retrieves the results.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// // score is an f32 in this example
    /// for mapping in ScoresByRank::entries_async(&db).query().await? {
    ///     println!("Rank {} has a score of {:3}", mapping.key, mapping.value);
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
326
    pub async fn query(self) -> Result<ViewMappingsCurrent<V>, Error> {
326
        self.connection
326
            .query::<V, Key>(self.key, self.sort, self.limit, self.access_policy)
323
            .await
326
    }

            
    /// Executes the query and retrieves the results with the associated [`Document`s](crate::document::OwnedDocument).
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// for mapping in &ScoresByRank::entries_async(&db)
    ///     .with_key_range(42..=44)
    ///     .query_with_docs()
    ///     .await?
    /// {
    ///     println!(
    ///         "Mapping from #{} with rank: {} and score: {}. Document bytes: {:?}",
    ///         mapping.document.header.id, mapping.key, mapping.value, mapping.document.contents
    ///     );
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
9561
    pub async fn query_with_docs(self) -> Result<MappedDocuments<OwnedDocument, V>, Error> {
9561
        self.connection
9561
            .query_with_docs::<V, _>(self.key, self.sort, self.limit, self.access_policy)
17569
            .await
9561
    }

            
    /// Executes the query and retrieves the results with the associated [`CollectionDocument`s](crate::document::CollectionDocument).
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// for mapping in &ScoresByRank::entries_async(&db)
    ///     .with_key_range(42..=44)
    ///     .query_with_collection_docs()
    ///     .await?
    /// {
    ///     println!(
    ///         "Mapping from #{} with rank: {} and score: {}. Deserialized Contents: {:?}",
    ///         mapping.document.header.id, mapping.key, mapping.value, mapping.document.contents
    ///     );
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
117
    pub async fn query_with_collection_docs(
117
        self,
117
    ) -> Result<MappedDocuments<CollectionDocument<V::Collection>, V>, Error>
117
    where
117
        V::Collection: SerializedCollection,
117
        <V::Collection as SerializedCollection>::Contents: std::fmt::Debug,
117
    {
117
        self.connection
117
            .query_with_collection_docs::<V, _>(self.key, self.sort, self.limit, self.access_policy)
232
            .await
117
    }

            
    /// Executes a reduce over the results of the query
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// // score is an f32 in this example
    /// let score = ScoresByRank::entries_async(&db).reduce().await?;
    /// println!("Average score: {:3}", score);
    /// # Ok(())
    /// # })
    /// # }
    /// ```
19094
    pub async fn reduce(self) -> Result<V::Value, Error> {
19094
        self.connection
19094
            .reduce::<V, _>(self.key, self.access_policy)
17529
            .await
19094
    }

            
    /// Executes a reduce over the results of the query, grouping by key.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// // score is an f32 in this example
    /// for mapping in ScoresByRank::entries_async(&db).reduce_grouped().await? {
    ///     println!(
    ///         "Rank {} has an average score of {:3}",
    ///         mapping.key, mapping.value
    ///     );
    /// }
    /// # Ok(())
    /// # })
    /// # }
    /// ```
12
    pub async fn reduce_grouped(self) -> Result<Vec<MappedValue<V::Key, V::Value>>, Error> {
12
        self.connection
12
            .reduce_grouped::<V, _>(self.key, self.access_policy)
14
            .await
12
    }

            
    /// Deletes all of the associated documents that match this view query.
    ///
    /// ```rust
    /// # bonsaidb_core::__doctest_prelude!();
    /// # use bonsaidb_core::connection::AsyncConnection;
    /// # fn test_fn<C: AsyncConnection>(db: C) -> Result<(), Error> {
    /// # tokio::runtime::Runtime::new().unwrap().block_on(async {
    /// ScoresByRank::entries_async(&db).delete_docs().await?;
    /// # Ok(())
    /// # })
    /// # }
    /// ```
13
    pub async fn delete_docs(self) -> Result<u64, Error> {
13
        self.connection
13
            .delete_docs::<V, _>(self.key, self.access_policy)
13
            .await
13
    }
}

            
/// A sort order.
87148
#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
pub enum Sort {
    /// Sort ascending (A -> Z).
    Ascending,
    /// Sort descending (Z -> A).
    Descending,
}

            
/// Filters a [`View`] by key.
#[derive(Clone, Debug)]
pub enum QueryKey<'k, KOwned, KBorrowed = KOwned>
where
    KBorrowed: PartialEq + ?Sized,
    KOwned: Borrow<KBorrowed> + PartialEq<KBorrowed>,
{
    /// Matches all entries with the key provided.
    Matches(MaybeOwned<'k, KOwned, KBorrowed>),

            
    /// Matches all entires with keys in the range provided.
    Range(RangeRef<'k, KOwned, KBorrowed>),

            
    /// Matches all entries that have keys that are included in the set provided.
    Multiple(Vec<MaybeOwned<'k, KOwned, KBorrowed>>),
}

            
impl<'a, KOwned, KBorrowed> QueryKey<'a, KOwned, KBorrowed>
where
    KBorrowed: KeyEncoding<KOwned> + PartialEq + ?Sized,
    KOwned: for<'k> Key<'k> + Borrow<KBorrowed> + PartialEq<KBorrowed>,
{
    /// Converts this key to a serialized format using the [`Key`] trait.
392524
    pub fn serialized(&self) -> Result<SerializedQueryKey, Error> {
392524
        match self {
392414
            Self::Matches(key) => key
392414
                .as_ord_bytes()
392414
                .map_err(|err| Error::other("key serialization", err))
392414
                .map(|v| SerializedQueryKey::Matches(Bytes::from(v.to_vec()))),
82
            Self::Range(range) => Ok(SerializedQueryKey::Range(
82
                range
82
                    .as_ord_bytes()
82
                    .map_err(|err| Error::other("key serialization", err))?,
            )),
28
            Self::Multiple(keys) => {
28
                let keys = keys
28
                    .iter()
48
                    .map(|key| {
48
                        key.as_ord_bytes()
48
                            .map(|key| Bytes::from(key.to_vec()))
48
                            .map_err(|err| Error::other("key serialization", err))
48
                    })
28
                    .collect::<Result<Vec<_>, Error>>()?;

            
28
                Ok(SerializedQueryKey::Multiple(keys))
            }
        }
392524
    }
}

            
/// A [`QueryKey`] that has had its keys serialized.
258324
#[derive(Clone, Serialize, Deserialize, Debug)]
pub enum SerializedQueryKey {
    /// Matches all entries with the key provided.
    Matches(Bytes),

            
    /// Matches all entires with keys in the range provided.
    Range(Range<Bytes>),

            
    /// Matches all entries that have keys that are included in the set provided.
    Multiple(Vec<Bytes>),
}

            
impl SerializedQueryKey {
    /// Deserializes the bytes into `K` via the [`Key`] trait.
    pub fn deserialized<K: for<'k> Key<'k> + PartialEq>(
        &self,
    ) -> Result<QueryKey<'static, K>, Error> {
        match self {
            Self::Matches(key) => K::from_ord_bytes(ByteSource::Borrowed(key.as_ref()))
                .map_err(|err| Error::other("key serialization", err))
                .map(|key| QueryKey::Matches(MaybeOwned::Owned(key))),
            Self::Range(range) => Ok(QueryKey::Range(RangeRef::owned(
                range
                    .deserialize()
                    .map_err(|err| Error::other("key serialization", err))?,
            ))),
            Self::Multiple(keys) => {
                let keys = keys
                    .iter()
                    .map(|key| {
                        K::from_ord_bytes(ByteSource::Borrowed(key.as_ref()))
                            .map(MaybeOwned::Owned)
                            .map_err(|err| Error::other("key serialization", err))
                    })
                    .collect::<Result<Vec<_>, Error>>()?;

            
                Ok(QueryKey::Multiple(keys))
            }
        }
    }
}

            
/// A range type that can represent all `std` range types and be serialized.
///
/// This type implements conversion operations from all range types defined in
/// `std`.
571
#[derive(Serialize, Deserialize, Default, Debug, Copy, Clone, Eq, PartialEq)]
#[must_use]
pub struct Range<T> {
    /// The start of the range.
    pub start: Bound<T>,
    /// The end of the range.
    pub end: Bound<T>,
}

            
/// A range bound that can be serialized.
980
#[derive(Serialize, Deserialize, Debug, Copy, Clone, Eq, PartialEq)]
#[must_use]
pub enum Bound<T> {
    /// No bound.
    Unbounded,
    /// Bounded by the contained value (inclusive).
    Included(T),
    /// Bounded by the contained value (exclusive).
    Excluded(T),
}

            
impl<T> Default for Bound<T> {
8
    fn default() -> Self {
8
        Self::Unbounded
8
    }
}

            
impl<T> Range<T> {
    /// Sets the start bound of this range to [`Bound::Excluded`] with
    /// `excluded_start`. The range will represent values that are
    /// [`Ordering::Greater`](std::cmp::Ordering::Greater) than, but not
    /// including, `excluded_start`.
    #[allow(clippy::missing_const_for_fn)]
1
    pub fn after(mut self, excluded_start: T) -> Self {
1
        self.start = Bound::Excluded(excluded_start);
1
        self
1
    }

            
    /// Sets the start bound of this range to [`Bound::Included`] with
    /// `included_start`. The range will represent values that are
    /// [`Ordering::Greater`](std::cmp::Ordering::Greater) than or
    /// [`Ordering::Equal`](std::cmp::Ordering::Equal) to `included_start`.
    #[allow(clippy::missing_const_for_fn)]
1
    pub fn start_at(mut self, included_start: T) -> Self {
1
        self.start = Bound::Included(included_start);
1
        self
1
    }

            
    /// Sets the end bound of this range to [`Bound::Excluded`] with
    /// `excluded_end`. The range will represent values that are
    /// [`Ordering::Less`](std::cmp::Ordering::Less) than, but not including,
    /// `excluded_end`.
    #[allow(clippy::missing_const_for_fn)]
1
    pub fn before(mut self, excluded_end: T) -> Self {
1
        self.end = Bound::Excluded(excluded_end);
1
        self
1
    }

            
    /// Sets the end bound of this range to [`Bound::Included`] with
    /// `included_end`. The range will represent values that are
    /// [`Ordering:::Less`](std::cmp::Ordering::Less) than or
    /// [`Ordering::Equal`](std::cmp::Ordering::Equal) to `included_end`.
    #[allow(clippy::missing_const_for_fn)]
1
    pub fn end_at(mut self, included_end: T) -> Self {
1
        self.end = Bound::Included(included_end);
1
        self
1
    }

            
    /// Maps each contained value with the function provided.
    pub fn map<U, F: Fn(T) -> U>(self, map: F) -> Range<U> {
        Range {
            start: self.start.map(&map),
            end: self.end.map(&map),
        }
    }

            
    /// Maps each contained value with the function provided. The callback's
    /// return type is a Result, unlike with `map`.
    pub fn map_result<U, E, F: Fn(T) -> Result<U, E>>(self, map: F) -> Result<Range<U>, E> {
        Ok(Range {
            start: self.start.map_result(&map)?,
            end: self.end.map_result(&map)?,
        })
    }

            
    /// Maps each contained value as a reference.
1412
    pub fn map_ref<U: ?Sized, F: Fn(&T) -> &U>(&self, map: F) -> Range<&U> {
1412
        Range {
1412
            start: self.start.map_ref(&map),
1412
            end: self.end.map_ref(&map),
1412
        }
1412
    }
}

            
1
#[test]
1
fn range_constructors() {
1
    assert_eq!(
1
        Range::default().after(1_u32),
1
        Range {
1
            start: Bound::Excluded(1),
1
            end: Bound::Unbounded
1
        }
1
    );
1
    assert_eq!(
1
        Range::default().start_at(1_u32),
1
        Range {
1
            start: Bound::Included(1),
1
            end: Bound::Unbounded
1
        }
1
    );
1
    assert_eq!(
1
        Range::default().before(1_u32),
1
        Range {
1
            start: Bound::Unbounded,
1
            end: Bound::Excluded(1),
1
        }
1
    );
1
    assert_eq!(
1
        Range::default().end_at(1_u32),
1
        Range {
1
            start: Bound::Unbounded,
1
            end: Bound::Included(1),
1
        }
1
    );
1
}

            
impl<'a, TOwned, TBorrowed> RangeRef<'a, TOwned, TBorrowed>
where
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
    TBorrowed: PartialEq + ?Sized,
{
    /// Serializes the range's contained values to big-endian bytes.
82
    pub fn as_ord_bytes(&'a self) -> Result<Range<Bytes>, TBorrowed::Error>
82
    where
82
        TBorrowed: KeyEncoding<TOwned>,
82
        TOwned: for<'k> Key<'k> + Borrow<TBorrowed>,
82
    {
82
        Ok(Range {
82
            start: self.start.as_ord_bytes()?,
82
            end: self.end.as_ord_bytes()?,
        })
82
    }
}

            
impl Range<Bytes> {
    /// Deserializes the range's contained values from big-endian bytes.
    pub fn deserialize<T: for<'k> Key<'k>>(
        &self,
    ) -> Result<Range<T>, <T as KeyEncoding<T>>::Error> {
        Ok(Range {
            start: self.start.deserialize()?,
            end: self.start.deserialize()?,
        })
    }
}

            
impl<T> Bound<T> {
    /// Maps the contained value, if any, and returns the resulting `Bound`.
    pub fn map<U, F: Fn(T) -> U>(self, map: F) -> Bound<U> {
        match self {
            Self::Unbounded => Bound::Unbounded,
            Self::Included(value) => Bound::Included(map(value)),
            Self::Excluded(value) => Bound::Excluded(map(value)),
        }
    }

            
    /// Maps the contained value with the function provided. The callback's
    /// return type is a Result, unlike with `map`.
    pub fn map_result<U, E, F: Fn(T) -> Result<U, E>>(self, map: F) -> Result<Bound<U>, E> {
        Ok(match self {
            Self::Unbounded => Bound::Unbounded,
            Self::Included(value) => Bound::Included(map(value)?),
            Self::Excluded(value) => Bound::Excluded(map(value)?),
        })
    }

            
    /// Maps each contained value as a reference.
2824
    pub fn map_ref<U: ?Sized, F: Fn(&T) -> &U>(&self, map: F) -> Bound<&U> {
2824
        match self {
72
            Self::Unbounded => Bound::Unbounded,
1708
            Self::Included(value) => Bound::Included(map(value)),
1044
            Self::Excluded(value) => Bound::Excluded(map(value)),
        }
2824
    }
}

            
impl<'a, TOwned, TBorrowed> BoundRef<'a, TOwned, TBorrowed>
where
    TBorrowed: PartialEq + ?Sized,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
    /// Serializes the contained value to big-endian bytes.
164
    pub fn as_ord_bytes(&'a self) -> Result<Bound<Bytes>, TBorrowed::Error>
164
    where
164
        TBorrowed: KeyEncoding<TOwned>,
164
        TOwned: for<'k> Key<'k> + Borrow<TBorrowed>,
164
    {
164
        match self {
2
            Self::Unbounded => Ok(Bound::Unbounded),
98
            Self::Included(value) => {
98
                Ok(Bound::Included(Bytes::from(value.as_ord_bytes()?.to_vec())))
            }
64
            Self::Excluded(value) => {
64
                Ok(Bound::Excluded(Bytes::from(value.as_ord_bytes()?.to_vec())))
            }
        }
164
    }
}

            
impl Bound<Bytes> {
    /// Deserializes the bound's contained value from big-endian bytes.
    pub fn deserialize<T: for<'k> Key<'k>>(
        &self,
    ) -> Result<Bound<T>, <T as KeyEncoding<T>>::Error> {
        match self {
            Self::Unbounded => Ok(Bound::Unbounded),
            Self::Included(value) => Ok(Bound::Included(T::from_ord_bytes(ByteSource::Borrowed(
                value.as_ref(),
            ))?)),
            Self::Excluded(value) => Ok(Bound::Excluded(T::from_ord_bytes(ByteSource::Borrowed(
                value.as_ref(),
            ))?)),
        }
    }
}

            
impl<T> std::ops::RangeBounds<T> for Range<T> {
412196
    fn start_bound(&self) -> std::ops::Bound<&T> {
412196
        std::ops::Bound::from(&self.start)
412196
    }

            
372800
    fn end_bound(&self) -> std::ops::Bound<&T> {
372800
        std::ops::Bound::from(&self.end)
372800
    }
}

            
impl<'a, T> From<&'a Bound<T>> for std::ops::Bound<&'a T> {
784996
    fn from(bound: &'a Bound<T>) -> Self {
784996
        match bound {
603464
            Bound::Unbounded => std::ops::Bound::Unbounded,
178040
            Bound::Included(value) => std::ops::Bound::Included(value),
3492
            Bound::Excluded(value) => std::ops::Bound::Excluded(value),
        }
784996
    }
}

            
impl<'a, T> From<Bound<&'a T>> for std::ops::Bound<&'a T> {
    fn from(bound: Bound<&'a T>) -> Self {
        match bound {
            Bound::Unbounded => std::ops::Bound::Unbounded,
            Bound::Included(value) => std::ops::Bound::Included(value),
            Bound::Excluded(value) => std::ops::Bound::Excluded(value),
        }
    }
}

            
impl<T> From<std::ops::Range<T>> for Range<T> {
    fn from(range: std::ops::Range<T>) -> Self {
        Self {
            start: Bound::Included(range.start),
            end: Bound::Excluded(range.end),
        }
    }
}

            
impl<T> From<std::ops::RangeFrom<T>> for Range<T> {
19812
    fn from(range: std::ops::RangeFrom<T>) -> Self {
19812
        Self {
19812
            start: Bound::Included(range.start),
19812
            end: Bound::Unbounded,
19812
        }
19812
    }
}

            
impl<T> From<std::ops::RangeTo<T>> for Range<T> {
    fn from(range: std::ops::RangeTo<T>) -> Self {
        Self {
            start: Bound::Unbounded,
            end: Bound::Excluded(range.end),
        }
    }
}

            
impl<T: Clone> From<std::ops::RangeInclusive<T>> for Range<T> {
    fn from(range: std::ops::RangeInclusive<T>) -> Self {
        Self {
            start: Bound::Included(range.start().clone()),
            end: Bound::Included(range.end().clone()),
        }
    }
}

            
impl<T> From<std::ops::RangeToInclusive<T>> for Range<T> {
    fn from(range: std::ops::RangeToInclusive<T>) -> Self {
        Self {
            start: Bound::Unbounded,
            end: Bound::Included(range.end),
        }
    }
}

            
impl<T> From<std::ops::RangeFull> for Range<T> {
19082
    fn from(_: std::ops::RangeFull) -> Self {
19082
        Self {
19082
            start: Bound::Unbounded,
19082
            end: Bound::Unbounded,
19082
        }
19082
    }
}

            
/// A range reference type that can be serialized.
#[derive(Debug, Clone, PartialEq)]
#[must_use]
pub struct RangeRef<'a, TOwned, TBorrowed = TOwned>
where
    TBorrowed: PartialEq + ?Sized,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
    /// The start of the range.
    pub start: BoundRef<'a, TOwned, TBorrowed>,
    /// The end of the range.
    pub end: BoundRef<'a, TOwned, TBorrowed>,
}

            
impl<'a, TOwned, TBorrowed> From<std::ops::Range<TOwned>> for RangeRef<'a, TOwned, TBorrowed>
where
    TBorrowed: PartialEq,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
10
    fn from(range: std::ops::Range<TOwned>) -> Self {
10
        Self {
10
            start: BoundRef::Included(MaybeOwned::Owned(range.start)),
10
            end: BoundRef::Excluded(MaybeOwned::Owned(range.end)),
10
        }
10
    }
}

            
impl<'a, 'b, TOwned, TBorrowed> From<&'b std::ops::Range<&'a TBorrowed>>
    for RangeRef<'a, TOwned, TBorrowed>
where
    TBorrowed: PartialEq,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
    fn from(range: &'b std::ops::Range<&'a TBorrowed>) -> Self {
        Self {
            start: BoundRef::Included(MaybeOwned::Borrowed(range.start)),
            end: BoundRef::Excluded(MaybeOwned::Borrowed(range.end)),
        }
    }
}

            
impl<'a, TOwned, TBorrowed> From<std::ops::RangeFrom<TOwned>> for RangeRef<'a, TOwned, TBorrowed>
where
    TBorrowed: PartialEq,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
2
    fn from(range: std::ops::RangeFrom<TOwned>) -> Self {
2
        Self {
2
            start: BoundRef::Included(MaybeOwned::Owned(range.start)),
2
            end: BoundRef::Unbounded,
2
        }
2
    }
}

            
impl<'a, 'b, TOwned, TBorrowed> From<&'b std::ops::RangeFrom<&'a TBorrowed>>
    for RangeRef<'a, TOwned, TBorrowed>
where
    TBorrowed: PartialEq,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
    fn from(range: &'b std::ops::RangeFrom<&'a TBorrowed>) -> Self {
        Self {
            start: BoundRef::Included(MaybeOwned::Borrowed(range.start)),
            end: BoundRef::Unbounded,
        }
    }
}

            
impl<'a, TOwned, TBorrowed> From<std::ops::RangeTo<TOwned>> for RangeRef<'a, TOwned, TBorrowed>
where
    TBorrowed: PartialEq,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
    fn from(range: std::ops::RangeTo<TOwned>) -> Self {
        Self {
            start: BoundRef::Unbounded,
            end: BoundRef::Excluded(MaybeOwned::Owned(range.end)),
        }
    }
}

            
impl<'a, 'b, TOwned, TBorrowed> From<&'b std::ops::RangeTo<&'a TBorrowed>>
    for RangeRef<'a, TOwned, TBorrowed>
where
    TBorrowed: PartialEq,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
    fn from(range: &'b std::ops::RangeTo<&'a TBorrowed>) -> Self {
        Self {
            start: BoundRef::Unbounded,
            end: BoundRef::Excluded(MaybeOwned::Borrowed(range.end)),
        }
    }
}

            
impl<'a, TOwned, TBorrowed> From<std::ops::RangeInclusive<TOwned>>
    for RangeRef<'a, TOwned, TBorrowed>
where
    TBorrowed: PartialEq,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed> + Clone,
{
48
    fn from(range: std::ops::RangeInclusive<TOwned>) -> Self {
48
        Self {
48
            start: BoundRef::Included(MaybeOwned::Owned(range.start().clone())),
48
            end: BoundRef::Included(MaybeOwned::Owned(range.end().clone())),
48
        }
48
    }
}

            
impl<'a, 'b, TOwned, TBorrowed> From<&'b std::ops::RangeInclusive<&'a TBorrowed>>
    for RangeRef<'a, TOwned, TBorrowed>
where
    TBorrowed: PartialEq,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
    fn from(range: &'b std::ops::RangeInclusive<&'a TBorrowed>) -> Self {
        Self {
            start: BoundRef::Included(MaybeOwned::Borrowed(range.start())),
            end: BoundRef::Included(MaybeOwned::Borrowed(range.end())),
        }
    }
}

            
impl<'a, TOwned, TBorrowed> From<std::ops::RangeToInclusive<&'a TBorrowed>>
    for RangeRef<'a, TOwned, TBorrowed>
where
    TBorrowed: PartialEq,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
    fn from(range: std::ops::RangeToInclusive<&'a TBorrowed>) -> Self {
        Self {
            start: BoundRef::Unbounded,
            end: BoundRef::Included(MaybeOwned::Borrowed(range.end)),
        }
    }
}

            
impl<'a, TOwned, TBorrowed> From<std::ops::RangeFull> for RangeRef<'a, TOwned, TBorrowed>
where
    TBorrowed: PartialEq,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
28
    fn from(_: std::ops::RangeFull) -> Self {
28
        Self {
28
            start: BoundRef::Unbounded,
28
            end: BoundRef::Unbounded,
28
        }
28
    }
}

            
impl<'a, TOwned, TBorrowed> RangeRef<'a, TOwned, TBorrowed>
where
    TBorrowed: PartialEq + ?Sized,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
    /// Returns a borrowed range ref using the bounds in the range provided.
    pub const fn borrowed(range: Range<&'a TBorrowed>) -> Self {
        Self {
            start: BoundRef::borrowed(range.start),
            end: BoundRef::borrowed(range.end),
        }
    }

            
    /// Returns an owned range ref using the bounds in the range provided.
    pub fn owned(range: Range<TOwned>) -> Self {
        Self {
            start: BoundRef::owned(range.start),
            end: BoundRef::owned(range.end),
        }
    }

            
    /// Maps each contained value with the function provided. The callback's
    /// return type is a Result, unlike with `map`.
68
    pub fn map_result<U, E, F: Fn(&TBorrowed) -> Result<U, E>>(
68
        self,
68
        map: F,
68
    ) -> Result<Range<U>, E> {
68
        Ok(Range {
68
            start: self.start.map_result(&map)?,
68
            end: self.end.map_result(&map)?,
        })
68
    }
}

            
impl<'a, TOwned, TBorrowed> std::ops::RangeBounds<TBorrowed> for RangeRef<'a, TOwned, TBorrowed>
where
    TBorrowed: PartialEq + ?Sized,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
26
    fn start_bound(&self) -> std::ops::Bound<&TBorrowed> {
26
        std::ops::Bound::from(&self.start)
26
    }

            
20
    fn end_bound(&self) -> std::ops::Bound<&TBorrowed> {
20
        std::ops::Bound::from(&self.end)
20
    }
}

            
impl<'a, TOwned, TBorrowed> From<&'a BoundRef<'a, TOwned, TBorrowed>>
    for std::ops::Bound<&'a TBorrowed>
where
    TBorrowed: PartialEq + ?Sized,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
46
    fn from(bound: &'a BoundRef<'a, TOwned, TBorrowed>) -> Self {
46
        match bound {
6
            BoundRef::Unbounded => std::ops::Bound::Unbounded,
26
            BoundRef::Included(value) => std::ops::Bound::Included(value),
14
            BoundRef::Excluded(value) => std::ops::Bound::Excluded(value),
        }
46
    }
}

            
/// A range bound reference.
#[derive(Debug, Clone, PartialEq)]
#[must_use]
pub enum BoundRef<'a, TOwned, TBorrowed = TOwned>
where
    TBorrowed: PartialEq + ?Sized,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
    MaybeOwned<'a, TOwned, TBorrowed>: PartialEq,
{
    /// No bound.
    Unbounded,
    /// Bounded by the contained value (inclusive).
    Included(MaybeOwned<'a, TOwned, TBorrowed>),
    /// Bounded by the contained value (exclusive).
    Excluded(MaybeOwned<'a, TOwned, TBorrowed>),
}

            
impl<'a, TOwned, TBorrowed> BoundRef<'a, TOwned, TBorrowed>
where
    TBorrowed: PartialEq + ?Sized,
    TOwned: Borrow<TBorrowed> + PartialEq<TBorrowed>,
{
    /// Returns a borrowed bound from the bound provided.
118
    pub const fn borrowed(range: Bound<&'a TBorrowed>) -> Self {
118
        match range {
            Bound::Unbounded => Self::Unbounded,
92
            Bound::Included(value) => Self::Included(MaybeOwned::Borrowed(value)),
26
            Bound::Excluded(value) => Self::Excluded(MaybeOwned::Borrowed(value)),
        }
118
    }

            
    /// Returns an owned bound ref from the bound provided.
    #[allow(clippy::missing_const_for_fn)] // false positive, destructors
54
    pub fn owned(range: Bound<TOwned>) -> Self {
54
        match range {
            Bound::Unbounded => Self::Unbounded,
            Bound::Included(value) => Self::Included(MaybeOwned::Owned(value)),
54
            Bound::Excluded(value) => Self::Excluded(MaybeOwned::Owned(value)),
        }
54
    }

            
    /// Maps each contained value with the function provided. The callback's
    /// return type is a Result, unlike with `map`.
136
    pub fn map_result<U, E, F: Fn(&TBorrowed) -> Result<U, E>>(
136
        self,
136
        map: F,
136
    ) -> Result<Bound<U>, E> {
136
        Ok(match self {
56
            BoundRef::Unbounded => Bound::Unbounded,
72
            BoundRef::Included(value) => Bound::Included(map(&*value)?),
8
            BoundRef::Excluded(value) => Bound::Excluded(map(&*value)?),
        })
136
    }
}

            
/// Changes how the view's outdated data will be treated.
258884
#[derive(Copy, Clone, Serialize, Deserialize, Debug)]
pub enum AccessPolicy {
    /// Update any changed documents before returning a response.
    UpdateBefore,

            
    /// Return the results, which may be out-of-date, and start an update job in
    /// the background. This pattern is useful when you want to ensure you
    /// provide consistent response times while ensuring the database is
    /// updating in the background.
    UpdateAfter,

            
    /// Returns the results, which may be out-of-date, and do not start any
    /// background jobs. This mode is useful if you're using a view as a cache
    /// and have a background process that is responsible for controlling when
    /// data is refreshed and updated. While the default `UpdateBefore`
    /// shouldn't have much overhead, this option removes all overhead related
    /// to view updating from the query.
    NoUpdate,
}

            
/// Functions for interacting with a multi-database BonsaiDb instance.
#[async_trait]
pub trait StorageConnection: HasSession + Sized + Send + Sync {
    /// The type that represents a database for this implementation.
    type Database: Connection;
    /// The [`StorageConnection`] type returned from authentication calls.
    type Authenticated: StorageConnection;

            
    /// Returns the administration database.
    fn admin(&self) -> Self::Database;

            
    /// Creates a database named `name` with the `Schema` provided.
    ///
    /// ## Errors
    ///
    /// * [`Error::InvalidDatabaseName`]: `name` must begin with an alphanumeric
    ///   character (`[a-zA-Z0-9]`), and all remaining characters must be
    ///   alphanumeric, a period (`.`), or a hyphen (`-`).
    /// * [`Error::DatabaseNameAlreadyTaken`]: `name` was already used for a
    ///   previous database name. Returned if `only_if_needed` is false.
    fn create_database<DB: Schema>(
        &self,
        name: &str,
        only_if_needed: bool,
    ) -> Result<Self::Database, crate::Error> {
4683
        self.create_database_with_schema(name, DB::schema_name(), only_if_needed)?;
4674
        self.database::<DB>(name)
4683
    }

            
    /// Returns a reference to database `name` with schema `DB`.
    fn database<DB: Schema>(&self, name: &str) -> Result<Self::Database, crate::Error>;

            
    /// Creates a database named `name` using the [`SchemaName`] `schema`.
    ///
    /// ## Errors
    ///
    /// * [`Error::InvalidDatabaseName`]: `name` must begin with an alphanumeric
    ///   character (`[a-zA-Z0-9]`), and all remaining characters must be
    ///   alphanumeric, a period (`.`), or a hyphen (`-`).
    /// * [`Error::DatabaseNameAlreadyTaken`]: `name` was already used for a
    ///   previous database name. Returned if `only_if_needed` is false.
    fn create_database_with_schema(
        &self,
        name: &str,
        schema: SchemaName,
        only_if_needed: bool,
    ) -> Result<(), crate::Error>;

            
    /// Deletes a database named `name`.
    ///
    /// ## Errors
    ///
    /// * [`Error::DatabaseNotFound`]: database `name` does not exist.
    /// * [`Error::Other`]: an error occurred while deleting files.
    fn delete_database(&self, name: &str) -> Result<(), crate::Error>;

            
    /// Lists the databases in this storage.
    fn list_databases(&self) -> Result<Vec<Database>, crate::Error>;

            
    /// Lists the [`SchemaName`]s registered with this storage.
    fn list_available_schemas(&self) -> Result<Vec<SchemaSummary>, crate::Error>;

            
    /// Creates a user.
    fn create_user(&self, username: &str) -> Result<u64, crate::Error>;

            
    /// Deletes a user.
    fn delete_user<'user, U: Nameable<'user, u64> + Send + Sync>(
        &self,
        user: U,
    ) -> Result<(), crate::Error>;

            
    /// Sets a user's password.
    #[cfg(feature = "password-hashing")]
    fn set_user_password<'user, U: Nameable<'user, u64> + Send + Sync>(
        &self,
        user: U,
        password: SensitiveString,
    ) -> Result<(), crate::Error>;

            
    /// Authenticates using the active session, returning a connection with a
    /// new session upon success. The existing connection will remain usable
    /// with the existing authentication, if any.
    #[cfg(any(feature = "token-authentication", feature = "password-hashing"))]
    fn authenticate(
        &self,
        authentication: Authentication,
    ) -> Result<Self::Authenticated, crate::Error>;

            
    /// Assumes the `identity`. If successful, the returned instance will have
    ///  the permissions from `identity`.
    fn assume_identity(
        &self,
        identity: IdentityReference<'_>,
    ) -> Result<Self::Authenticated, crate::Error>;

            
    /// Authenticates using an
    /// [`AuthenticationToken`](crate::admin::AuthenticationToken). If
    ///  successful, the returned instance will have the permissions from
    ///  `identity`.
    #[cfg(feature = "token-authentication")]
6
    fn authenticate_with_token(
6
        &self,
6
        id: u64,
6
        token: &SensitiveString,
6
    ) -> Result<<Self::Authenticated as StorageConnection>::Authenticated, crate::Error> {
6
        let challenge_session = self.authenticate(Authentication::token(id, token)?)?;
6
        match challenge_session
6
            .session()
6
            .map(|session| &session.authentication)
        {
            Some(SessionAuthentication::TokenChallenge {
                algorithm: TokenChallengeAlgorithm::Blake3,
6
                nonce,
6
                server_timestamp,
6
                ..
6
            }) => {
6
                let response = crate::admin::AuthenticationToken::compute_challenge_response_blake3(
6
                    token,
6
                    nonce,
6
                    *server_timestamp,
6
                );
6
                challenge_session.authenticate(Authentication::TokenChallengeResponse(Bytes::from(
6
                    response.as_bytes().to_vec(),
6
                )))
            }
            _ => Err(crate::Error::InvalidCredentials),
        }
6
    }

            
    /// Authenticates a [`User`](crate::admin::User) using a password. If
    ///  successful, the returned instance will have the permissions from
    ///  `identity`.
    #[cfg(feature = "password-hashing")]
    fn authenticate_with_password<'name, User: Nameable<'name, u64>>(
        &self,
        user: User,
        password: SensitiveString,
    ) -> Result<Self::Authenticated, crate::Error> {
        self.authenticate(Authentication::password(user, password)?)
    }

            
    /// Adds a user to a permission group.
    fn add_permission_group_to_user<
        'user,
        'group,
        U: Nameable<'user, u64> + Send + Sync,
        G: Nameable<'group, u64> + Send + Sync,
    >(
        &self,
        user: U,
        permission_group: G,
    ) -> Result<(), crate::Error>;

            
    /// Removes a user from a permission group.
    fn remove_permission_group_from_user<
        'user,
        'group,
        U: Nameable<'user, u64> + Send + Sync,
        G: Nameable<'group, u64> + Send + Sync,
    >(
        &self,
        user: U,
        permission_group: G,
    ) -> Result<(), crate::Error>;

            
    /// Adds a user to a permission group.
    fn add_role_to_user<
        'user,
        'role,
        U: Nameable<'user, u64> + Send + Sync,
        R: Nameable<'role, u64> + Send + Sync,
    >(
        &self,
        user: U,
        role: R,
    ) -> Result<(), crate::Error>;

            
    /// Removes a user from a permission group.
    fn remove_role_from_user<
        'user,
        'role,
        U: Nameable<'user, u64> + Send + Sync,
        R: Nameable<'role, u64> + Send + Sync,
    >(
        &self,
        user: U,
        role: R,
    ) -> Result<(), crate::Error>;
}

            
/// Functions for interacting with a multi-database BonsaiDb instance.
#[async_trait]
pub trait AsyncStorageConnection: HasSession + Sized + Send + Sync {
    /// The type that represents a database for this implementation.
    type Database: AsyncConnection;
    /// The [`StorageConnection`] type returned from authentication calls.
    type Authenticated: AsyncStorageConnection;

            
    /// Returns the currently authenticated session, if any.
    async fn admin(&self) -> Self::Database;
    /// Creates a database named `name` with the `Schema` provided.
    ///
    /// ## Errors
    ///
    /// * [`Error::InvalidDatabaseName`]: `name` must begin with an alphanumeric
    ///   character (`[a-zA-Z0-9]`), and all remaining characters must be
    ///   alphanumeric, a period (`.`), or a hyphen (`-`).
    /// * [`Error::DatabaseNameAlreadyTaken`]: `name` was already used for a
    ///   previous database name. Returned if `only_if_needed` is false.
843
    async fn create_database<DB: Schema>(
843
        &self,
843
        name: &str,
843
        only_if_needed: bool,
843
    ) -> Result<Self::Database, crate::Error> {
843
        self.create_database_with_schema(name, DB::schema_name(), only_if_needed)
4167
            .await?;
828
        self.database::<DB>(name).await
1686
    }

            
    /// Returns a reference to database `name` with schema `DB`.
    async fn database<DB: Schema>(&self, name: &str) -> Result<Self::Database, crate::Error>;

            
    /// Creates a database named `name` using the [`SchemaName`] `schema`.
    ///
    /// ## Errors
    ///
    /// * [`Error::InvalidDatabaseName`]: `name` must begin with an alphanumeric
    ///   character (`[a-zA-Z0-9]`), and all remaining characters must be
    ///   alphanumeric, a period (`.`), or a hyphen (`-`).
    /// * [`Error::DatabaseNameAlreadyTaken`]: `name` was already used for a
    ///   previous database name. Returned if `only_if_needed` is false.
    async fn create_database_with_schema(
        &self,
        name: &str,
        schema: SchemaName,
        only_if_needed: bool,
    ) -> Result<(), crate::Error>;

            
    /// Deletes a database named `name`.
    ///
    /// ## Errors
    ///
    /// * [`Error::DatabaseNotFound`]: database `name` does not exist.
    /// * [`Error::Other`]: an error occurred while deleting files.
    async fn delete_database(&self, name: &str) -> Result<(), crate::Error>;

            
    /// Lists the databases in this storage.
    async fn list_databases(&self) -> Result<Vec<Database>, crate::Error>;

            
    /// Lists the [`SchemaName`]s registered with this storage.
    async fn list_available_schemas(&self) -> Result<Vec<SchemaSummary>, crate::Error>;

            
    /// Creates a user.
    async fn create_user(&self, username: &str) -> Result<u64, crate::Error>;

            
    /// Deletes a user.
    async fn delete_user<'user, U: Nameable<'user, u64> + Send + Sync>(
        &self,
        user: U,
    ) -> Result<(), crate::Error>;

            
    /// Sets a user's password.
    #[cfg(feature = "password-hashing")]
    async fn set_user_password<'user, U: Nameable<'user, u64> + Send + Sync>(
        &self,
        user: U,
        password: SensitiveString,
    ) -> Result<(), crate::Error>;

            
    /// Authenticates using an
    /// [`AuthenticationToken`](crate::admin::AuthenticationToken). If
    ///  successful, the returned instance will have the permissions from
    ///  `identity`.
    #[cfg(any(feature = "token-authentication", feature = "password-hashing"))]
    async fn authenticate(
        &self,
        authentication: Authentication,
    ) -> Result<Self::Authenticated, crate::Error>;

            
    /// Authenticates using an
    /// [`AuthenticationToken`](crate::admin::AuthenticationToken). If
    ///  successful, the returned instance will have the permissions from
    ///  `identity`.
    #[cfg(feature = "token-authentication")]
10
    async fn authenticate_with_token(
10
        &self,
10
        id: u64,
10
        token: &SensitiveString,
10
    ) -> Result<<Self::Authenticated as AsyncStorageConnection>::Authenticated, crate::Error> {
10
        let challenge_session = self.authenticate(Authentication::token(id, token)?).await?;
10
        match challenge_session
10
            .session()
10
            .map(|session| &session.authentication)
        {
            Some(SessionAuthentication::TokenChallenge {
                algorithm: TokenChallengeAlgorithm::Blake3,
10
                nonce,
10
                server_timestamp,
10
                ..
10
            }) => {
10
                let response = crate::admin::AuthenticationToken::compute_challenge_response_blake3(
10
                    token,
10
                    nonce,
10
                    *server_timestamp,
10
                );
10
                challenge_session
10
                    .authenticate(Authentication::TokenChallengeResponse(Bytes::from(
10
                        response.as_bytes().to_vec(),
10
                    )))
10
                    .await
            }
            _ => Err(crate::Error::InvalidCredentials),
        }
20
    }

            
    /// Authenticates a [`User`](crate::admin::User) using a password. If
    ///  successful, the returned instance will have the permissions from
    ///  `identity`.
    #[cfg(feature = "password-hashing")]
2
    async fn authenticate_with_password<'name, User: Nameable<'name, u64> + Send>(
2
        &self,
2
        user: User,
2
        password: SensitiveString,
2
    ) -> Result<Self::Authenticated, crate::Error> {
2
        self.authenticate(Authentication::password(user, password)?)
2
            .await
4
    }

            
    /// Assumes the `identity`. If successful, the returned instance will have
    /// the merged permissions of the current authentication session and the
    /// permissions from `identity`.
    async fn assume_identity(
        &self,
        identity: IdentityReference<'_>,
    ) -> Result<Self::Authenticated, crate::Error>;

            
    /// Adds a user to a permission group.
    async fn add_permission_group_to_user<
        'user,
        'group,
        U: Nameable<'user, u64> + Send + Sync,
        G: Nameable<'group, u64> + Send + Sync,
    >(
        &self,
        user: U,
        permission_group: G,
    ) -> Result<(), crate::Error>;

            
    /// Removes a user from a permission group.
    async fn remove_permission_group_from_user<
        'user,
        'group,
        U: Nameable<'user, u64> + Send + Sync,
        G: Nameable<'group, u64> + Send + Sync,
    >(
        &self,
        user: U,
        permission_group: G,
    ) -> Result<(), crate::Error>;

            
    /// Adds a user to a permission group.
    async fn add_role_to_user<
        'user,
        'role,
        U: Nameable<'user, u64> + Send + Sync,
        R: Nameable<'role, u64> + Send + Sync,
    >(
        &self,
        user: U,
        role: R,
    ) -> Result<(), crate::Error>;

            
    /// Removes a user from a permission group.
    async fn remove_role_from_user<
        'user,
        'role,
        U: Nameable<'user, u64> + Send + Sync,
        R: Nameable<'role, u64> + Send + Sync,
    >(
        &self,
        user: U,
        role: R,
    ) -> Result<(), crate::Error>;
}

            
/// A database stored in BonsaiDb.
65535
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)]
pub struct Database {
    /// The name of the database.
    pub name: String,
    /// The schema defining the database.
    pub schema: SchemaName,
}

            
/// A string containing sensitive (private) data. This struct automatically
/// overwrites its contents with zeroes when dropped.
8000
#[derive(Clone, Default, Serialize, Deserialize, Zeroize, Eq, PartialEq)]
#[zeroize(drop)]
#[serde(transparent)]
pub struct SensitiveString(pub String);

            
impl std::fmt::Debug for SensitiveString {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str("SensitiveString(...)")
    }
}

            
impl Deref for SensitiveString {
    type Target = String;

            
560
    fn deref(&self) -> &Self::Target {
560
        &self.0
560
    }
}

            
impl DerefMut for SensitiveString {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

            
impl<'k> Key<'k> for SensitiveString {
    const CAN_OWN_BYTES: bool = String::CAN_OWN_BYTES;

            
    fn from_ord_bytes<'e>(bytes: ByteSource<'k, 'e>) -> Result<Self, Self::Error> {
        String::from_ord_bytes(bytes).map(Self)
    }
}

            
impl KeyEncoding<Self> for SensitiveString {
    type Error = FromUtf8Error;

            
    const LENGTH: Option<usize> = None;

            
    fn describe<Visitor>(visitor: &mut Visitor)
    where
        Visitor: KeyVisitor,
    {
        visitor.visit_type(KeyKind::String);
    }

            
    fn as_ord_bytes(&self) -> Result<std::borrow::Cow<'_, [u8]>, Self::Error> {
        self.0.as_ord_bytes()
    }
}

            
impl From<String> for SensitiveString {
    fn from(sensitive: String) -> Self {
        Self(sensitive)
    }
}

            
impl<'a> From<&'a str> for SensitiveString {
280
    fn from(sensitive: &'a str) -> Self {
280
        Self(sensitive.to_owned())
280
    }
}

            
/// A buffer containing sensitive (private) data. This struct automatically
/// overwrites its contents with zeroes when dropped.
#[derive(Clone, Serialize, Deserialize, Zeroize, Eq, PartialEq)]
#[zeroize(drop)]
#[serde(transparent)]
pub struct SensitiveBytes(pub Bytes);

            
impl std::fmt::Debug for SensitiveBytes {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str("SensitiveBytes(...)")
    }
}

            
impl Deref for SensitiveBytes {
    type Target = Bytes;

            
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

            
impl DerefMut for SensitiveBytes {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

            
impl<'k> Key<'k> for SensitiveBytes {
    const CAN_OWN_BYTES: bool = Bytes::CAN_OWN_BYTES;

            
    fn from_ord_bytes<'e>(bytes: ByteSource<'k, 'e>) -> Result<Self, Self::Error> {
        Bytes::from_ord_bytes(bytes).map(Self)
    }
}

            
impl KeyEncoding<Self> for SensitiveBytes {
    type Error = Infallible;

            
    const LENGTH: Option<usize> = None;

            
    fn describe<Visitor>(visitor: &mut Visitor)
    where
        Visitor: KeyVisitor,
    {
        visitor.visit_type(KeyKind::Bytes);
    }

            
    fn as_ord_bytes(&self) -> Result<std::borrow::Cow<'_, [u8]>, Self::Error> {
        self.0.as_ord_bytes()
    }
}

            
/// Authentication methods.
389
#[derive(Clone, Debug, Serialize, Deserialize)]
#[must_use]
pub enum Authentication {
    /// Initialize token-based authentication.
    #[cfg(feature = "token-authentication")]
    Token {
        /// The unique token id.
        id: u64,
        /// The current timestamp of the authenticating device. This must be
        /// within 5 minutes of the server's time for token authentication to
        /// succeed.
        now: crate::key::time::TimestampAsNanoseconds,
        /// The hash of `now`, using the private token as key matter.
        now_hash: Bytes,
        /// The token challenge algorithm used to generate `now_hash`.
        algorithm: TokenChallengeAlgorithm,
    },
    /// A response to the server's token authentication challenge.
    #[cfg(feature = "token-authentication")]
    TokenChallengeResponse(Bytes),
    /// Authenticate a user with a password.
    #[cfg(feature = "password-hashing")]
    Password {
        /// The username or the user id to authenticate as.
        user: NamedReference<'static, u64>,
        /// The password of the user.
        password: SensitiveString,
    },
}

            
impl Authentication {
    /// Returns an authentication instance for this user and password.
    #[cfg(feature = "password-hashing")]
7
    pub fn password<'user, UsernameOrId: Nameable<'user, u64>>(
7
        user: UsernameOrId,
7
        password: SensitiveString,
7
    ) -> Result<Self, crate::Error> {
7
        Ok(Self::Password {
7
            user: user.name()?.into_owned(),
7
            password,
        })
7
    }

            
    /// Returns a token authentication initialization instance for this token.
    #[cfg(feature = "token-authentication")]
640
    pub fn token(id: u64, token: &SensitiveString) -> Result<Self, crate::Error> {
640
        let now = crate::key::time::TimestampAsNanoseconds::now();
640
        Ok(Self::Token {
640
            id,
640
            now,
640
            now_hash: Bytes::from(
640
                crate::admin::AuthenticationToken::compute_request_time_hash_blake3(now, token)
640
                    .as_bytes()
640
                    .to_vec(),
640
            ),
640
            algorithm: TokenChallengeAlgorithm::Blake3,
640
        })
640
    }
}

            
#[doc(hidden)]
#[macro_export]
macro_rules! __doctest_prelude {
    () => {
        use bonsaidb_core::{
            connection::AccessPolicy,
            define_basic_unique_mapped_view,
            document::{CollectionDocument,Emit, Document, OwnedDocument},
            schema::{
                Collection, CollectionName,  DefaultSerialization,
                DefaultViewSerialization, Name, NamedCollection, ReduceResult, Schema, SchemaName,
                Schematic, SerializedCollection, View, ViewSchema, CollectionMapReduce, ViewMapResult, ViewMappedValue, SerializedView,
            },
            Error,
        };
        use serde::{Deserialize, Serialize};

            
        #[derive(Debug, Schema)]
        #[schema(name = "MySchema", collections = [MyCollection], core = $crate)]
        pub struct MySchema;

            
        #[derive( Debug, Serialize, Deserialize, Default, Collection)]
        #[collection(name = "MyCollection", views = [MyCollectionByName], core = $crate)]
        pub struct MyCollection {
            pub name: String,
            pub rank: u32,
            pub score: f32,
        }

            
        impl MyCollection {
            pub fn named(s: impl Into<String>) -> Self {
                Self::new(s, 0, 0.)
            }

            
            pub fn new(s: impl Into<String>, rank: u32, score: f32) -> Self {
                Self {
                    name: s.into(),
                    rank,
                    score,
                }
            }
        }

            
        impl NamedCollection for MyCollection {
            type ByNameView = MyCollectionByName;
        }

            
        #[derive(Debug, Clone, View, ViewSchema)]
        #[view(collection = MyCollection, key = u32, value = f32, name = "scores-by-rank", core = $crate)]
        #[view_schema(core = $crate)]
        pub struct ScoresByRank;

            
        impl CollectionMapReduce for ScoresByRank {
            fn map<'doc>(
                &self,
                document: CollectionDocument<<Self::View as View>::Collection>,
            ) -> ViewMapResult<'doc, Self::View> {
                document
                    .header
                    .emit_key_and_value(document.contents.rank, document.contents.score)
            }

            
            fn reduce(
                &self,
                mappings: &[ViewMappedValue<'_, Self::View>],
                rereduce: bool,
            ) -> ReduceResult<Self::View> {
                if mappings.is_empty() {
                    Ok(0.)
                } else {
                    Ok(mappings.iter().map(|map| map.value).sum::<f32>() / mappings.len() as f32)
                }
            }
        }

            
        define_basic_unique_mapped_view!(
            MyCollectionByName,
            MyCollection,
            1,
            "by-name",
            String,
            (),
            |document: CollectionDocument<MyCollection>| {
                document.header.emit_key(document.contents.name.clone())
            },
        );
    };
}

            
/// The authentication state for a [`StorageConnection`].
148957
#[derive(Default, Clone, Debug, Serialize, Deserialize)]
#[must_use]
pub struct Session {
    /// The session's unique ID.
    pub id: Option<SessionId>,
    /// The authenticated identity, if any.
    pub authentication: SessionAuthentication,
    /// The effective permissions of the session.
    pub permissions: Permissions,
}

            
/// The authentication state of a [`Session`].
148429
#[derive(Hash, Eq, PartialEq, Clone, Debug, Serialize, Deserialize)]
pub enum SessionAuthentication {
    /// The session is unauthenticated.
    None,
    /// The session is authenticated as an identity.
    Identity(Arc<Identity>),
    /// The session is pending authentication using a token.
    #[cfg(feature = "token-authentication")]
    TokenChallenge {
        /// The id of the token being authenticated
        id: u64,
        /// The algorithm the server has chosen for the token challenge.
        algorithm: TokenChallengeAlgorithm,
        /// Random data generated by the server to be hashed during the
        /// challenge.
        nonce: [u8; 32],
        /// The server timestamp that is used for authenticated extra data.
        server_timestamp: crate::key::time::TimestampAsNanoseconds,
    },
}

            
impl Default for SessionAuthentication {
10600
    fn default() -> Self {
10600
        Self::None
10600
    }
}

            
/// A token challenge algorith designates with which algorthm to authenticate
/// tokens.
708
#[derive(Hash, Eq, PartialEq, Clone, Copy, Debug, Serialize, Deserialize)]
#[non_exhaustive]
#[cfg(feature = "token-authentication")]
pub enum TokenChallengeAlgorithm {
    /// Authenticate tokens using [`blake3`](https://crates.io/crates/blake3).
    ///
    /// The initial request requires a hash of
    /// [`TimestampAsNanoseconds::now()`](crate::key::time::TimestampAsNanoseconds::now)
    /// to be performed using [`blake3::keyed_hash()`]. The key is derived using
    /// [`blake3::derive_key()`] using a context formatted like this: `bonsaidb
    /// {now} token-authentication`. The `now` value should be timestamp's
    /// nanoseconds relative to
    /// [`BonsaiEpoch`](crate::key::time::limited::BonsaiEpoch), and the hash's
    /// contents should be the 8-byte big-endian representation of the
    /// nanoseconds as an i64.
    ///
    /// The storage will verify that the timestamp is within a reasonable delta
    /// of the server's current time, and it will verify the private token was
    /// used to generate the hash sent. To prevent replay attacks and add
    /// additional security, the server will return a new [`Session`] whose
    /// authentication field is [`SessionAuthentication::TokenChallenge`].
    ///
    /// The connector must use the new connection to call `authenticate()` with
    /// [`Authentication::TokenChallengeResponse`]. It is possible that the
    /// server will elect a different challenge algorithm than the connector
    /// chose when initially authenticating.
    ///
    /// To generate the challenge response for [`blake3`],
    /// [`blake3::keyed_hash()`] is used to hash the `nonce`. The key is derived
    /// using [`blake3::derive_key()`] using a context formatted like this:
    /// `bonsaidb {server_timestamp} token-challenge`. The `server_timestamp`
    /// value should be timestamp's nanoseconds relative to
    /// [`BonsaiEpoch`](crate::key::time::limited::BonsaiEpoch).
    Blake3,
}

            
/// Methods for authentication.
680
#[derive(Action, Serialize, Deserialize, Clone, Copy, Debug)]
pub enum AuthenticationMethod {
    /// Authenticate the user or role using an
    /// [`AuthenticationToken`](crate::admin::AuthenticationToken).
    Token,
    /// Authenticate a user using password hashing (Argon2).
    PasswordHash,
}

            
/// A unique session ID.
5189
#[derive(Default, Clone, Copy, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
#[serde(transparent)]
pub struct SessionId(pub u64);

            
impl Session {
    /// Checks if `action` is permitted against `resource_name`.
169
    pub fn allowed_to<'a, R: AsRef<[Identifier<'a>]>, P: Action>(
169
        &self,
169
        resource_name: R,
169
        action: &P,
169
    ) -> bool {
169
        self.permissions.allowed_to(resource_name, action)
169
    }

            
    /// Checks if `action` is permitted against `resource_name`. If permission
    /// is denied, returns a [`PermissionDenied`](Error::PermissionDenied)
    /// error.
3107240
    pub fn check_permission<'a, R: AsRef<[Identifier<'a>]>, P: Action>(
3107240
        &self,
3107240
        resource_name: R,
3107240
        action: &P,
3107240
    ) -> Result<(), Error> {
3107240
        self.permissions
3107240
            .check(resource_name, action)
3107240
            .map_err(Error::from)
3107240
    }

            
    /// Returns the identity that this session is authenticated as, if any.
    #[must_use]
    pub fn identity(&self) -> Option<&Identity> {
640
        if let SessionAuthentication::Identity(identity) = &self.authentication {
640
            Some(identity)
        } else {
            None
        }
640
    }
}

            
impl Eq for Session {}

            
impl PartialEq for Session {
    fn eq(&self, other: &Self) -> bool {
        self.authentication == other.authentication
    }
}

            
impl std::hash::Hash for Session {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        self.authentication.hash(state);
    }
}

            
/// An identity from the connected BonsaiDb instance.
1785
#[derive(Clone, Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub enum Identity {
    /// A [`User`](crate::admin::User).
    User {
        /// The unique ID of the user.
        id: u64,
        /// The username of the user.
        username: String,
    },
    /// A [`Role`](crate::admin::Role).
    Role {
        /// The unique ID of the role.
        id: u64,
        /// The name of the role.
        name: String,
    },
}

            
impl Eq for Identity {}

            
impl PartialEq for Identity {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (Self::User { id: l_id, .. }, Self::User { id: r_id, .. })
            | (Self::Role { id: l_id, .. }, Self::Role { id: r_id, .. }) => l_id == r_id,
            _ => false,
        }
    }
}

            
impl std::hash::Hash for Identity {
    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
        match self {
            Identity::User { id, .. } => {
                0_u8.hash(state); // "Tag" for the variant
                id.hash(state);
            }
            Identity::Role { id, .. } => {
                1_u8.hash(state); // "Tag" for the variant
                id.hash(state);
            }
        }
    }
}

            
/// A reference to an identity.
36
#[derive(Clone, Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub enum IdentityReference<'name> {
    /// A reference to a [`User`](crate::admin::User).
    User(NamedReference<'name, u64>),
    /// A reference to a [`Role`](crate::admin::Role).
    Role(NamedReference<'name, u64>),
}

            
impl<'name> IdentityReference<'name> {
    /// Returns a reference to a [`User`]. This function accepts either the
    /// user's unique id or their username.
8
    pub fn user<User: Nameable<'name, u64>>(user: User) -> Result<Self, crate::Error> {
8
        Ok(Self::User(user.name()?))
8
    }

            
    /// Returns a reference to a [`Role`]. This function accepts either the
    /// role's unique id or the role's name.
8
    pub fn role<Role: Nameable<'name, u64>>(role: Role) -> Result<Self, crate::Error> {
8
        Ok(Self::Role(role.name()?))
8
    }

            
    /// Converts this reference to an owned reference with a `'static` lifetime.
    #[must_use]
160
    pub fn into_owned(self) -> IdentityReference<'static> {
160
        match self {
            IdentityReference::User(user) => IdentityReference::User(user.into_owned()),
160
            IdentityReference::Role(role) => IdentityReference::Role(role.into_owned()),
        }
160
    }

            
    /// Resolves this reference to the unique id.
6
    pub fn resolve<C: Connection>(&self, admin: &C) -> Result<Option<IdentityId>, crate::Error> {
6
        match self {
3
            IdentityReference::User(name) => Ok(name.id::<User, _>(admin)?.map(IdentityId::User)),
3
            IdentityReference::Role(name) => Ok(name.id::<Role, _>(admin)?.map(IdentityId::Role)),
        }
6
    }

            
    /// Resolves this reference to the unique id.
10
    pub async fn resolve_async<C: AsyncConnection>(
10
        &self,
10
        admin: &C,
10
    ) -> Result<Option<IdentityId>, crate::Error> {
10
        match self {
5
            IdentityReference::User(name) => {
5
                Ok(name.id_async::<User, _>(admin).await?.map(IdentityId::User))
            }
5
            IdentityReference::Role(name) => {
5
                Ok(name.id_async::<Role, _>(admin).await?.map(IdentityId::Role))
            }
        }
10
    }
}

            
/// An identity from the connected BonsaiDb instance.
1184
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub enum IdentityId {
    /// A [`User`](crate::admin::User) id.
    User(u64),
    /// A [`Role`](crate::admin::Role) id.
    Role(u64),
}

            
/// This type is the result of `query()`. It is a list of mappings, which
/// contains:
///
/// - The key emitted during the map function.
/// - The value emitted during the map function.
/// - The source document header that the mappings originated from.
///
/// This type alias is being moved to [`schema::view::map::ViewMappings`] and
/// will be removed in v0.6.0.
#[deprecated(
    since = "0.5.0",
    note = "ViewMappings has been moved to bonsaidb_core::schema::view::ViewMappings"
)]
pub type ViewMappings<V> = schema::view::map::ViewMappings<V>;