Coverage Report

Created: 2026-08-13 06:47

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