bson/raw/
document.rs

1use std::{
2    borrow::Cow,
3    convert::{TryFrom, TryInto},
4};
5
6use crate::{
7    error::{Error, Result},
8    raw::CStr,
9    Bson,
10    DateTime,
11    JavaScriptCodeWithScope,
12    RawBson,
13    RawJavaScriptCodeWithScope,
14    Timestamp,
15    Utf8Lossy,
16};
17
18use super::{
19    i32_from_slice,
20    iter::Iter,
21    try_to_str,
22    Error as RawError,
23    RawArray,
24    RawBinaryRef,
25    RawBsonRef,
26    RawDocumentBuf,
27    RawIter,
28    RawRegexRef,
29    Result as RawResult,
30    MIN_BSON_DOCUMENT_SIZE,
31};
32use crate::{oid::ObjectId, spec::ElementType, Document};
33
34/// A slice of a BSON document (akin to [`std::str`]). This can be created from a
35/// [`RawDocumentBuf`] or any type that contains valid BSON data, including static binary literals,
36/// [`Vec<u8>`](std::vec::Vec), or arrays.
37///
38/// This is an _unsized_ type, meaning that it must always be used behind a pointer like `&`. For an
39/// owned version of this type, see [`RawDocumentBuf`].
40///
41/// Accessing elements within a [`RawDocument`] is similar to element access in [`crate::Document`],
42/// but because the contents are parsed during iteration instead of at creation time, format errors
43/// can happen at any time during use.
44///
45/// Iterating over a [`RawDocument`] yields either an error or a key-value pair that borrows from
46/// the original document without making any additional allocations.
47/// ```
48/// # use bson::error::Error;
49/// use bson::raw::RawDocument;
50///
51/// let doc = RawDocument::from_bytes(b"\x13\x00\x00\x00\x02hi\x00\x06\x00\x00\x00y'all\x00\x00")?;
52/// let mut iter = doc.into_iter();
53/// let (key, value) = iter.next().unwrap()?;
54/// assert_eq!(key, "hi");
55/// assert_eq!(value.as_str(), Some("y'all"));
56/// assert!(iter.next().is_none());
57/// # Ok::<(), Error>(())
58/// ```
59///
60/// Individual elements can be accessed using [`RawDocument::get`] or any of
61/// the type-specific getters, such as [`RawDocument::get_object_id`] or
62/// [`RawDocument::get_str`]. Note that accessing elements is an O(N) operation, as it
63/// requires iterating through the document from the beginning to find the requested key.
64///
65/// ```
66/// use bson::raw::RawDocument;
67///
68/// let doc = RawDocument::from_bytes(b"\x13\x00\x00\x00\x02hi\x00\x06\x00\x00\x00y'all\x00\x00")?;
69/// assert_eq!(doc.get_str("hi")?, "y'all");
70/// # Ok::<(), Box<dyn std::error::Error>>(())
71/// ```
72#[derive(PartialEq)]
73#[repr(transparent)]
74pub struct RawDocument {
75    data: [u8],
76}
77
78impl RawDocument {
79    /// Constructs a new [`RawDocument`], validating _only_ the
80    /// following invariants:
81    ///   * `data` is at least five bytes long (the minimum for a valid BSON document)
82    ///   * the initial four bytes of `data` accurately represent the length of the bytes as
83    ///     required by the BSON spec.
84    ///   * the last byte of `data` is a 0
85    ///
86    /// Note that the internal structure of the bytes representing the
87    /// BSON elements is _not_ validated at all by this method. If the
88    /// bytes do not conform to the BSON spec, then method calls on
89    /// the [`RawDocument`] will return Errors where appropriate.
90    ///
91    /// ```
92    /// use bson::raw::RawDocument;
93    ///
94    /// let doc = RawDocument::from_bytes(b"\x05\0\0\0\0")?;
95    /// # Ok::<(), bson::error::Error>(())
96    /// ```
97    pub fn from_bytes<D: AsRef<[u8]> + ?Sized>(data: &D) -> RawResult<&RawDocument> {
98        let data = data.as_ref();
99
100        if data.len() < 5 {
101            return Err(Error::malformed_bytes("document too short"));
102        }
103
104        let length = i32_from_slice(data)?;
105
106        if data.len() as i32 != length {
107            return Err(Error::malformed_bytes("document length incorrect"));
108        }
109
110        if data[data.len() - 1] != 0 {
111            return Err(Error::malformed_bytes("document not null-terminated"));
112        }
113
114        Ok(RawDocument::new_unchecked(data))
115    }
116
117    /// Creates a new [`RawDocument`] referencing the provided data slice.
118    pub(crate) fn new_unchecked<D: AsRef<[u8]> + ?Sized>(data: &D) -> &RawDocument {
119        // SAFETY:
120        //
121        // Dereferencing a raw pointer requires unsafe due to the potential that the pointer is
122        // null, dangling, or misaligned. We know the pointer is not null or dangling due to the
123        // fact that it's created by a safe reference. Converting &[u8] to *const [u8] will be
124        // properly aligned due to them being references to the same type, and converting *const
125        // [u8] to *const RawDocument is aligned due to the fact that the only field in a
126        // RawDocument is a [u8] and it is #[repr(transparent), meaning the structs are represented
127        // identically at the byte level.
128        unsafe { &*(data.as_ref() as *const [u8] as *const RawDocument) }
129    }
130
131    /// Gets a reference to the value corresponding to the given key by iterating until the key is
132    /// found.
133    ///
134    /// ```
135    /// # use bson::error::Error;
136    /// use bson::{rawdoc, oid::ObjectId};
137    ///
138    /// let doc = rawdoc! {
139    ///     "_id": ObjectId::new(),
140    ///     "f64": 2.5,
141    /// };
142    ///
143    /// let element = doc.get("f64")?.expect("finding key f64");
144    /// assert_eq!(element.as_f64(), Some(2.5));
145    /// assert!(doc.get("unknown")?.is_none());
146    /// # Ok::<(), Error>(())
147    /// ```
148    pub fn get(&self, key: impl AsRef<str>) -> RawResult<Option<RawBsonRef<'_>>> {
149        for elem in RawIter::new(self) {
150            let elem = elem?;
151            if key.as_ref() == elem.key().as_str() {
152                return Ok(Some(elem.try_into()?));
153            }
154        }
155        Ok(None)
156    }
157
158    /// Gets an iterator over the elements in the [`RawDocument`] that yields
159    /// `Result<(&str, RawBson<'_>)>`.
160    pub fn iter(&self) -> Iter<'_> {
161        Iter::new(self)
162    }
163
164    /// Gets an iterator over the elements in the [`RawDocument`],
165    /// which yields `Result<RawElement<'_>>` values. These hold a
166    /// reference to the underlying document but do not explicitly
167    /// resolve the values.
168    ///
169    /// This iterator, which underpins the implementation of the
170    /// default iterator, produces `RawElement` objects that hold a
171    /// view onto the document but do not parse out or construct
172    /// values until the `.value()` or `.try_into()` methods are
173    /// called.
174    pub fn iter_elements(&self) -> RawIter<'_> {
175        RawIter::new(self)
176    }
177
178    fn get_with<'a, T>(
179        &'a self,
180        key: impl AsRef<str>,
181        expected_type: ElementType,
182        f: impl FnOnce(RawBsonRef<'a>) -> Option<T>,
183    ) -> Result<T> {
184        let key = key.as_ref();
185
186        let bson = self
187            .get(key)
188            .map_err(|e| Error::value_access_invalid_bson(format!("{:?}", e)))?
189            .ok_or_else(Error::value_access_not_present)
190            .map_err(|e| e.with_key(key))?;
191        match f(bson) {
192            Some(t) => Ok(t),
193            None => Err(
194                Error::value_access_unexpected_type(bson.element_type(), expected_type)
195                    .with_key(key),
196            ),
197        }
198    }
199
200    /// Gets a reference to the BSON double value corresponding to a given key or returns an error
201    /// if the key corresponds to a value which isn't a double.
202    ///
203    /// ```
204    /// # use bson::error::Error;
205    /// use bson::rawdoc;
206    ///
207    /// let doc = rawdoc! {
208    ///     "bool": true,
209    ///     "f64": 2.5,
210    /// };
211    ///
212    /// assert_eq!(doc.get_f64("f64")?, 2.5);
213    /// assert!(doc.get_f64("bool").is_err());
214    /// assert!(doc.get_f64("unknown").is_err());
215    /// # Ok::<(), Box<dyn std::error::Error>>(())
216    /// ```
217    pub fn get_f64(&self, key: impl AsRef<str>) -> Result<f64> {
218        self.get_with(key, ElementType::Double, RawBsonRef::as_f64)
219    }
220
221    /// Gets a reference to the string value corresponding to a given key or returns an error if the
222    /// key corresponds to a value which isn't a string.
223    ///
224    /// ```
225    /// use bson::rawdoc;
226    ///
227    /// let doc = rawdoc! {
228    ///     "string": "hello",
229    ///     "bool": true,
230    /// };
231    ///
232    /// assert_eq!(doc.get_str("string")?, "hello");
233    /// assert!(doc.get_str("bool").is_err());
234    /// assert!(doc.get_str("unknown").is_err());
235    /// # Ok::<(), Box<dyn std::error::Error>>(())
236    /// ```
237    pub fn get_str(&self, key: impl AsRef<str>) -> Result<&'_ str> {
238        self.get_with(key, ElementType::String, RawBsonRef::as_str)
239    }
240
241    /// Gets a reference to the document value corresponding to a given key or returns an error if
242    /// the key corresponds to a value which isn't a document.
243    ///
244    /// ```
245    /// # use bson::error::Error;
246    /// use bson::rawdoc;
247    ///
248    /// let doc = rawdoc! {
249    ///     "doc": { "key": "value"},
250    ///     "bool": true,
251    /// };
252    ///
253    /// assert_eq!(doc.get_document("doc")?.get_str("key")?, "value");
254    /// assert!(doc.get_document("bool").is_err());
255    /// assert!(doc.get_document("unknown").is_err());
256    /// # Ok::<(), Box<dyn std::error::Error>>(())
257    /// ```
258    pub fn get_document(&self, key: impl AsRef<str>) -> Result<&'_ RawDocument> {
259        self.get_with(key, ElementType::EmbeddedDocument, RawBsonRef::as_document)
260    }
261
262    /// Gets a reference to the array value corresponding to a given key or returns an error if
263    /// the key corresponds to a value which isn't an array.
264    ///
265    /// ```
266    /// use bson::rawdoc;
267    ///
268    /// let doc = rawdoc! {
269    ///     "array": [true, 3],
270    ///     "bool": true,
271    /// };
272    ///
273    /// let mut arr_iter = doc.get_array("array")?.into_iter();
274    /// let _: bool = arr_iter.next().unwrap()?.as_bool().unwrap();
275    /// let _: i32 = arr_iter.next().unwrap()?.as_i32().unwrap();
276    ///
277    /// assert!(arr_iter.next().is_none());
278    /// assert!(doc.get_array("bool").is_err());
279    /// assert!(doc.get_array("unknown").is_err());
280    /// # Ok::<(), Box<dyn std::error::Error>>(())
281    /// ```
282    pub fn get_array(&self, key: impl AsRef<str>) -> Result<&'_ RawArray> {
283        self.get_with(key, ElementType::Array, RawBsonRef::as_array)
284    }
285
286    /// Gets a reference to the BSON binary value corresponding to a given key or returns an error
287    /// if the key corresponds to a value which isn't a binary value.
288    ///
289    /// ```
290    /// use bson::{
291    ///     rawdoc,
292    ///     spec::BinarySubtype,
293    ///     Binary,
294    /// };
295    ///
296    /// let doc = rawdoc! {
297    ///     "binary": Binary { subtype: BinarySubtype::Generic, bytes: vec![1, 2, 3] },
298    ///     "bool": true,
299    /// };
300    ///
301    /// assert_eq!(&doc.get_binary("binary")?.bytes, &[1, 2, 3]);
302    /// assert!(doc.get_binary("bool").is_err());
303    /// assert!(doc.get_binary("unknown").is_err());
304    /// # Ok::<(), Box<dyn std::error::Error>>(())
305    /// ```
306    pub fn get_binary(&self, key: impl AsRef<str>) -> Result<RawBinaryRef<'_>> {
307        self.get_with(key, ElementType::Binary, RawBsonRef::as_binary)
308    }
309
310    /// Gets a reference to the ObjectId value corresponding to a given key or returns an error if
311    /// the key corresponds to a value which isn't an ObjectId.
312    ///
313    /// ```
314    /// # use bson::error::Error;
315    /// use bson::{rawdoc, oid::ObjectId};
316    ///
317    /// let doc = rawdoc! {
318    ///     "_id": ObjectId::new(),
319    ///     "bool": true,
320    /// };
321    ///
322    /// let oid = doc.get_object_id("_id")?;
323    /// assert!(doc.get_object_id("bool").is_err());
324    /// assert!(doc.get_object_id("unknown").is_err());
325    /// # Ok::<(), Box<dyn std::error::Error>>(())
326    /// ```
327    pub fn get_object_id(&self, key: impl AsRef<str>) -> Result<ObjectId> {
328        self.get_with(key, ElementType::ObjectId, RawBsonRef::as_object_id)
329    }
330
331    /// Gets a reference to the boolean value corresponding to a given key or returns an error if
332    /// the key corresponds to a value which isn't a boolean.
333    ///
334    /// ```
335    /// # use bson::error::Error;
336    /// use bson::{rawdoc, oid::ObjectId};
337    ///
338    /// let doc = rawdoc! {
339    ///     "_id": ObjectId::new(),
340    ///     "bool": true,
341    /// };
342    ///
343    /// assert!(doc.get_bool("bool")?);
344    /// assert!(doc.get_bool("_id").is_err());
345    /// assert!(doc.get_bool("unknown").is_err());
346    /// # Ok::<(), Box<dyn std::error::Error>>(())
347    /// ```
348    pub fn get_bool(&self, key: impl AsRef<str>) -> Result<bool> {
349        self.get_with(key, ElementType::Boolean, RawBsonRef::as_bool)
350    }
351
352    /// Gets a reference to the BSON DateTime value corresponding to a given key or returns an
353    /// error if the key corresponds to a value which isn't a DateTime.
354    ///
355    /// ```
356    /// # use bson::error::Error;
357    /// use bson::{rawdoc, DateTime};
358    ///
359    /// let dt = DateTime::now();
360    /// let doc = rawdoc! {
361    ///     "created_at": dt,
362    ///     "bool": true,
363    /// };
364    ///
365    /// assert_eq!(doc.get_datetime("created_at")?, dt);
366    /// assert!(doc.get_datetime("bool").is_err());
367    /// assert!(doc.get_datetime("unknown").is_err());
368    /// # Ok::<(), Box<dyn std::error::Error>>(())
369    /// ```
370    pub fn get_datetime(&self, key: impl AsRef<str>) -> Result<DateTime> {
371        self.get_with(key, ElementType::DateTime, RawBsonRef::as_datetime)
372    }
373
374    /// Gets a reference to the BSON regex value corresponding to a given key or returns an error if
375    /// the key corresponds to a value which isn't a regex.
376    ///
377    /// ```
378    /// use bson::{rawdoc, Regex, raw::cstr};
379    ///
380    /// let doc = rawdoc! {
381    ///     "regex": Regex {
382    ///         pattern: cstr!(r"end\s*$").into(),
383    ///         options: cstr!("i").into(),
384    ///     },
385    ///     "bool": true,
386    /// };
387    ///
388    /// assert_eq!(doc.get_regex("regex")?.pattern, cstr!(r"end\s*$"));
389    /// assert_eq!(doc.get_regex("regex")?.options, cstr!("i"));
390    /// assert!(doc.get_regex("bool").is_err());
391    /// assert!(doc.get_regex("unknown").is_err());
392    /// # Ok::<(), Box<dyn std::error::Error>>(())
393    /// ```
394    pub fn get_regex(&self, key: impl AsRef<str>) -> Result<RawRegexRef<'_>> {
395        self.get_with(key, ElementType::RegularExpression, RawBsonRef::as_regex)
396    }
397
398    /// Gets a reference to the BSON timestamp value corresponding to a given key or returns an
399    /// error if the key corresponds to a value which isn't a timestamp.
400    ///
401    /// ```
402    /// # use bson::error::Error;
403    /// use bson::{rawdoc, Timestamp};
404    ///
405    /// let doc = rawdoc! {
406    ///     "bool": true,
407    ///     "ts": Timestamp { time: 649876543, increment: 9 },
408    /// };
409    ///
410    /// let timestamp = doc.get_timestamp("ts")?;
411    ///
412    /// assert_eq!(timestamp.time, 649876543);
413    /// assert_eq!(timestamp.increment, 9);
414    /// assert!(doc.get_timestamp("bool").is_err());
415    /// assert!(doc.get_timestamp("unknown").is_err());
416    /// # Ok::<(), Box<dyn std::error::Error>>(())
417    /// ```
418    pub fn get_timestamp(&self, key: impl AsRef<str>) -> Result<Timestamp> {
419        self.get_with(key, ElementType::Timestamp, RawBsonRef::as_timestamp)
420    }
421
422    /// Gets a reference to the BSON int32 value corresponding to a given key or returns an error if
423    /// the key corresponds to a value which isn't a 32-bit integer.
424    ///
425    /// ```
426    /// # use bson::error::Error;
427    /// use bson::rawdoc;
428    ///
429    /// let doc = rawdoc! {
430    ///     "bool": true,
431    ///     "i32": 1_000_000,
432    /// };
433    ///
434    /// assert_eq!(doc.get_i32("i32")?, 1_000_000);
435    /// assert!(doc.get_i32("bool").is_err());
436    /// assert!(doc.get_i32("unknown").is_err());
437    /// # Ok::<(), Box<dyn std::error::Error>>(())
438    /// ```
439    pub fn get_i32(&self, key: impl AsRef<str>) -> Result<i32> {
440        self.get_with(key, ElementType::Int32, RawBsonRef::as_i32)
441    }
442
443    /// Gets a reference to the BSON int64 value corresponding to a given key or returns an error if
444    /// the key corresponds to a value which isn't a 64-bit integer.
445    ///
446    /// ```
447    /// # use bson::error::Error;
448    /// use bson::rawdoc;
449    ///
450    /// let doc = rawdoc! {
451    ///     "bool": true,
452    ///     "i64": 9223372036854775807_i64,
453    /// };
454    ///
455    /// assert_eq!(doc.get_i64("i64")?, 9223372036854775807);
456    /// assert!(doc.get_i64("bool").is_err());
457    /// assert!(doc.get_i64("unknown").is_err());
458    /// # Ok::<(), Box<dyn std::error::Error>>(())
459    /// ```
460    pub fn get_i64(&self, key: impl AsRef<str>) -> Result<i64> {
461        self.get_with(key, ElementType::Int64, RawBsonRef::as_i64)
462    }
463
464    /// Return a reference to the contained data as a `&[u8]`
465    ///
466    /// ```
467    /// # use bson::error::Error;
468    /// use bson::rawdoc;
469    /// let docbuf = rawdoc! {};
470    /// assert_eq!(docbuf.as_bytes(), b"\x05\x00\x00\x00\x00");
471    /// # Ok::<(), Error>(())
472    /// ```
473    pub fn as_bytes(&self) -> &[u8] {
474        &self.data
475    }
476
477    /// Returns whether this document contains any elements or not.
478    pub fn is_empty(&self) -> bool {
479        self.as_bytes().len() == MIN_BSON_DOCUMENT_SIZE as usize
480    }
481
482    pub(crate) fn cstring_bytes_at(&self, start_at: usize) -> RawResult<&[u8]> {
483        let buf = &self.as_bytes()[start_at..];
484
485        let mut splits = buf.splitn(2, |x| *x == 0);
486        let value = splits
487            .next()
488            .ok_or_else(|| RawError::malformed_bytes("no value"))?;
489        if splits.next().is_some() {
490            Ok(value)
491        } else {
492            Err(RawError::malformed_bytes("expected null terminator"))
493        }
494    }
495
496    pub(crate) fn read_cstring_at(&self, start_at: usize) -> RawResult<&CStr> {
497        let bytes = self.cstring_bytes_at(start_at)?;
498        let s = try_to_str(bytes)?;
499        s.try_into()
500    }
501}
502
503#[cfg(feature = "serde")]
504impl<'de: 'a, 'a> serde::Deserialize<'de> for &'a RawDocument {
505    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
506    where
507        D: serde::Deserializer<'de>,
508    {
509        use super::serde::OwnedOrBorrowedRawDocument;
510        match OwnedOrBorrowedRawDocument::deserialize(deserializer)? {
511            OwnedOrBorrowedRawDocument::Borrowed(b) => Ok(b),
512            OwnedOrBorrowedRawDocument::Owned(d) => Err(serde::de::Error::custom(format!(
513                "expected borrowed raw document, instead got owned {:?}",
514                d
515            ))),
516        }
517    }
518}
519
520#[cfg(feature = "serde")]
521impl serde::Serialize for &RawDocument {
522    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
523    where
524        S: serde::Serializer,
525    {
526        struct KvpSerializer<'a>(&'a RawDocument);
527
528        impl serde::Serialize for KvpSerializer<'_> {
529            fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
530            where
531                S: serde::Serializer,
532            {
533                use serde::ser::SerializeMap as _;
534                if serializer.is_human_readable() {
535                    let mut map = serializer.serialize_map(None)?;
536                    for kvp in self.0 {
537                        let (k, v) = kvp.map_err(serde::ser::Error::custom)?;
538                        map.serialize_entry(k.as_str(), &v)?;
539                    }
540                    map.end()
541                } else {
542                    serializer.serialize_bytes(self.0.as_bytes())
543                }
544            }
545        }
546        serializer.serialize_newtype_struct(super::RAW_DOCUMENT_NEWTYPE, &KvpSerializer(self))
547    }
548}
549
550impl std::fmt::Debug for RawDocument {
551    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
552        f.debug_struct("RawDocument")
553            .field("data", &hex::encode(&self.data))
554            .finish()
555    }
556}
557
558impl AsRef<RawDocument> for RawDocument {
559    fn as_ref(&self) -> &RawDocument {
560        self
561    }
562}
563
564impl ToOwned for RawDocument {
565    type Owned = RawDocumentBuf;
566
567    fn to_owned(&self) -> Self::Owned {
568        // unwrap is ok here because we already verified the bytes in
569        // `RawDocument::from_bytes`
570        RawDocumentBuf::from_bytes(self.data.to_owned()).unwrap()
571    }
572}
573
574impl<'a> From<&'a RawDocument> for Cow<'a, RawDocument> {
575    fn from(rdr: &'a RawDocument) -> Self {
576        Cow::Borrowed(rdr)
577    }
578}
579
580impl TryFrom<&RawDocument> for Document {
581    type Error = RawError;
582
583    fn try_from(rawdoc: &RawDocument) -> RawResult<Document> {
584        rawdoc
585            .into_iter()
586            .map(|res| res.and_then(|(k, v)| Ok((k.as_str().to_owned(), v.try_into()?))))
587            .collect()
588    }
589}
590
591impl TryFrom<&RawDocument> for Utf8Lossy<Document> {
592    type Error = RawError;
593
594    fn try_from(rawdoc: &RawDocument) -> RawResult<Utf8Lossy<Document>> {
595        let mut out = Document::new();
596        for elem in rawdoc.iter_elements() {
597            let elem = elem?;
598            let value = deep_utf8_lossy(elem.value_utf8_lossy()?)?;
599            out.insert(elem.key().as_str(), value);
600        }
601        Ok(Utf8Lossy(out))
602    }
603}
604
605fn deep_utf8_lossy(src: RawBson) -> RawResult<Bson> {
606    match src {
607        RawBson::Array(arr) => {
608            let mut tmp = vec![];
609            for elem in arr.iter_elements() {
610                tmp.push(deep_utf8_lossy(elem?.value_utf8_lossy()?)?);
611            }
612            Ok(Bson::Array(tmp))
613        }
614        RawBson::Document(doc) => {
615            let mut tmp = doc! {};
616            for elem in doc.iter_elements() {
617                let elem = elem?;
618                tmp.insert(
619                    elem.key().as_str(),
620                    deep_utf8_lossy(elem.value_utf8_lossy()?)?,
621                );
622            }
623            Ok(Bson::Document(tmp))
624        }
625        RawBson::JavaScriptCodeWithScope(RawJavaScriptCodeWithScope { code, scope }) => {
626            let mut tmp = doc! {};
627            for elem in scope.iter_elements() {
628                let elem = elem?;
629                tmp.insert(
630                    elem.key().as_str(),
631                    deep_utf8_lossy(elem.value_utf8_lossy()?)?,
632                );
633            }
634            Ok(Bson::JavaScriptCodeWithScope(JavaScriptCodeWithScope {
635                code,
636                scope: tmp,
637            }))
638        }
639        v => v.try_into(),
640    }
641}
642
643impl TryFrom<RawDocumentBuf> for Document {
644    type Error = crate::error::Error;
645
646    fn try_from(raw: RawDocumentBuf) -> Result<Document> {
647        Document::try_from(raw.as_ref())
648    }
649}
650
651impl TryFrom<RawDocumentBuf> for Utf8Lossy<Document> {
652    type Error = crate::error::Error;
653
654    fn try_from(raw: RawDocumentBuf) -> Result<Utf8Lossy<Document>> {
655        Utf8Lossy::<Document>::try_from(raw.as_ref())
656    }
657}
658
659impl TryFrom<&RawDocumentBuf> for Document {
660    type Error = crate::error::Error;
661
662    fn try_from(raw: &RawDocumentBuf) -> Result<Document> {
663        Document::try_from(raw.as_ref())
664    }
665}
666
667impl TryFrom<&RawDocumentBuf> for Utf8Lossy<Document> {
668    type Error = crate::error::Error;
669
670    fn try_from(raw: &RawDocumentBuf) -> Result<Utf8Lossy<Document>> {
671        Utf8Lossy::<Document>::try_from(raw.as_ref())
672    }
673}
674
675impl<'a> IntoIterator for &'a RawDocument {
676    type IntoIter = Iter<'a>;
677    type Item = RawResult<(&'a CStr, RawBsonRef<'a>)>;
678
679    fn into_iter(self) -> Iter<'a> {
680        self.iter()
681    }
682}