bson/raw/
document_buf.rs

1use std::{
2    borrow::{Borrow, Cow},
3    convert::TryFrom,
4    ops::Deref,
5};
6
7use crate::{
8    raw::{doc_writer::DocWriter, CStr},
9    Document,
10};
11
12use super::{bson::RawBson, iter::Iter, RawBsonRef, RawDocument, RawIter, Result};
13
14/// An owned BSON document (akin to [`std::path::PathBuf`]), backed by a buffer of raw BSON bytes.
15/// This can be created from a `Vec<u8>` or a [`crate::Document`].
16///
17/// Accessing elements within a [`RawDocumentBuf`] is similar to element access in
18/// [`crate::Document`], but because the contents are parsed during iteration instead of at creation
19/// time, format errors can happen at any time during use.
20///
21/// Iterating over a [`RawDocumentBuf`] yields either an error or a key-value pair that borrows from
22/// the original document without making any additional allocations.
23///
24/// ```
25/// # use bson::error::Error;
26/// use bson::raw::RawDocumentBuf;
27///
28/// let doc = RawDocumentBuf::from_bytes(b"\x13\x00\x00\x00\x02hi\x00\x06\x00\x00\x00y'all\x00\x00".to_vec())?;
29/// let mut iter = doc.iter();
30/// let (key, value) = iter.next().unwrap()?;
31/// assert_eq!(key, "hi");
32/// assert_eq!(value.as_str(), Some("y'all"));
33/// assert!(iter.next().is_none());
34/// # Ok::<(), Error>(())
35/// ```
36///
37/// This type implements [`Deref`] to [`RawDocument`], meaning that all methods on [`RawDocument`]
38/// are available on [`RawDocumentBuf`] values as well. This includes [`RawDocument::get`] or any of
39/// the type-specific getters, such as [`RawDocument::get_object_id`] or [`RawDocument::get_str`].
40/// Note that accessing elements is an O(N) operation, as it requires iterating through the document
41/// from the beginning to find the requested key.
42///
43/// ```
44/// use bson::raw::RawDocumentBuf;
45///
46/// let doc = RawDocumentBuf::from_bytes(b"\x13\x00\x00\x00\x02hi\x00\x06\x00\x00\x00y'all\x00\x00".to_vec())?;
47/// assert_eq!(doc.get_str("hi")?, "y'all");
48/// # Ok::<(), Box<dyn std::error::Error>>(())
49/// ```
50#[derive(Clone, PartialEq)]
51pub struct RawDocumentBuf {
52    data: Vec<u8>,
53}
54
55impl RawDocumentBuf {
56    /// Creates a new, empty [`RawDocumentBuf`].
57    pub fn new() -> Self {
58        let mut data = Vec::new();
59        DocWriter::open(&mut data);
60        Self { data }
61    }
62
63    /// Constructs a new [`RawDocumentBuf`], validating _only_ the
64    /// following invariants:
65    ///   * `data` is at least five bytes long (the minimum for a valid BSON document)
66    ///   * the initial four bytes of `data` accurately represent the length of the bytes as
67    ///     required by the BSON spec.
68    ///   * the last byte of `data` is a 0
69    ///
70    /// Note that the internal structure of the bytes representing the
71    /// BSON elements is _not_ validated at all by this method. If the
72    /// bytes do not conform to the BSON spec, then method calls on
73    /// the RawDocument will return Errors where appropriate.
74    ///
75    /// ```
76    /// # use bson::raw::RawDocumentBuf;
77    /// let doc = RawDocumentBuf::from_bytes(b"\x05\0\0\0\0".to_vec())?;
78    /// # Ok::<(), bson::error::Error>(())
79    /// ```
80    pub fn from_bytes(data: Vec<u8>) -> Result<Self> {
81        let _ = RawDocument::from_bytes(data.as_slice())?;
82        Ok(Self { data })
83    }
84
85    /// Constructs a new [`RawDocumentBuf`], validating _only_ the
86    /// following invariants:
87    ///   * `data` is at least five bytes long (the minimum for a valid BSON document)
88    ///   * the initial four bytes of `data` accurately represent the length of the bytes as
89    ///     required by the BSON spec.
90    ///   * the last byte of `data` is a 0
91    ///
92    /// Note that the internal structure of the bytes representing the
93    /// BSON elements is _not_ validated at all by this method. If the
94    /// bytes do not conform to the BSON spec, then method calls on
95    /// the RawDocument will return Errors where appropriate.
96    ///
97    /// ```
98    /// # use bson::raw::RawDocumentBuf;
99    /// let doc = RawDocumentBuf::from_reader(b"\x05\0\0\0\0".as_slice())?;
100    /// # Ok::<(), bson::error::Error>(())
101    /// ```
102    pub fn from_reader<R: std::io::Read>(reader: R) -> Result<Self> {
103        let buf = crate::raw::reader_to_vec(reader)?;
104        Self::from_bytes(buf)
105    }
106
107    /// Gets an iterator over the elements in the [`RawDocumentBuf`], which yields
108    /// `Result<(&str, RawBson<'_>)>`.
109    ///
110    /// ```
111    /// use bson::{doc, raw::RawDocumentBuf};
112    ///
113    /// let doc = RawDocumentBuf::try_from(&doc! { "ferris": true })?;
114    ///
115    /// for element in doc.iter() {
116    ///     let (key, value) = element?;
117    ///     assert_eq!(key, "ferris");
118    ///     assert_eq!(value.as_bool(), Some(true));
119    /// }
120    /// # Ok::<(), bson::error::Error>(())
121    /// ```
122    ///
123    /// # Note:
124    ///
125    /// There is no owning iterator for [`RawDocumentBuf`]. If you need ownership over
126    /// elements that might need to allocate, you must explicitly convert
127    /// them to owned types yourself.
128    pub fn iter(&self) -> Iter<'_> {
129        Iter::new(self)
130    }
131
132    /// Gets an iterator over the elements in the [`RawDocumentBuf`],
133    /// which yields `Result<RawElement<'_>>` values. These hold a
134    /// reference to the underlying document but do not explicitly
135    /// resolve the values.
136    ///
137    /// This iterator, which underpins the implementation of the
138    /// default iterator, produces `RawElement` objects that hold a
139    /// view onto the document but do not parse out or construct
140    /// values until the `.value()` or `.try_into()` methods are
141    /// called.
142    ///
143    /// # Note:
144    ///
145    /// There is no owning iterator for [`RawDocumentBuf`]. If you
146    /// need ownership over elements that might need to allocate, you
147    /// must explicitly convert them to owned types yourself.
148    pub fn iter_elements(&self) -> RawIter<'_> {
149        RawIter::new(self)
150    }
151
152    /// Return the contained data as a `Vec<u8>`
153    ///
154    /// ```
155    /// use bson::{doc, raw::RawDocumentBuf};
156    ///
157    /// let doc = RawDocumentBuf::try_from(&doc!{})?;
158    /// assert_eq!(doc.into_bytes(), b"\x05\x00\x00\x00\x00".to_vec());
159    /// # Ok::<(), bson::error::Error>(())
160    /// ```
161    pub fn into_bytes(self) -> Vec<u8> {
162        self.data
163    }
164
165    /// Append a key value pair to the end of the document without checking to see if
166    /// the key already exists.
167    ///
168    /// It is a user error to append the same key more than once to the same document, and it may
169    /// result in errors when communicating with MongoDB.
170    ///
171    /// Keys can be a [`&CStr`](crate::raw::CStr) or [`CString`](crate::raw::CString).
172    ///
173    /// Values can be any type that can be converted to either borrowed or owned raw bson data; see
174    /// the documentation for [BindRawBsonRef] for more details.
175    /// ```
176    /// # use bson::error::Error;
177    /// use bson::{Document, doc, raw::{cstr, RawBsonRef, RawDocumentBuf}};
178    ///
179    /// let mut doc = RawDocumentBuf::new();
180    /// // `&str` and `i32` both convert to `RawBsonRef`
181    /// doc.append(cstr!("a string"), "some string");
182    /// doc.append(cstr!("an integer"), 12_i32);
183    ///
184    /// let mut subdoc = RawDocumentBuf::new();
185    /// subdoc.append(cstr!("a key"), true);
186    /// doc.append(cstr!("a borrowed document"), &subdoc);
187    /// doc.append(cstr!("an owned document"), subdoc);
188    ///
189    /// let expected = doc! {
190    ///     "a string": "some string",
191    ///     "an integer": 12_i32,
192    ///     "a borrowed document": { "a key": true },
193    ///     "an owned document": { "a key": true },
194    /// };
195    ///
196    /// assert_eq!(Document::try_from(doc)?, expected);
197    /// # Ok::<(), Error>(())
198    /// ```
199    pub fn append(&mut self, key: impl AsRef<CStr>, value: impl BindRawBsonRef) {
200        self.data.pop();
201        let key = key.as_ref();
202        value.bind(|value_ref| {
203            let mut writer = DocWriter::resume(&mut self.data, 0);
204            writer.append_key(value_ref.element_type(), key);
205            value_ref.append_to(writer.buffer());
206        });
207    }
208}
209
210impl<K: AsRef<CStr>, B: BindRawBsonRef> FromIterator<(K, B)> for RawDocumentBuf {
211    fn from_iter<T: IntoIterator<Item = (K, B)>>(iter: T) -> Self {
212        let mut buf = RawDocumentBuf::new();
213        for (k, v) in iter {
214            buf.append(k, v);
215        }
216        buf
217    }
218}
219
220impl Default for RawDocumentBuf {
221    fn default() -> Self {
222        Self::new()
223    }
224}
225
226#[cfg(feature = "serde")]
227impl<'de> serde::Deserialize<'de> for RawDocumentBuf {
228    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
229    where
230        D: serde::Deserializer<'de>,
231    {
232        Ok(super::serde::OwnedOrBorrowedRawDocument::deserialize(deserializer)?.into_owned())
233    }
234}
235
236#[cfg(feature = "serde")]
237impl serde::Serialize for RawDocumentBuf {
238    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
239    where
240        S: serde::Serializer,
241    {
242        let doc: &RawDocument = self.deref();
243        doc.serialize(serializer)
244    }
245}
246
247impl std::fmt::Debug for RawDocumentBuf {
248    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
249        f.debug_struct("RawDocumentBuf")
250            .field("data", &hex::encode(&self.data))
251            .finish()
252    }
253}
254
255impl From<RawDocumentBuf> for Cow<'_, RawDocument> {
256    fn from(rd: RawDocumentBuf) -> Self {
257        Cow::Owned(rd)
258    }
259}
260
261impl<'a> From<&'a RawDocumentBuf> for Cow<'a, RawDocument> {
262    fn from(rd: &'a RawDocumentBuf) -> Self {
263        Cow::Borrowed(rd.as_ref())
264    }
265}
266
267impl TryFrom<&Document> for RawDocumentBuf {
268    type Error = crate::error::Error;
269
270    fn try_from(doc: &Document) -> std::result::Result<Self, Self::Error> {
271        let mut out = vec![];
272        doc.append_to(&mut out)?;
273        RawDocumentBuf::from_bytes(out)
274    }
275}
276
277impl TryFrom<Document> for RawDocumentBuf {
278    type Error = crate::error::Error;
279
280    fn try_from(doc: Document) -> std::result::Result<Self, Self::Error> {
281        RawDocumentBuf::try_from(&doc)
282    }
283}
284
285impl<'a> IntoIterator for &'a RawDocumentBuf {
286    type IntoIter = Iter<'a>;
287    type Item = Result<(&'a CStr, RawBsonRef<'a>)>;
288
289    fn into_iter(self) -> Iter<'a> {
290        self.iter()
291    }
292}
293
294impl AsRef<RawDocument> for RawDocumentBuf {
295    fn as_ref(&self) -> &RawDocument {
296        RawDocument::new_unchecked(&self.data)
297    }
298}
299
300impl Deref for RawDocumentBuf {
301    type Target = RawDocument;
302
303    fn deref(&self) -> &Self::Target {
304        RawDocument::new_unchecked(&self.data)
305    }
306}
307
308impl Borrow<RawDocument> for RawDocumentBuf {
309    fn borrow(&self) -> &RawDocument {
310        self.deref()
311    }
312}
313
314/// Types that can be consumed to produce raw bson references valid for a limited lifetime.
315/// Conceptually a union between `T: Into<RawBson>` and `T: Into<RawBsonRef>`; if your type
316/// implements `Into<RawBsonRef>` it will automatically implement this, but if it
317/// implements `Into<RawBson>` it will need to also define an impl of `BindRawBsonRef`:
318/// ```
319/// # use bson::raw::{BindRawBsonRef, BindValue, RawBson};
320/// # struct MyType;
321/// # impl Into<RawBson> for MyType {
322/// #  fn into(self: Self) -> RawBson { todo!() }
323/// # }
324/// impl BindRawBsonRef for MyType {
325///   type Target = BindValue<Self>;
326/// }
327/// ```
328#[allow(missing_docs)]
329pub trait BindRawBsonRef: Sized {
330    type Target: BindHelper<Target = Self>;
331
332    fn bind<F, R>(self, f: F) -> R
333    where
334        F: for<'a> FnOnce(RawBsonRef<'a>) -> R,
335    {
336        <Self::Target as BindHelper>::bind(self, f)
337    }
338}
339
340#[doc(hidden)]
341pub trait BindHelper {
342    type Target;
343    fn bind<F, R>(target: Self::Target, f: F) -> R
344    where
345        F: for<'b> FnOnce(RawBsonRef<'b>) -> R;
346}
347
348/// A struct to use as the `Target` of a [`BindRawBsonRef`] impl for custom types.
349pub struct BindValue<A>(std::marker::PhantomData<A>);
350#[doc(hidden)]
351pub struct BindRef<A>(std::marker::PhantomData<A>);
352
353impl<A: Into<RawBson>> BindHelper for BindValue<A> {
354    type Target = A;
355
356    fn bind<F, R>(target: Self::Target, f: F) -> R
357    where
358        F: for<'a> FnOnce(RawBsonRef<'a>) -> R,
359    {
360        f(target.into().as_raw_bson_ref())
361    }
362}
363
364impl<'a, A: Into<RawBsonRef<'a>> + 'a> BindHelper for BindRef<A> {
365    type Target = A;
366
367    fn bind<F, R>(target: Self::Target, f: F) -> R
368    where
369        F: for<'b> FnOnce(RawBsonRef<'a>) -> R,
370    {
371        f(target.into())
372    }
373}
374
375impl<'a, T: Into<RawBsonRef<'a>> + 'a> BindRawBsonRef for T {
376    type Target = BindRef<T>;
377}
378
379impl BindRawBsonRef for RawBson {
380    type Target = BindValue<Self>;
381}
382
383macro_rules! raw_bson_from_impls {
384    ($($t:ty),+$(,)?) => {
385        $(
386            impl BindRawBsonRef for $t {
387                type Target = BindValue<Self>;
388            }
389        )+
390    };
391}
392
393raw_bson_from_impls! {
394    &crate::binary::Vector,
395    crate::Binary,
396    crate::DbPointer,
397    super::RawArrayBuf,
398    RawDocumentBuf,
399    super::RawJavaScriptCodeWithScope,
400    crate::Regex,
401    String,
402    crate::binary::Vector,
403}