Skip to content

Commit 8f1af6c

Browse files
committed
Added ViewSchema::MappedKey
Closes khonsulabs#284 This commit adds an associateed type to ViewSchema which is used in map and reduce. This type uses a generic associated lifetime, which allows for the map/reduce functions to utilize borrowed data. The extra associated type is an unfortunate side effect of how lifetime extension with generic associated types currently works -- see khonsulabs#287 for where the exploration ended when trying to put the associated type on `Key` instead. Thanks to @asonix for their help in various ideas while experimenting on how to make this work!
1 parent daea610 commit 8f1af6c

File tree

23 files changed

+427
-282
lines changed

23 files changed

+427
-282
lines changed

benchmarks/benches/commerce/bonsai.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ impl CollectionViewSchema for ProductsByCategoryId {
431431
fn map(
432432
&self,
433433
document: CollectionDocument<<Self::View as View>::Collection>,
434-
) -> ViewMapResult<Self::View> {
434+
) -> ViewMapResult<'static, Self> {
435435
let mut mappings = Mappings::default();
436436
for &id in &document.contents.category_ids {
437437
mappings = mappings.and(document.header.emit_key_and_value(id, 1)?);
@@ -469,7 +469,7 @@ impl CollectionViewSchema for ProductReviewsByProduct {
469469
fn map(
470470
&self,
471471
document: CollectionDocument<<Self as View>::Collection>,
472-
) -> ViewMapResult<Self::View> {
472+
) -> ViewMapResult<'static, Self> {
473473
document.header.emit_key_and_value(
474474
document.contents.product_id,
475475
ProductRatings {

book/book-examples/tests/view-example-enum.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,10 @@ pub struct BlogPost {
3535
pub struct BlogPostsByCategory;
3636

3737
impl ViewSchema for BlogPostsByCategory {
38+
type MappedKey<'doc> = Option<Category>;
3839
type View = Self;
3940

40-
fn map(&self, document: &BorrowedDocument<'_>) -> ViewMapResult<Self::View> {
41+
fn map<'doc>(&self, document: &'doc BorrowedDocument<'_>) -> ViewMapResult<'doc, Self> {
4142
let post = BlogPost::document_contents(document)?;
4243
document.header.emit_key_and_value(post.category, 1)
4344
}

book/book-examples/tests/view-example-string.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ pub struct BlogPost {
2525
pub struct BlogPostsByCategory;
2626

2727
impl ViewSchema for BlogPostsByCategory {
28+
type MappedKey<'doc> = Option<String>;
2829
type View = Self;
2930

30-
fn map(&self, document: &BorrowedDocument<'_>) -> ViewMapResult<Self::View> {
31+
fn map<'doc>(&self, document: &'doc BorrowedDocument<'_>) -> ViewMapResult<'doc, Self> {
3132
let post = BlogPost::document_contents(document)?;
3233
document.header.emit_key_and_value(post.category, 1)
3334
}

crates/bonsaidb-core/src/connection.rs

Lines changed: 36 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ where
242242
) -> Result<CollectionHeader<Cl::PrimaryKey>, crate::Error>
243243
where
244244
Cl: schema::SerializedCollection,
245-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + ?Sized,
245+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + ?Sized,
246246
{
247247
let contents = Cl::serialize(item)?;
248248
self.connection.insert::<Cl, _, _>(Some(id), contents)
@@ -268,7 +268,7 @@ where
268268
contents: B,
269269
) -> Result<CollectionHeader<Cl::PrimaryKey>, crate::Error>
270270
where
271-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + ?Sized,
271+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + ?Sized,
272272
{
273273
self.connection.insert::<Cl, _, B>(Some(id), contents)
274274
}
@@ -331,7 +331,7 @@ where
331331
/// ```
332332
pub fn get<PrimaryKey>(&self, id: &PrimaryKey) -> Result<Option<OwnedDocument>, Error>
333333
where
334-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + ?Sized,
334+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + ?Sized,
335335
{
336336
self.connection.get::<Cl, _>(id)
337337
}
@@ -358,7 +358,7 @@ where
358358
where
359359
DocumentIds: IntoIterator<Item = &'id PrimaryKey, IntoIter = I> + Send + Sync,
360360
I: Iterator<Item = &'id PrimaryKey> + Send + Sync,
361-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + 'id + ?Sized,
361+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + 'id + ?Sized,
362362
{
363363
self.connection.get_multiple::<Cl, _, _, _>(ids)
364364
}
@@ -386,7 +386,7 @@ where
386386
pub fn list<PrimaryKey, R>(&'a self, ids: R) -> List<'a, Cn, Cl, PrimaryKey>
387387
where
388388
R: Into<Range<&'a PrimaryKey>>,
389-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + PartialEq + 'a + ?Sized,
389+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + 'a + ?Sized,
390390
Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
391391
{
392392
List::new(MaybeOwned::Borrowed(self), RangeRef::borrowed(ids.into()))
@@ -417,10 +417,8 @@ where
417417
prefix: &'a PrimaryKey,
418418
) -> List<'a, Cn, Cl, PrimaryKey>
419419
where
420-
PrimaryKey: IntoPrefixRange<'a, Cl::PrimaryKey>
421-
+ for<'k> KeyEncoding<'k, Cl::PrimaryKey>
422-
+ PartialEq
423-
+ ?Sized,
420+
PrimaryKey:
421+
IntoPrefixRange<'a, Cl::PrimaryKey> + KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized,
424422
Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
425423
{
426424
List::new(MaybeOwned::Borrowed(self), prefix.to_prefix_range())
@@ -483,7 +481,7 @@ impl<'a, Cn, Cl, PrimaryKey> List<'a, Cn, Cl, PrimaryKey>
483481
where
484482
Cl: schema::Collection,
485483
Cn: Connection,
486-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + PartialEq + 'a + ?Sized,
484+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + 'a + ?Sized,
487485
Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
488486
{
489487
pub(crate) const fn new(
@@ -673,7 +671,7 @@ where
673671
V::Key: Borrow<Key> + PartialEq<Key>,
674672
V: schema::SerializedView,
675673
Cn: Connection,
676-
Key: for<'k> KeyEncoding<'k, V::Key> + PartialEq + ?Sized,
674+
Key: KeyEncoding<V::Key> + PartialEq + ?Sized,
677675
{
678676
const fn new(connection: &'a Cn) -> Self {
679677
Self {
@@ -703,7 +701,7 @@ where
703701
#[allow(clippy::missing_const_for_fn)] // false positive, destructors
704702
pub fn with_key<K>(self, key: &'a K) -> View<'a, Cn, V, K>
705703
where
706-
K: for<'k> KeyEncoding<'k, V::Key> + PartialEq + ?Sized,
704+
K: KeyEncoding<V::Key> + PartialEq + ?Sized,
707705
V::Key: Borrow<K> + PartialEq<K>,
708706
{
709707
View {
@@ -800,7 +798,7 @@ where
800798
/// ```
801799
pub fn with_key_prefix<K>(self, prefix: &'a K) -> View<'a, Cn, V, K>
802800
where
803-
K: for<'k> KeyEncoding<'k, V::Key> + IntoPrefixRange<'a, V::Key> + PartialEq + ?Sized,
801+
K: KeyEncoding<V::Key> + IntoPrefixRange<'a, V::Key> + PartialEq + ?Sized,
804802
V::Key: Borrow<K> + PartialEq<K>,
805803
{
806804
View {
@@ -1261,7 +1259,7 @@ where
12611259
) -> Result<CollectionHeader<Cl::PrimaryKey>, crate::Error>
12621260
where
12631261
Cl: schema::SerializedCollection,
1264-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + ?Sized,
1262+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + ?Sized,
12651263
{
12661264
let contents = Cl::serialize(item)?;
12671265
self.connection.insert::<Cl, _, _>(Some(id), contents).await
@@ -1292,7 +1290,7 @@ where
12921290
contents: B,
12931291
) -> Result<CollectionHeader<Cl::PrimaryKey>, crate::Error>
12941292
where
1295-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + ?Sized,
1293+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + ?Sized,
12961294
{
12971295
self.connection.insert::<Cl, _, B>(Some(id), contents).await
12981296
}
@@ -1365,7 +1363,7 @@ where
13651363
/// ```
13661364
pub async fn get<PrimaryKey>(&self, id: &PrimaryKey) -> Result<Option<OwnedDocument>, Error>
13671365
where
1368-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + ?Sized,
1366+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + ?Sized,
13691367
{
13701368
self.connection.get::<Cl, _>(id).await
13711369
}
@@ -1398,7 +1396,7 @@ where
13981396
where
13991397
DocumentIds: IntoIterator<Item = &'id PrimaryKey, IntoIter = I> + Send + Sync,
14001398
I: Iterator<Item = &'id PrimaryKey> + Send + Sync,
1401-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + 'id + ?Sized,
1399+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + 'id + ?Sized,
14021400
{
14031401
self.connection.get_multiple::<Cl, _, _, _>(ids).await
14041402
}
@@ -1428,7 +1426,7 @@ where
14281426
pub fn list<PrimaryKey, R>(&'a self, ids: R) -> AsyncList<'a, Cn, Cl, PrimaryKey>
14291427
where
14301428
R: Into<RangeRef<'a, Cl::PrimaryKey, PrimaryKey>>,
1431-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + PartialEq + ?Sized,
1429+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized,
14321430
Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
14331431
{
14341432
AsyncList::new(MaybeOwned::Borrowed(self), ids.into())
@@ -1457,10 +1455,8 @@ where
14571455
prefix: &'a PrimaryKey,
14581456
) -> AsyncList<'a, Cn, Cl, PrimaryKey>
14591457
where
1460-
PrimaryKey: IntoPrefixRange<'a, Cl::PrimaryKey>
1461-
+ for<'k> KeyEncoding<'k, Cl::PrimaryKey>
1462-
+ PartialEq
1463-
+ ?Sized,
1458+
PrimaryKey:
1459+
IntoPrefixRange<'a, Cl::PrimaryKey> + KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized,
14641460
Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
14651461
{
14661462
AsyncList::new(MaybeOwned::Borrowed(self), prefix.to_prefix_range())
@@ -1508,7 +1504,7 @@ where
15081504
pub(crate) struct AsyncListBuilder<'a, Cn, Cl, PrimaryKey>
15091505
where
15101506
Cl: schema::Collection,
1511-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + PartialEq + ?Sized,
1507+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized,
15121508
Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
15131509
{
15141510
collection: MaybeOwned<'a, AsyncCollection<'a, Cn, Cl>>,
@@ -1608,7 +1604,7 @@ where
16081604
pub(crate) enum ListState<'a, Cn, Cl, PrimaryKey>
16091605
where
16101606
Cl: schema::Collection,
1611-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + PartialEq + ?Sized,
1607+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized,
16121608
Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
16131609
{
16141610
Pending(Option<AsyncListBuilder<'a, Cn, Cl, PrimaryKey>>),
@@ -1621,7 +1617,7 @@ where
16211617
pub struct AsyncList<'a, Cn, Cl, PrimaryKey>
16221618
where
16231619
Cl: schema::Collection,
1624-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + PartialEq + ?Sized,
1620+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized,
16251621
Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
16261622
{
16271623
state: ListState<'a, Cn, Cl, PrimaryKey>,
@@ -1631,7 +1627,7 @@ impl<'a, Cn, Cl, PrimaryKey> AsyncList<'a, Cn, Cl, PrimaryKey>
16311627
where
16321628
Cl: schema::Collection,
16331629
Cn: AsyncConnection,
1634-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + PartialEq + ?Sized,
1630+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized,
16351631
Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey>,
16361632
{
16371633
pub(crate) const fn new(
@@ -1747,7 +1743,7 @@ impl<'a, Cn, Cl, PrimaryKey> Future for AsyncList<'a, Cn, Cl, PrimaryKey>
17471743
where
17481744
Cn: AsyncConnection,
17491745
Cl: schema::Collection + Unpin,
1750-
PrimaryKey: for<'k> KeyEncoding<'k, Cl::PrimaryKey> + PartialEq + ?Sized + Unpin,
1746+
PrimaryKey: KeyEncoding<Cl::PrimaryKey> + PartialEq + ?Sized + Unpin,
17511747
Cl::PrimaryKey: Borrow<PrimaryKey> + PartialEq<PrimaryKey> + Unpin,
17521748
{
17531749
type Output = Result<Vec<OwnedDocument>, Error>;
@@ -1854,7 +1850,7 @@ impl<'a, Cn, V, Key> AsyncView<'a, Cn, V, Key>
18541850
where
18551851
V: schema::SerializedView,
18561852
Cn: AsyncConnection,
1857-
Key: for<'k> KeyEncoding<'k, V::Key> + PartialEq + ?Sized,
1853+
Key: KeyEncoding<V::Key> + PartialEq + ?Sized,
18581854
V::Key: Borrow<Key> + PartialEq<Key>,
18591855
{
18601856
const fn new(connection: &'a Cn) -> Self {
@@ -1891,7 +1887,7 @@ where
18911887
#[allow(clippy::missing_const_for_fn)] // false positive, destructors
18921888
pub fn with_key<K>(self, key: &'a K) -> AsyncView<'a, Cn, V, K>
18931889
where
1894-
K: for<'k> KeyEncoding<'k, V::Key> + PartialEq + ?Sized,
1890+
K: KeyEncoding<V::Key> + PartialEq + ?Sized,
18951891
V::Key: Borrow<K> + PartialEq<K>,
18961892
{
18971893
AsyncView {
@@ -1968,7 +1964,7 @@ where
19681964
range: R,
19691965
) -> AsyncView<'a, Cn, V, K>
19701966
where
1971-
K: for<'k> KeyEncoding<'k, V::Key> + PartialEq + ?Sized,
1967+
K: KeyEncoding<V::Key> + PartialEq + ?Sized,
19721968
V::Key: Borrow<K> + PartialEq<K>,
19731969
{
19741970
AsyncView {
@@ -2008,7 +2004,7 @@ where
20082004
/// ```
20092005
pub fn with_key_prefix<K>(self, prefix: &'a K) -> AsyncView<'a, Cn, V, K>
20102006
where
2011-
K: for<'k> KeyEncoding<'k, V::Key> + IntoPrefixRange<'a, V::Key> + PartialEq + ?Sized,
2007+
K: KeyEncoding<V::Key> + IntoPrefixRange<'a, V::Key> + PartialEq + ?Sized,
20122008
V::Key: Borrow<K> + PartialEq<K>,
20132009
{
20142010
AsyncView {
@@ -2291,7 +2287,7 @@ where
22912287

22922288
impl<'a, KOwned, KBorrowed> QueryKey<'a, KOwned, KBorrowed>
22932289
where
2294-
KBorrowed: for<'k> KeyEncoding<'k, KOwned> + PartialEq + ?Sized,
2290+
KBorrowed: KeyEncoding<KOwned> + PartialEq + ?Sized,
22952291
KOwned: for<'k> Key<'k> + Borrow<KBorrowed> + PartialEq<KBorrowed>,
22962292
{
22972293
/// Converts this key to a serialized format using the [`Key`] trait.
@@ -2503,7 +2499,7 @@ where
25032499
/// Serializes the range's contained values to big-endian bytes.
25042500
pub fn as_ord_bytes(&'a self) -> Result<Range<Bytes>, TBorrowed::Error>
25052501
where
2506-
TBorrowed: KeyEncoding<'a, TOwned>,
2502+
TBorrowed: KeyEncoding<TOwned>,
25072503
TOwned: for<'k> Key<'k> + Borrow<TBorrowed>,
25082504
{
25092505
Ok(Range {
@@ -2517,7 +2513,7 @@ impl Range<Bytes> {
25172513
/// Deserializes the range's contained values from big-endian bytes.
25182514
pub fn deserialize<T: for<'k> Key<'k>>(
25192515
&self,
2520-
) -> Result<Range<T>, <T as KeyEncoding<'_, T>>::Error> {
2516+
) -> Result<Range<T>, <T as KeyEncoding<T>>::Error> {
25212517
Ok(Range {
25222518
start: self.start.deserialize()?,
25232519
end: self.start.deserialize()?,
@@ -2563,7 +2559,7 @@ where
25632559
/// Serializes the contained value to big-endian bytes.
25642560
pub fn as_ord_bytes(&'a self) -> Result<Bound<Bytes>, TBorrowed::Error>
25652561
where
2566-
TBorrowed: KeyEncoding<'a, TOwned>,
2562+
TBorrowed: KeyEncoding<TOwned>,
25672563
TOwned: for<'k> Key<'k> + Borrow<TBorrowed>,
25682564
{
25692565
match self {
@@ -2582,7 +2578,7 @@ impl Bound<Bytes> {
25822578
/// Deserializes the bound's contained value from big-endian bytes.
25832579
pub fn deserialize<T: for<'k> Key<'k>>(
25842580
&self,
2585-
) -> Result<Bound<T>, <T as KeyEncoding<'_, T>>::Error> {
2581+
) -> Result<Bound<T>, <T as KeyEncoding<T>>::Error> {
25862582
match self {
25872583
Self::Unbounded => Ok(Bound::Unbounded),
25882584
Self::Included(value) => Ok(Bound::Included(T::from_ord_bytes(ByteSource::Borrowed(
@@ -3397,7 +3393,7 @@ impl<'k> Key<'k> for SensitiveString {
33973393
}
33983394
}
33993395

3400-
impl<'k> KeyEncoding<'k, Self> for SensitiveString {
3396+
impl KeyEncoding<Self> for SensitiveString {
34013397
type Error = FromUtf8Error;
34023398

34033399
const LENGTH: Option<usize> = None;
@@ -3409,7 +3405,7 @@ impl<'k> KeyEncoding<'k, Self> for SensitiveString {
34093405
visitor.visit_type(KeyKind::String);
34103406
}
34113407

3412-
fn as_ord_bytes(&'k self) -> Result<std::borrow::Cow<'k, [u8]>, Self::Error> {
3408+
fn as_ord_bytes(&self) -> Result<std::borrow::Cow<'_, [u8]>, Self::Error> {
34133409
self.0.as_ord_bytes()
34143410
}
34153411
}
@@ -3461,7 +3457,7 @@ impl<'k> Key<'k> for SensitiveBytes {
34613457
}
34623458
}
34633459

3464-
impl<'k> KeyEncoding<'k, Self> for SensitiveBytes {
3460+
impl KeyEncoding<Self> for SensitiveBytes {
34653461
type Error = Infallible;
34663462

34673463
const LENGTH: Option<usize> = None;
@@ -3473,7 +3469,7 @@ impl<'k> KeyEncoding<'k, Self> for SensitiveBytes {
34733469
visitor.visit_type(KeyKind::Bytes);
34743470
}
34753471

3476-
fn as_ord_bytes(&'k self) -> Result<std::borrow::Cow<'k, [u8]>, Self::Error> {
3472+
fn as_ord_bytes(&self) -> Result<std::borrow::Cow<'_, [u8]>, Self::Error> {
34773473
self.0.as_ord_bytes()
34783474
}
34793475
}

0 commit comments

Comments
 (0)