@@ -189,43 +189,38 @@ impl RawDocumentBuf {
189189 ///
190190 /// If the provided key contains an interior null byte, this method will panic.
191191 ///
192+ /// Values can be any type that can be converted to either borrowed or owned raw bson data; see
193+ /// the documentation for [BindRawBsonRef] for more details.
192194 /// ```
193195 /// # use bson::raw::Error;
194- /// use bson::{doc, raw::RawDocumentBuf};
196+ /// use bson::{doc, raw::{RawBsonRef, RawDocumentBuf} };
195197 ///
196198 /// let mut doc = RawDocumentBuf::new();
199+ /// // `&str` and `i32` both convert to `RawBsonRef`
197200 /// doc.append("a string", "some string");
198201 /// doc.append("an integer", 12_i32);
199202 ///
200203 /// let mut subdoc = RawDocumentBuf::new();
201204 /// subdoc.append("a key", true);
202- /// doc.append("a document", subdoc);
205+ /// doc.append("a borrowed document", &subdoc);
206+ /// doc.append("an owned document", subdoc);
203207 ///
204208 /// let expected = doc! {
205209 /// "a string": "some string",
206210 /// "an integer": 12_i32,
207- /// "a document": { "a key": true },
211+ /// "a borrowed document": { "a key": true },
212+ /// "an owned document": { "a key": true },
208213 /// };
209214 ///
210215 /// assert_eq!(doc.to_document()?, expected);
211216 /// # Ok::<(), Error>(())
212217 /// ```
213- pub fn append ( & mut self , key : impl AsRef < str > , value : impl Into < RawBson > ) {
214- let value = value. into ( ) ;
215- self . append_ref ( key, value. as_raw_bson_ref ( ) )
216- }
217-
218- /// Append a key value pair to the end of the document without checking to see if
219- /// the key already exists.
220- ///
221- /// It is a user error to append the same key more than once to the same document, and it may
222- /// result in errors when communicating with MongoDB.
223- ///
224- /// If the provided key contains an interior null byte, this method will panic.
225- pub fn append_ref < ' a > ( & mut self , key : impl AsRef < str > , value : impl Into < RawBsonRef < ' a > > ) {
226- raw_writer:: RawWriter :: new ( & mut self . data )
227- . append ( key. as_ref ( ) , value. into ( ) )
228- . expect ( "key should not contain interior null byte" )
218+ pub fn append ( & mut self , key : impl AsRef < str > , value : impl BindRawBsonRef ) {
219+ value. bind ( |value_ref| {
220+ raw_writer:: RawWriter :: new ( & mut self . data )
221+ . append ( key. as_ref ( ) , value_ref)
222+ . expect ( "key should not contain interior null byte" )
223+ } )
229224 }
230225
231226 /// Convert this [`RawDocumentBuf`] to a [`Document`], returning an error
@@ -325,7 +320,7 @@ impl Borrow<RawDocument> for RawDocumentBuf {
325320 }
326321}
327322
328- impl < S : AsRef < str > , T : Into < RawBson > > FromIterator < ( S , T ) > for RawDocumentBuf {
323+ impl < S : AsRef < str > , T : BindRawBsonRef > FromIterator < ( S , T ) > for RawDocumentBuf {
329324 fn from_iter < I : IntoIterator < Item = ( S , T ) > > ( iter : I ) -> Self {
330325 let mut buf = RawDocumentBuf :: new ( ) ;
331326 for ( k, v) in iter {
@@ -334,3 +329,68 @@ impl<S: AsRef<str>, T: Into<RawBson>> FromIterator<(S, T)> for RawDocumentBuf {
334329 buf
335330 }
336331}
332+
333+ /// Types that can be consumed to produce raw bson references valid for a limited lifetime.
334+ /// Conceptually a union between `T: Into<RawBson>` and `T: Into<RawBsonRef>`; if your type
335+ /// implements `Into<RawBsonRef>` it will automatically implement this, but if it only
336+ /// implements `Into<RawBson>` it will need to manually define the trivial impl.
337+ pub trait BindRawBsonRef {
338+ fn bind < F , R > ( self , f : F ) -> R
339+ where
340+ F : for < ' a > FnOnce ( RawBsonRef < ' a > ) -> R ;
341+ }
342+
343+ impl < ' a , T : Into < RawBsonRef < ' a > > > BindRawBsonRef for T {
344+ fn bind < F , R > ( self , f : F ) -> R
345+ where
346+ F : for < ' b > FnOnce ( RawBsonRef < ' b > ) -> R ,
347+ {
348+ f ( self . into ( ) )
349+ }
350+ }
351+
352+ impl BindRawBsonRef for RawBson {
353+ fn bind < F , R > ( self , f : F ) -> R
354+ where
355+ F : for < ' a > FnOnce ( RawBsonRef < ' a > ) -> R ,
356+ {
357+ f ( self . as_raw_bson_ref ( ) )
358+ }
359+ }
360+
361+ impl BindRawBsonRef for & RawBson {
362+ fn bind < F , R > ( self , f : F ) -> R
363+ where
364+ F : for < ' a > FnOnce ( RawBsonRef < ' a > ) -> R ,
365+ {
366+ f ( self . as_raw_bson_ref ( ) )
367+ }
368+ }
369+
370+ macro_rules! raw_bson_from_impls {
371+ ( $( $t: ty) ,+$( , ) ?) => {
372+ $(
373+ impl BindRawBsonRef for $t {
374+ fn bind<F , R >( self , f: F ) -> R
375+ where
376+ F : for <' a> FnOnce ( RawBsonRef <' a>) -> R ,
377+ {
378+ let tmp: RawBson = self . into( ) ;
379+ f( tmp. as_raw_bson_ref( ) )
380+ }
381+ }
382+ ) +
383+ } ;
384+ }
385+
386+ raw_bson_from_impls ! {
387+ & crate :: binary:: Vector ,
388+ crate :: Binary ,
389+ crate :: DbPointer ,
390+ super :: RawArrayBuf ,
391+ RawDocumentBuf ,
392+ super :: RawJavaScriptCodeWithScope ,
393+ crate :: Regex ,
394+ String ,
395+ crate :: binary:: Vector ,
396+ }
0 commit comments