bson/raw/
bson_ref.rs

1use std::convert::{TryFrom, TryInto};
2
3use super::{bson::RawBson, Error, RawArray, RawDocument, Result};
4use crate::{
5    oid::{self, ObjectId},
6    raw::{write_string, CStr, RawJavaScriptCodeWithScope},
7    spec::{BinarySubtype, ElementType},
8    Binary,
9    Bson,
10    DbPointer,
11    Decimal128,
12    RawArrayBuf,
13    RawDocumentBuf,
14    Regex,
15    Timestamp,
16};
17
18#[cfg(feature = "serde")]
19use serde::ser::SerializeStruct as _;
20
21/// A BSON value referencing raw bytes stored elsewhere.
22#[derive(Debug, Clone, Copy, PartialEq)]
23pub enum RawBsonRef<'a> {
24    /// 64-bit binary floating point
25    Double(f64),
26    /// UTF-8 string
27    String(&'a str),
28    /// Array
29    Array(&'a RawArray),
30    /// Embedded document
31    Document(&'a RawDocument),
32    /// Boolean value
33    Boolean(bool),
34    /// Null value
35    Null,
36    /// Regular expression
37    RegularExpression(RawRegexRef<'a>),
38    /// JavaScript code
39    JavaScriptCode(&'a str),
40    /// JavaScript code w/ scope
41    JavaScriptCodeWithScope(RawJavaScriptCodeWithScopeRef<'a>),
42    /// 32-bit signed integer
43    Int32(i32),
44    /// 64-bit signed integer
45    Int64(i64),
46    /// Timestamp
47    Timestamp(Timestamp),
48    /// Binary data
49    Binary(RawBinaryRef<'a>),
50    /// [ObjectId](http://dochub.mongodb.org/core/objectids)
51    ObjectId(oid::ObjectId),
52    /// UTC datetime
53    DateTime(crate::DateTime),
54    /// Symbol (Deprecated)
55    Symbol(&'a str),
56    /// [128-bit decimal floating point](https://github.com/mongodb/specifications/blob/master/source/bson-decimal128/decimal128.rst)
57    Decimal128(Decimal128),
58    /// Undefined value (Deprecated)
59    Undefined,
60    /// Max key
61    MaxKey,
62    /// Min key
63    MinKey,
64    /// DBPointer (Deprecated)
65    DbPointer(RawDbPointerRef<'a>),
66}
67
68impl<'a> RawBsonRef<'a> {
69    /// Get the [`ElementType`] of this value.
70    pub fn element_type(&self) -> ElementType {
71        match *self {
72            RawBsonRef::Double(..) => ElementType::Double,
73            RawBsonRef::String(..) => ElementType::String,
74            RawBsonRef::Array(..) => ElementType::Array,
75            RawBsonRef::Document(..) => ElementType::EmbeddedDocument,
76            RawBsonRef::Boolean(..) => ElementType::Boolean,
77            RawBsonRef::Null => ElementType::Null,
78            RawBsonRef::RegularExpression(..) => ElementType::RegularExpression,
79            RawBsonRef::JavaScriptCode(..) => ElementType::JavaScriptCode,
80            RawBsonRef::JavaScriptCodeWithScope(..) => ElementType::JavaScriptCodeWithScope,
81            RawBsonRef::Int32(..) => ElementType::Int32,
82            RawBsonRef::Int64(..) => ElementType::Int64,
83            RawBsonRef::Timestamp(..) => ElementType::Timestamp,
84            RawBsonRef::Binary(..) => ElementType::Binary,
85            RawBsonRef::ObjectId(..) => ElementType::ObjectId,
86            RawBsonRef::DateTime(..) => ElementType::DateTime,
87            RawBsonRef::Symbol(..) => ElementType::Symbol,
88            RawBsonRef::Decimal128(..) => ElementType::Decimal128,
89            RawBsonRef::Undefined => ElementType::Undefined,
90            RawBsonRef::MaxKey => ElementType::MaxKey,
91            RawBsonRef::MinKey => ElementType::MinKey,
92            RawBsonRef::DbPointer(..) => ElementType::DbPointer,
93        }
94    }
95
96    /// Gets the `f64` that's referenced or returns [`None`] if the referenced value isn't a BSON
97    /// double.
98    pub fn as_f64(self) -> Option<f64> {
99        match self {
100            RawBsonRef::Double(d) => Some(d),
101            _ => None,
102        }
103    }
104
105    /// Gets the `&str` that's referenced or returns [`None`] if the referenced value isn't a BSON
106    /// String.
107    pub fn as_str(self) -> Option<&'a str> {
108        match self {
109            RawBsonRef::String(s) => Some(s),
110            _ => None,
111        }
112    }
113
114    /// Gets the [`RawArray`] that's referenced or returns [`None`] if the referenced value
115    /// isn't a BSON array.
116    pub fn as_array(self) -> Option<&'a RawArray> {
117        match self {
118            RawBsonRef::Array(v) => Some(v),
119            _ => None,
120        }
121    }
122
123    /// Gets the [`RawDocument`] that's referenced or returns [`None`] if the referenced value
124    /// isn't a BSON document.
125    pub fn as_document(self) -> Option<&'a RawDocument> {
126        match self {
127            RawBsonRef::Document(v) => Some(v),
128            _ => None,
129        }
130    }
131
132    /// Gets the `bool` that's referenced or returns [`None`] if the referenced value isn't a BSON
133    /// boolean.
134    pub fn as_bool(self) -> Option<bool> {
135        match self {
136            RawBsonRef::Boolean(v) => Some(v),
137            _ => None,
138        }
139    }
140
141    /// Gets the `i32` that's referenced or returns [`None`] if the referenced value isn't a BSON
142    /// Int32.
143    pub fn as_i32(self) -> Option<i32> {
144        match self {
145            RawBsonRef::Int32(v) => Some(v),
146            _ => None,
147        }
148    }
149
150    /// Gets the `i64` that's referenced or returns [`None`] if the referenced value isn't a BSON
151    /// Int64.
152    pub fn as_i64(self) -> Option<i64> {
153        match self {
154            RawBsonRef::Int64(v) => Some(v),
155            _ => None,
156        }
157    }
158
159    /// Gets the [`crate::oid::ObjectId`] that's referenced or returns [`None`] if the referenced
160    /// value isn't a BSON ObjectID.
161    pub fn as_object_id(self) -> Option<oid::ObjectId> {
162        match self {
163            RawBsonRef::ObjectId(v) => Some(v),
164            _ => None,
165        }
166    }
167
168    /// Gets the [`RawBinaryRef`] that's referenced or returns [`None`] if the referenced value
169    /// isn't a BSON binary.
170    pub fn as_binary(self) -> Option<RawBinaryRef<'a>> {
171        match self {
172            RawBsonRef::Binary(v) => Some(v),
173            _ => None,
174        }
175    }
176
177    /// Gets the [`RawRegexRef`] that's referenced or returns [`None`] if the referenced value isn't
178    /// a BSON regular expression.
179    pub fn as_regex(self) -> Option<RawRegexRef<'a>> {
180        match self {
181            RawBsonRef::RegularExpression(v) => Some(v),
182            _ => None,
183        }
184    }
185
186    /// Gets the [`crate::DateTime`] that's referenced or returns [`None`] if the referenced value
187    /// isn't a BSON datetime.
188    pub fn as_datetime(self) -> Option<crate::DateTime> {
189        match self {
190            RawBsonRef::DateTime(v) => Some(v),
191            _ => None,
192        }
193    }
194
195    /// Gets the symbol that's referenced or returns [`None`] if the referenced value isn't a BSON
196    /// symbol.
197    pub fn as_symbol(self) -> Option<&'a str> {
198        match self {
199            RawBsonRef::Symbol(v) => Some(v),
200            _ => None,
201        }
202    }
203
204    /// Gets the [`crate::Timestamp`] that's referenced or returns [`None`] if the referenced value
205    /// isn't a BSON timestamp.
206    pub fn as_timestamp(self) -> Option<Timestamp> {
207        match self {
208            RawBsonRef::Timestamp(timestamp) => Some(timestamp),
209            _ => None,
210        }
211    }
212
213    /// Gets the null value that's referenced or returns [`None`] if the referenced value isn't a
214    /// BSON null.
215    pub fn as_null(self) -> Option<()> {
216        match self {
217            RawBsonRef::Null => Some(()),
218            _ => None,
219        }
220    }
221
222    /// Gets the [`RawDbPointerRef`] that's referenced or returns [`None`] if the referenced value
223    /// isn't a BSON DB pointer.
224    pub fn as_db_pointer(self) -> Option<RawDbPointerRef<'a>> {
225        match self {
226            RawBsonRef::DbPointer(d) => Some(d),
227            _ => None,
228        }
229    }
230
231    /// Gets the code that's referenced or returns [`None`] if the referenced value isn't a BSON
232    /// JavaScript.
233    pub fn as_javascript(self) -> Option<&'a str> {
234        match self {
235            RawBsonRef::JavaScriptCode(s) => Some(s),
236            _ => None,
237        }
238    }
239
240    /// Gets the [`RawJavaScriptCodeWithScope`] that's referenced or returns [`None`] if the
241    /// referenced value isn't a BSON JavaScript with scope.
242    pub fn as_javascript_with_scope(self) -> Option<RawJavaScriptCodeWithScopeRef<'a>> {
243        match self {
244            RawBsonRef::JavaScriptCodeWithScope(s) => Some(s),
245            _ => None,
246        }
247    }
248
249    #[inline]
250    pub(crate) fn append_to(self, dest: &mut Vec<u8>) {
251        match self {
252            Self::Int32(val) => dest.extend(val.to_le_bytes()),
253            Self::Int64(val) => dest.extend(val.to_le_bytes()),
254            Self::Double(val) => dest.extend(val.to_le_bytes()),
255            Self::Binary(b @ RawBinaryRef { subtype, bytes }) => {
256                let len = b.len();
257                dest.extend(len.to_le_bytes());
258                dest.push(subtype.into());
259                if let BinarySubtype::BinaryOld = subtype {
260                    dest.extend((len - 4).to_le_bytes())
261                }
262                dest.extend(bytes);
263            }
264            Self::String(s) => write_string(dest, s),
265            Self::Array(raw_array) => dest.extend(raw_array.as_bytes()),
266            Self::Document(raw_document) => dest.extend(raw_document.as_bytes()),
267            Self::Boolean(b) => dest.push(b as u8),
268            Self::RegularExpression(re) => {
269                re.pattern.append_to(dest);
270                re.options.append_to(dest);
271            }
272            Self::JavaScriptCode(js) => write_string(dest, js),
273            Self::JavaScriptCodeWithScope(code_w_scope) => {
274                let len = code_w_scope.len();
275                dest.extend(len.to_le_bytes());
276                write_string(dest, code_w_scope.code);
277                dest.extend(code_w_scope.scope.as_bytes());
278            }
279            Self::Timestamp(ts) => dest.extend(ts.to_le_bytes()),
280            Self::ObjectId(oid) => dest.extend(oid.bytes()),
281            Self::DateTime(dt) => dest.extend(dt.timestamp_millis().to_le_bytes()),
282            Self::Symbol(s) => write_string(dest, s),
283            Self::Decimal128(d) => dest.extend(d.bytes()),
284            Self::DbPointer(dbp) => {
285                write_string(dest, dbp.namespace);
286                dest.extend(dbp.id.bytes());
287            }
288            Self::Null | Self::Undefined | Self::MinKey | Self::MaxKey => {}
289        }
290    }
291}
292
293impl<'a> From<RawBsonRef<'a>> for RawBson {
294    fn from(value: RawBsonRef<'a>) -> Self {
295        match value {
296            RawBsonRef::Double(d) => RawBson::Double(d),
297            RawBsonRef::String(s) => RawBson::String(s.to_string()),
298            RawBsonRef::Array(a) => RawBson::Array(a.to_owned()),
299            RawBsonRef::Document(d) => RawBson::Document(d.to_owned()),
300            RawBsonRef::Boolean(b) => RawBson::Boolean(b),
301            RawBsonRef::Null => RawBson::Null,
302            RawBsonRef::RegularExpression(re) => {
303                let mut chars: Vec<_> = re.options.as_str().chars().collect();
304                chars.sort_unstable();
305                let options: String = chars.into_iter().collect();
306                RawBson::RegularExpression(Regex {
307                    pattern: re.pattern.into(),
308                    options: super::CString::from_string_unchecked(options),
309                })
310            }
311            RawBsonRef::JavaScriptCode(c) => RawBson::JavaScriptCode(c.to_owned()),
312            RawBsonRef::JavaScriptCodeWithScope(c_w_s) => {
313                RawBson::JavaScriptCodeWithScope(RawJavaScriptCodeWithScope {
314                    code: c_w_s.code.to_string(),
315                    scope: c_w_s.scope.to_owned(),
316                })
317            }
318            RawBsonRef::Int32(i) => RawBson::Int32(i),
319            RawBsonRef::Int64(i) => RawBson::Int64(i),
320            RawBsonRef::Timestamp(t) => RawBson::Timestamp(t),
321            RawBsonRef::Binary(b) => RawBson::Binary(Binary {
322                bytes: b.bytes.to_vec(),
323                subtype: b.subtype,
324            }),
325            RawBsonRef::ObjectId(o) => RawBson::ObjectId(o),
326            RawBsonRef::DateTime(dt) => RawBson::DateTime(dt),
327            RawBsonRef::Symbol(s) => RawBson::Symbol(s.to_string()),
328            RawBsonRef::Decimal128(d) => RawBson::Decimal128(d),
329            RawBsonRef::Undefined => RawBson::Undefined,
330            RawBsonRef::MaxKey => RawBson::MaxKey,
331            RawBsonRef::MinKey => RawBson::MinKey,
332            RawBsonRef::DbPointer(d) => RawBson::DbPointer(DbPointer {
333                namespace: d.namespace.to_string(),
334                id: d.id,
335            }),
336        }
337    }
338}
339
340#[cfg(feature = "serde")]
341impl<'de: 'a, 'a> serde::Deserialize<'de> for RawBsonRef<'a> {
342    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
343    where
344        D: serde::Deserializer<'de>,
345    {
346        use super::serde::{bson_visitor::OwnedOrBorrowedRawBsonVisitor, OwnedOrBorrowedRawBson};
347        match deserializer.deserialize_newtype_struct(
348            crate::raw::RAW_BSON_NEWTYPE,
349            OwnedOrBorrowedRawBsonVisitor,
350        )? {
351            OwnedOrBorrowedRawBson::Borrowed(b) => Ok(b),
352            o => Err(serde::de::Error::custom(format!(
353                "RawBson must be deserialized from borrowed content, instead got {:?}",
354                o
355            ))),
356        }
357    }
358}
359
360#[cfg(feature = "serde")]
361impl serde::Serialize for RawBsonRef<'_> {
362    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
363    where
364        S: serde::Serializer,
365    {
366        match self {
367            RawBsonRef::Double(v) => serializer.serialize_f64(*v),
368            RawBsonRef::String(v) => serializer.serialize_str(v),
369            RawBsonRef::Array(v) => v.serialize(serializer),
370            RawBsonRef::Document(v) => v.serialize(serializer),
371            RawBsonRef::Boolean(v) => serializer.serialize_bool(*v),
372            RawBsonRef::Null => serializer.serialize_unit(),
373            RawBsonRef::Int32(v) => serializer.serialize_i32(*v),
374            RawBsonRef::Int64(v) => serializer.serialize_i64(*v),
375            RawBsonRef::ObjectId(oid) => oid.serialize(serializer),
376            RawBsonRef::DateTime(dt) => dt.serialize(serializer),
377            RawBsonRef::Binary(b) => b.serialize(serializer),
378            RawBsonRef::JavaScriptCode(c) => {
379                let mut state = serializer.serialize_struct("$code", 1)?;
380                state.serialize_field("$code", c)?;
381                state.end()
382            }
383            RawBsonRef::JavaScriptCodeWithScope(code_w_scope) => code_w_scope.serialize(serializer),
384            RawBsonRef::DbPointer(dbp) => dbp.serialize(serializer),
385            RawBsonRef::Symbol(s) => {
386                let mut state = serializer.serialize_struct("$symbol", 1)?;
387                state.serialize_field("$symbol", s)?;
388                state.end()
389            }
390            RawBsonRef::RegularExpression(re) => re.serialize(serializer),
391            RawBsonRef::Timestamp(t) => t.serialize(serializer),
392            RawBsonRef::Decimal128(d) => d.serialize(serializer),
393            RawBsonRef::Undefined => {
394                let mut state = serializer.serialize_struct("$undefined", 1)?;
395                state.serialize_field("$undefined", &true)?;
396                state.end()
397            }
398            RawBsonRef::MaxKey => {
399                let mut state = serializer.serialize_struct("$maxKey", 1)?;
400                state.serialize_field("$maxKey", &1)?;
401                state.end()
402            }
403            RawBsonRef::MinKey => {
404                let mut state = serializer.serialize_struct("$minKey", 1)?;
405                state.serialize_field("$minKey", &1)?;
406                state.end()
407            }
408        }
409    }
410}
411
412impl<'a> TryFrom<RawBsonRef<'a>> for Bson {
413    type Error = Error;
414
415    fn try_from(rawbson: RawBsonRef<'a>) -> Result<Bson> {
416        RawBson::from(rawbson).try_into()
417    }
418}
419
420impl From<i32> for RawBsonRef<'_> {
421    fn from(i: i32) -> Self {
422        RawBsonRef::Int32(i)
423    }
424}
425
426impl From<i64> for RawBsonRef<'_> {
427    fn from(i: i64) -> Self {
428        RawBsonRef::Int64(i)
429    }
430}
431
432impl<'a> From<&'a str> for RawBsonRef<'a> {
433    fn from(s: &'a str) -> Self {
434        RawBsonRef::String(s)
435    }
436}
437
438impl From<f64> for RawBsonRef<'_> {
439    fn from(f: f64) -> Self {
440        RawBsonRef::Double(f)
441    }
442}
443
444impl From<bool> for RawBsonRef<'_> {
445    fn from(b: bool) -> Self {
446        RawBsonRef::Boolean(b)
447    }
448}
449
450impl<'a> From<&'a RawDocumentBuf> for RawBsonRef<'a> {
451    fn from(d: &'a RawDocumentBuf) -> Self {
452        RawBsonRef::Document(d.as_ref())
453    }
454}
455
456impl<'a> From<&'a RawDocument> for RawBsonRef<'a> {
457    fn from(d: &'a RawDocument) -> Self {
458        RawBsonRef::Document(d)
459    }
460}
461
462impl<'a> From<&'a RawArray> for RawBsonRef<'a> {
463    fn from(a: &'a RawArray) -> Self {
464        RawBsonRef::Array(a)
465    }
466}
467
468impl<'a> From<&'a RawArrayBuf> for RawBsonRef<'a> {
469    fn from(a: &'a RawArrayBuf) -> Self {
470        RawBsonRef::Array(a)
471    }
472}
473
474impl From<crate::DateTime> for RawBsonRef<'_> {
475    fn from(dt: crate::DateTime) -> Self {
476        RawBsonRef::DateTime(dt)
477    }
478}
479
480impl From<Timestamp> for RawBsonRef<'_> {
481    fn from(ts: Timestamp) -> Self {
482        RawBsonRef::Timestamp(ts)
483    }
484}
485
486impl From<ObjectId> for RawBsonRef<'_> {
487    fn from(oid: ObjectId) -> Self {
488        RawBsonRef::ObjectId(oid)
489    }
490}
491
492impl From<Decimal128> for RawBsonRef<'_> {
493    fn from(d: Decimal128) -> Self {
494        RawBsonRef::Decimal128(d)
495    }
496}
497
498impl<'a> From<&'a RawBson> for RawBsonRef<'a> {
499    fn from(value: &'a RawBson) -> Self {
500        value.as_raw_bson_ref()
501    }
502}
503
504/// A BSON binary value referencing raw bytes stored elsewhere.
505#[derive(Clone, Copy, Debug, PartialEq)]
506pub struct RawBinaryRef<'a> {
507    /// The subtype of the binary value.
508    pub subtype: BinarySubtype,
509
510    /// The binary bytes.
511    pub bytes: &'a [u8],
512}
513
514impl RawBinaryRef<'_> {
515    /// Copy the contents into a [`Binary`].
516    pub fn to_binary(&self) -> Binary {
517        Binary {
518            subtype: self.subtype,
519            bytes: self.bytes.to_owned(),
520        }
521    }
522
523    pub(crate) fn len(&self) -> i32 {
524        match self.subtype {
525            BinarySubtype::BinaryOld => self.bytes.len() as i32 + 4,
526            _ => self.bytes.len() as i32,
527        }
528    }
529}
530
531#[cfg(feature = "serde")]
532impl<'de: 'a, 'a> serde::Deserialize<'de> for RawBinaryRef<'a> {
533    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
534    where
535        D: serde::Deserializer<'de>,
536    {
537        match RawBsonRef::deserialize(deserializer)? {
538            RawBsonRef::Binary(b) => Ok(b),
539            c => Err(serde::de::Error::custom(format!(
540                "expected binary, but got {:?} instead",
541                c
542            ))),
543        }
544    }
545}
546
547#[cfg(feature = "serde")]
548impl serde::Serialize for RawBinaryRef<'_> {
549    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
550    where
551        S: serde::Serializer,
552    {
553        if let BinarySubtype::Generic = self.subtype {
554            serializer.serialize_bytes(self.bytes)
555        } else if !serializer.is_human_readable() {
556            use serde_bytes::Bytes;
557
558            #[derive(serde::Serialize)]
559            struct BorrowedBinary<'a> {
560                bytes: &'a Bytes,
561
562                #[serde(rename = "subType")]
563                subtype: u8,
564            }
565
566            let mut state = serializer.serialize_struct("$binary", 1)?;
567            let body = BorrowedBinary {
568                bytes: Bytes::new(self.bytes),
569                subtype: self.subtype.into(),
570            };
571            state.serialize_field("$binary", &body)?;
572            state.end()
573        } else {
574            let mut state = serializer.serialize_struct("$binary", 1)?;
575            let body = crate::extjson::models::BinaryBody {
576                base64: crate::base64::encode(self.bytes),
577                subtype: hex::encode([self.subtype.into()]),
578            };
579            state.serialize_field("$binary", &body)?;
580            state.end()
581        }
582    }
583}
584
585impl<'a> From<RawBinaryRef<'a>> for RawBsonRef<'a> {
586    fn from(b: RawBinaryRef<'a>) -> Self {
587        RawBsonRef::Binary(b)
588    }
589}
590
591impl<'a> From<&'a Binary> for RawBsonRef<'a> {
592    fn from(bin: &'a Binary) -> Self {
593        bin.as_raw_binary().into()
594    }
595}
596
597/// A BSON regex referencing raw bytes stored elsewhere.
598#[derive(Clone, Copy, Debug, PartialEq)]
599pub struct RawRegexRef<'a> {
600    /// The regex pattern to match.
601    pub pattern: &'a CStr,
602
603    /// The options for the regex.
604    ///
605    /// Options are identified by characters, which must be stored in
606    /// alphabetical order. Valid options are 'i' for case insensitive matching, 'm' for
607    /// multiline matching, 'x' for verbose mode, 'l' to make \w, \W, etc. locale dependent,
608    /// 's' for dotall mode ('.' matches everything), and 'u' to make \w, \W, etc. match
609    /// unicode.
610    pub options: &'a CStr,
611}
612
613#[cfg(feature = "serde")]
614impl<'de: 'a, 'a> serde::Deserialize<'de> for RawRegexRef<'a> {
615    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
616    where
617        D: serde::Deserializer<'de>,
618    {
619        match RawBsonRef::deserialize(deserializer)? {
620            RawBsonRef::RegularExpression(b) => Ok(b),
621            c => Err(serde::de::Error::custom(format!(
622                "expected Regex, but got {:?} instead",
623                c
624            ))),
625        }
626    }
627}
628
629#[cfg(feature = "serde")]
630impl serde::Serialize for RawRegexRef<'_> {
631    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
632    where
633        S: serde::Serializer,
634    {
635        #[derive(serde::Serialize)]
636        struct BorrowedRegexBody<'a> {
637            pattern: &'a CStr,
638            options: &'a CStr,
639        }
640
641        let mut state = serializer.serialize_struct("$regularExpression", 1)?;
642        let body = BorrowedRegexBody {
643            pattern: self.pattern,
644            options: self.options,
645        };
646        state.serialize_field("$regularExpression", &body)?;
647        state.end()
648    }
649}
650
651impl<'a> From<RawRegexRef<'a>> for RawBsonRef<'a> {
652    fn from(re: RawRegexRef<'a>) -> Self {
653        RawBsonRef::RegularExpression(re)
654    }
655}
656
657/// A BSON "code with scope" value referencing raw bytes stored elsewhere.
658#[derive(Clone, Copy, Debug, PartialEq)]
659pub struct RawJavaScriptCodeWithScopeRef<'a> {
660    /// The JavaScript code.
661    pub code: &'a str,
662
663    /// The scope document containing variable bindings.
664    pub scope: &'a RawDocument,
665}
666
667impl RawJavaScriptCodeWithScopeRef<'_> {
668    pub(crate) fn len(self) -> i32 {
669        4 + 4 + self.code.len() as i32 + 1 + self.scope.as_bytes().len() as i32
670    }
671}
672
673#[cfg(feature = "serde")]
674impl<'de: 'a, 'a> serde::Deserialize<'de> for RawJavaScriptCodeWithScopeRef<'a> {
675    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
676    where
677        D: serde::Deserializer<'de>,
678    {
679        match RawBsonRef::deserialize(deserializer)? {
680            RawBsonRef::JavaScriptCodeWithScope(b) => Ok(b),
681            c => Err(serde::de::Error::custom(format!(
682                "expected CodeWithScope, but got {:?} instead",
683                c
684            ))),
685        }
686    }
687}
688
689#[cfg(feature = "serde")]
690impl serde::Serialize for RawJavaScriptCodeWithScopeRef<'_> {
691    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
692    where
693        S: serde::Serializer,
694    {
695        let mut state = serializer.serialize_struct("$codeWithScope", 2)?;
696        state.serialize_field("$code", &self.code)?;
697        state.serialize_field("$scope", &self.scope)?;
698        state.end()
699    }
700}
701
702impl<'a> From<RawJavaScriptCodeWithScopeRef<'a>> for RawBsonRef<'a> {
703    fn from(code_w_scope: RawJavaScriptCodeWithScopeRef<'a>) -> Self {
704        RawBsonRef::JavaScriptCodeWithScope(code_w_scope)
705    }
706}
707
708/// A BSON DB pointer value referencing raw bytes stored elesewhere.
709#[derive(Debug, Clone, Copy, PartialEq)]
710pub struct RawDbPointerRef<'a> {
711    pub(crate) namespace: &'a str,
712    pub(crate) id: ObjectId,
713}
714
715#[cfg(feature = "serde")]
716impl<'de: 'a, 'a> serde::Deserialize<'de> for RawDbPointerRef<'a> {
717    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
718    where
719        D: serde::Deserializer<'de>,
720    {
721        match RawBsonRef::deserialize(deserializer)? {
722            RawBsonRef::DbPointer(b) => Ok(b),
723            c => Err(serde::de::Error::custom(format!(
724                "expected DbPointer, but got {:?} instead",
725                c
726            ))),
727        }
728    }
729}
730
731#[cfg(feature = "serde")]
732impl serde::Serialize for RawDbPointerRef<'_> {
733    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
734    where
735        S: serde::Serializer,
736    {
737        #[derive(serde::Serialize)]
738        struct BorrowedDbPointerBody<'a> {
739            #[serde(rename = "$ref")]
740            ref_ns: &'a str,
741
742            #[serde(rename = "$id")]
743            id: ObjectId,
744        }
745
746        let mut state = serializer.serialize_struct("$dbPointer", 1)?;
747        let body = BorrowedDbPointerBody {
748            ref_ns: self.namespace,
749            id: self.id,
750        };
751        state.serialize_field("$dbPointer", &body)?;
752        state.end()
753    }
754}