Skip to content

Commit 59c347f

Browse files
authored
RUST-1887 Make BindRawBsonRef a little more user-friendly (#565)
1 parent 431d448 commit 59c347f

File tree

3 files changed

+56
-25
lines changed

3 files changed

+56
-25
lines changed

src/raw.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ pub use self::{
143143
RawRegexRef,
144144
},
145145
document::RawDocument,
146-
document_buf::{BindRawBsonRef, RawDocumentBuf},
146+
document_buf::{BindRawBsonRef, BindValue, RawDocumentBuf},
147147
iter::{RawElement, RawIter},
148148
};
149149

src/raw/bson_ref.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,12 @@ impl From<Decimal128> for RawBsonRef<'_> {
489489
}
490490
}
491491

492+
impl<'a> From<&'a RawBson> for RawBsonRef<'a> {
493+
fn from(value: &'a RawBson) -> Self {
494+
value.as_raw_bson_ref()
495+
}
496+
}
497+
492498
/// A BSON binary value referencing raw bytes stored elsewhere.
493499
#[derive(Clone, Copy, Debug, PartialEq)]
494500
pub struct RawBinaryRef<'a> {

src/raw/document_buf.rs

Lines changed: 49 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -325,52 +325,77 @@ impl Borrow<RawDocument> for RawDocumentBuf {
325325

326326
/// Types that can be consumed to produce raw bson references valid for a limited lifetime.
327327
/// Conceptually a union between `T: Into<RawBson>` and `T: Into<RawBsonRef>`; if your type
328-
/// implements `Into<RawBsonRef>` it will automatically implement this, but if it only
329-
/// implements `Into<RawBson>` it will need to manually define the trivial impl.
330-
pub trait BindRawBsonRef {
331-
fn bind<F, R>(self, f: F) -> R
332-
where
333-
F: for<'a> FnOnce(RawBsonRef<'a>) -> R;
334-
}
328+
/// implements `Into<RawBsonRef>` it will automatically implement this, but if it
329+
/// implements `Into<RawBson>` it will need to also define an impl of `BindRawBsonRef`:
330+
/// ```
331+
/// # use bson::raw::{BindRawBsonRef, BindValue, RawBson};
332+
/// # struct MyType;
333+
/// # impl Into<RawBson> for MyType {
334+
/// # fn into(self: Self) -> RawBson { todo!() }
335+
/// # }
336+
/// impl BindRawBsonRef for MyType {
337+
/// type Target = BindValue<Self>;
338+
/// }
339+
/// ```
340+
pub trait BindRawBsonRef: Sized {
341+
type Target: BindHelper<Target = Self>;
335342

336-
impl<'a, T: Into<RawBsonRef<'a>>> BindRawBsonRef for T {
337343
fn bind<F, R>(self, f: F) -> R
338344
where
339-
F: for<'b> FnOnce(RawBsonRef<'b>) -> R,
345+
F: for<'a> FnOnce(RawBsonRef<'a>) -> R,
340346
{
341-
f(self.into())
347+
<Self::Target as BindHelper>::bind(self, f)
342348
}
343349
}
344350

345-
impl BindRawBsonRef for RawBson {
346-
fn bind<F, R>(self, f: F) -> R
351+
#[doc(hidden)]
352+
pub trait BindHelper {
353+
type Target;
354+
fn bind<F, R>(target: Self::Target, f: F) -> R
355+
where
356+
F: for<'b> FnOnce(RawBsonRef<'b>) -> R;
357+
}
358+
359+
/// A struct to use as the `Target` of a [`BindRawBsonRef`] impl for custom types.
360+
pub struct BindValue<A>(std::marker::PhantomData<A>);
361+
#[doc(hidden)]
362+
pub struct BindRef<A>(std::marker::PhantomData<A>);
363+
364+
impl<A: Into<RawBson>> BindHelper for BindValue<A> {
365+
type Target = A;
366+
367+
fn bind<F, R>(target: Self::Target, f: F) -> R
347368
where
348369
F: for<'a> FnOnce(RawBsonRef<'a>) -> R,
349370
{
350-
f(self.as_raw_bson_ref())
371+
f(target.into().as_raw_bson_ref())
351372
}
352373
}
353374

354-
impl BindRawBsonRef for &RawBson {
355-
fn bind<F, R>(self, f: F) -> R
375+
impl<'a, A: Into<RawBsonRef<'a>> + 'a> BindHelper for BindRef<A> {
376+
type Target = A;
377+
378+
fn bind<F, R>(target: Self::Target, f: F) -> R
356379
where
357-
F: for<'a> FnOnce(RawBsonRef<'a>) -> R,
380+
F: for<'b> FnOnce(RawBsonRef<'a>) -> R,
358381
{
359-
f(self.as_raw_bson_ref())
382+
f(target.into())
360383
}
361384
}
362385

386+
impl<'a, T: Into<RawBsonRef<'a>> + 'a> BindRawBsonRef for T {
387+
type Target = BindRef<T>;
388+
}
389+
390+
impl BindRawBsonRef for RawBson {
391+
type Target = BindValue<Self>;
392+
}
393+
363394
macro_rules! raw_bson_from_impls {
364395
($($t:ty),+$(,)?) => {
365396
$(
366397
impl BindRawBsonRef for $t {
367-
fn bind<F, R>(self, f: F) -> R
368-
where
369-
F: for<'a> FnOnce(RawBsonRef<'a>) -> R,
370-
{
371-
let tmp: RawBson = self.into();
372-
f(tmp.as_raw_bson_ref())
373-
}
398+
type Target = BindValue<Self>;
374399
}
375400
)+
376401
};

0 commit comments

Comments
 (0)