Skip to main content

mutable_bson/
lib.rs

1mod parsed_document;
2
3use std::{borrow::Cow, sync::Arc};
4
5use bson::{
6    Binary, Bson, DateTime, Decimal128, Document, JavaScriptCodeWithScope, RawArray, RawBinaryRef,
7    RawBsonRef, RawDbPointerRef, RawDocument, RawJavaScriptCodeWithScopeRef, RawRegexRef, Regex,
8    Timestamp, oid::ObjectId, spec::ElementType,
9};
10
11use bytes::BufMut;
12pub use parsed_document::ParsedDocument;
13
14fn raw_cstr_len(s: &str) -> usize {
15    s.len() + 1
16}
17
18fn put_raw_cstr(s: &str, buf: &mut impl BufMut) -> Result<(), bson::ser::Error> {
19    if s.as_bytes().contains(&0) {
20        Err(bson::ser::Error::InvalidCString(s.to_owned()))
21    } else {
22        buf.put_slice(s.as_bytes());
23        buf.put_u8(0);
24        Ok(())
25    }
26}
27
28fn raw_str_len(s: &str) -> usize {
29    4 + s.len() + 1
30}
31
32fn put_raw_str(s: &str, buf: &mut impl BufMut) {
33    buf.put_i32_le(
34        (s.len() + 1)
35            .try_into()
36            .expect("len validated before serialization"),
37    );
38    buf.put_slice(s.as_bytes());
39    buf.put_u8(0);
40}
41
42/// A BSON Value that is mutable.
43///
44/// `Document` and `Array` types may refer to owned/unowned raw BSON types or to a parsed
45/// representation that allows mutation of individual elements. For other variable size types we
46/// either use a [`Cow`] or wrap owned + reference types. Fixed size types use the same inline
47/// representation as they do in [`bson::Bson`] and [`bson::RawBson`].
48#[derive(Clone, Debug)]
49pub enum MutableValue<'a> {
50    Double(f64),
51    String(Cow<'a, str>),
52    Document(MutableDocument<'a>),
53    Array(MutableArray<'a>),
54    Binary(MutableBinary<'a>),
55    Undefined,
56    ObjectId(ObjectId),
57    Boolean(bool),
58    DateTime(DateTime),
59    Null,
60    RegularExpression(MutableRegex<'a>),
61    /// DbPointers cannot be mutated using the `bson` crate.
62    DbPointer(RawDbPointerRef<'a>),
63    JavaScriptCode(Cow<'a, str>),
64    Symbol(Cow<'a, str>),
65    JavaScriptCodeWithScope(MutableJavaScriptCodeWithScope<'a>),
66    Int32(i32),
67    Timestamp(Timestamp),
68    Int64(i64),
69    Decimal128(Decimal128),
70    MinKey,
71    MaxKey,
72}
73
74impl<'a> MutableValue<'a> {
75    /// Get the [`bson::spec::ElementType`] used on the wire for a value type.
76    pub fn element_type(&self) -> ElementType {
77        match self {
78            Self::Double(_) => ElementType::Double,
79            Self::String(_) => ElementType::String,
80            Self::Document(_) => ElementType::EmbeddedDocument,
81            Self::Array(_) => ElementType::Array,
82            Self::Binary(_) => ElementType::Binary,
83            Self::Undefined => ElementType::Undefined,
84            Self::ObjectId(_) => ElementType::ObjectId,
85            Self::Boolean(_) => ElementType::Boolean,
86            Self::DateTime(_) => ElementType::DateTime,
87            Self::Null => ElementType::Null,
88            Self::RegularExpression(_) => ElementType::RegularExpression,
89            Self::DbPointer(_) => ElementType::DbPointer,
90            Self::JavaScriptCode(_) => ElementType::JavaScriptCode,
91            Self::Symbol(_) => ElementType::Symbol,
92            Self::JavaScriptCodeWithScope(_) => ElementType::JavaScriptCodeWithScope,
93            Self::Int32(_) => ElementType::Int32,
94            Self::Timestamp(_) => ElementType::Timestamp,
95            Self::Int64(_) => ElementType::Int64,
96            Self::Decimal128(_) => ElementType::Decimal128,
97            Self::MinKey => ElementType::MinKey,
98            Self::MaxKey => ElementType::MaxKey,
99        }
100    }
101
102    /// Returns the raw binary coded length of this value.
103    fn raw_len(&self) -> usize {
104        match self {
105            Self::Double(_) => 8,
106            Self::String(v) => raw_str_len(v),
107            Self::Document(v) => v.raw_len(),
108            Self::Array(v) => v.raw_len(),
109            Self::Binary(v) => v.raw_len(),
110            Self::Undefined => 0,
111            Self::ObjectId(_) => 12,
112            Self::Boolean(_) => 1,
113            Self::DateTime(_) => 8,
114            Self::Null => 0,
115            Self::RegularExpression(v) => v.raw_len(),
116            // No visibility into DbPointer components. Could still be fixed, it's just annoying.
117            Self::DbPointer(_) => unimplemented!(),
118            Self::JavaScriptCode(v) => raw_str_len(v),
119            Self::Symbol(v) => raw_str_len(v),
120            Self::JavaScriptCodeWithScope(v) => v.raw_len(),
121            Self::Int32(_) => 4,
122            Self::Timestamp(_) => 8,
123            Self::Int64(_) => 8,
124            Self::Decimal128(_) => 16,
125            Self::MinKey => 0,
126            Self::MaxKey => 0,
127        }
128    }
129
130    fn put(&self, buf: &mut impl BufMut) -> Result<(), bson::ser::Error> {
131        match self {
132            Self::Double(v) => buf.put_f64_le(*v),
133            Self::String(v) => put_raw_str(v, buf),
134            Self::Document(v) => v.put(buf)?,
135            Self::Array(v) => v.put(buf)?,
136            Self::Binary(v) => v.put(buf),
137            Self::Undefined => (),
138            Self::ObjectId(v) => buf.put_slice(&v.bytes()),
139            Self::Boolean(v) => buf.put_u8((*v).into()),
140            Self::DateTime(v) => buf.put_i64_le(v.timestamp_millis()),
141            Self::Null => (),
142            Self::RegularExpression(v) => v.put(buf)?,
143            // No visibility into DbPointer components. Could still be fixed, it's just annoying.
144            Self::DbPointer(_) => unimplemented!(),
145            Self::JavaScriptCode(v) => put_raw_str(v, buf),
146            Self::Symbol(v) => put_raw_str(v, buf),
147            Self::JavaScriptCodeWithScope(v) => v.put(buf)?,
148            Self::Int32(v) => buf.put_i32_le(*v),
149            Self::Timestamp(v) => {
150                buf.put_u32_le(v.increment);
151                buf.put_u32_le(v.time);
152            }
153            Self::Int64(v) => buf.put_i64_le(*v),
154            Self::Decimal128(v) => buf.put_slice(&v.bytes()),
155            Self::MinKey => (),
156            Self::MaxKey => (),
157        };
158        Ok(())
159    }
160
161    pub fn as_f64(&self) -> Option<f64> {
162        match self {
163            Self::Double(v) => Some(*v),
164            _ => None,
165        }
166    }
167
168    pub fn as_str(&self) -> Option<&str> {
169        match self {
170            Self::String(v) => Some(v.as_ref()),
171            _ => None,
172        }
173    }
174
175    pub fn as_doc(&self) -> Option<&MutableDocument<'a>> {
176        match self {
177            Self::Document(v) => Some(v),
178            _ => None,
179        }
180    }
181
182    pub fn as_doc_mut(&mut self) -> Option<&mut MutableDocument<'a>> {
183        match self {
184            Self::Document(v) => Some(v),
185            _ => None,
186        }
187    }
188
189    pub fn as_array(&self) -> Option<&MutableArray<'a>> {
190        match self {
191            Self::Array(v) => Some(v),
192            _ => None,
193        }
194    }
195
196    pub fn as_array_mut(&mut self) -> Option<&mut MutableArray<'a>> {
197        match self {
198            Self::Array(v) => Some(v),
199            _ => None,
200        }
201    }
202
203    pub fn as_binary(&self) -> Option<&MutableBinary<'a>> {
204        match self {
205            Self::Binary(v) => Some(v),
206            _ => None,
207        }
208    }
209
210    pub fn as_binary_mut(&mut self) -> Option<&mut MutableBinary<'a>> {
211        match self {
212            Self::Binary(v) => Some(v),
213            _ => None,
214        }
215    }
216
217    pub fn as_object_id(&self) -> Option<ObjectId> {
218        match self {
219            Self::ObjectId(v) => Some(*v),
220            _ => None,
221        }
222    }
223
224    pub fn as_bool(&self) -> Option<bool> {
225        match self {
226            Self::Boolean(v) => Some(*v),
227            _ => None,
228        }
229    }
230
231    pub fn as_date_time(&self) -> Option<DateTime> {
232        match self {
233            Self::DateTime(v) => Some(*v),
234            _ => None,
235        }
236    }
237
238    pub fn as_null(&self) -> Option<()> {
239        match self {
240            Self::Null => Some(()),
241            _ => None,
242        }
243    }
244
245    pub fn as_i32(&self) -> Option<i32> {
246        match self {
247            Self::Int32(v) => Some(*v),
248            _ => None,
249        }
250    }
251
252    pub fn as_timestamp(&self) -> Option<Timestamp> {
253        match self {
254            Self::Timestamp(v) => Some(*v),
255            _ => None,
256        }
257    }
258
259    pub fn as_i64(&self) -> Option<i64> {
260        match self {
261            Self::Int64(v) => Some(*v),
262            _ => None,
263        }
264    }
265}
266
267impl<'a> From<RawBsonRef<'a>> for MutableValue<'a> {
268    fn from(value: RawBsonRef<'a>) -> Self {
269        match value {
270            RawBsonRef::Double(v) => Self::Double(v),
271            RawBsonRef::String(v) => Self::String(v.into()),
272            RawBsonRef::Document(v) => Self::Document(v.into()),
273            RawBsonRef::Array(v) => Self::Array(v.into()),
274            RawBsonRef::Binary(v) => Self::Binary(v.into()),
275            RawBsonRef::Undefined => Self::Undefined,
276            RawBsonRef::ObjectId(v) => Self::ObjectId(v),
277            RawBsonRef::Boolean(v) => Self::Boolean(v),
278            RawBsonRef::DateTime(v) => Self::DateTime(v),
279            RawBsonRef::Null => Self::Null,
280            RawBsonRef::RegularExpression(v) => Self::RegularExpression(v.into()),
281            RawBsonRef::DbPointer(v) => Self::DbPointer(v),
282            RawBsonRef::JavaScriptCode(v) => Self::JavaScriptCode(v.into()),
283            RawBsonRef::Symbol(v) => Self::Symbol(v.into()),
284            RawBsonRef::JavaScriptCodeWithScope(v) => Self::JavaScriptCodeWithScope(v.into()),
285            RawBsonRef::Int32(v) => Self::Int32(v),
286            RawBsonRef::Timestamp(v) => Self::Timestamp(v),
287            RawBsonRef::Int64(v) => Self::Int64(v),
288            RawBsonRef::Decimal128(v) => Self::Decimal128(v),
289            RawBsonRef::MinKey => Self::MinKey,
290            RawBsonRef::MaxKey => Self::MaxKey,
291        }
292    }
293}
294
295impl<'a, T: Clone + Into<MutableValue<'a>>> From<&T> for MutableValue<'a> {
296    fn from(value: &T) -> Self {
297        value.clone().into()
298    }
299}
300
301impl From<Bson> for MutableValue<'_> {
302    fn from(value: Bson) -> Self {
303        match value {
304            Bson::Double(v) => Self::Double(v),
305            Bson::String(v) => Self::String(v.into()),
306            Bson::Document(v) => Self::Document(v.into()),
307            Bson::Array(v) => Self::Array(v.into()),
308            Bson::Binary(v) => Self::Binary(v.into()),
309            Bson::Undefined => Self::Undefined,
310            Bson::ObjectId(v) => Self::ObjectId(v),
311            Bson::Boolean(v) => Self::Boolean(v),
312            Bson::DateTime(v) => Self::DateTime(v),
313            Bson::Null => Self::Null,
314            Bson::RegularExpression(v) => Self::RegularExpression(v.into()),
315            Bson::DbPointer(_) => unimplemented!(),
316            Bson::JavaScriptCode(v) => Self::JavaScriptCode(v.into()),
317            Bson::Symbol(v) => Self::Symbol(v.into()),
318            Bson::JavaScriptCodeWithScope(v) => Self::JavaScriptCodeWithScope(v.into()),
319            Bson::Int32(v) => Self::Int32(v),
320            Bson::Timestamp(v) => Self::Timestamp(v),
321            Bson::Int64(v) => Self::Int64(v),
322            Bson::Decimal128(v) => Self::Decimal128(v),
323            Bson::MinKey => Self::MinKey,
324            Bson::MaxKey => Self::MaxKey,
325        }
326    }
327}
328
329impl From<f64> for MutableValue<'_> {
330    fn from(value: f64) -> Self {
331        Self::Double(value)
332    }
333}
334
335impl From<String> for MutableValue<'_> {
336    fn from(value: String) -> Self {
337        Self::String(value.into())
338    }
339}
340
341impl From<&str> for MutableValue<'_> {
342    fn from(value: &str) -> Self {
343        value.to_owned().into()
344    }
345}
346
347impl<'a> From<ParsedDocument<'a>> for MutableValue<'a> {
348    fn from(value: ParsedDocument<'a>) -> Self {
349        Self::Document(value.into())
350    }
351}
352
353impl<'a> From<Vec<MutableValue<'a>>> for MutableValue<'a> {
354    fn from(value: Vec<MutableValue<'a>>) -> Self {
355        Self::Array(value.into())
356    }
357}
358
359impl<'a> From<MutableBinary<'a>> for MutableValue<'a> {
360    fn from(value: MutableBinary<'a>) -> Self {
361        Self::Binary(value)
362    }
363}
364
365impl From<Binary> for MutableValue<'_> {
366    fn from(value: Binary) -> Self {
367        Self::Binary(value.into())
368    }
369}
370
371impl From<ObjectId> for MutableValue<'_> {
372    fn from(value: ObjectId) -> Self {
373        Self::ObjectId(value)
374    }
375}
376
377impl From<bool> for MutableValue<'_> {
378    fn from(value: bool) -> Self {
379        Self::Boolean(value)
380    }
381}
382
383impl From<DateTime> for MutableValue<'_> {
384    fn from(value: DateTime) -> Self {
385        Self::DateTime(value)
386    }
387}
388
389impl<'a> From<MutableRegex<'a>> for MutableValue<'a> {
390    fn from(value: MutableRegex<'a>) -> Self {
391        Self::RegularExpression(value)
392    }
393}
394
395impl From<Regex> for MutableValue<'_> {
396    fn from(value: Regex) -> Self {
397        Self::RegularExpression(value.into())
398    }
399}
400
401impl<'a> From<MutableJavaScriptCodeWithScope<'a>> for MutableValue<'a> {
402    fn from(value: MutableJavaScriptCodeWithScope<'a>) -> Self {
403        Self::JavaScriptCodeWithScope(value)
404    }
405}
406
407impl From<i32> for MutableValue<'_> {
408    fn from(value: i32) -> Self {
409        Self::Int32(value)
410    }
411}
412
413impl From<Timestamp> for MutableValue<'_> {
414    fn from(value: Timestamp) -> Self {
415        Self::Timestamp(value)
416    }
417}
418
419impl From<i64> for MutableValue<'_> {
420    fn from(value: i64) -> Self {
421        Self::Int64(value)
422    }
423}
424
425impl From<Decimal128> for MutableValue<'_> {
426    fn from(value: Decimal128) -> Self {
427        Self::Decimal128(value)
428    }
429}
430
431/// Contains either an encoded BSON document or a [`ParsedDocument`] that has decoded all of the
432/// key and [`MutableValue`] pairs for fast access and to allow mutation.
433///
434/// NB: while [bson::RawDocument] provides keyed access, it does so by decoding from the beginning
435/// of the document so it is often unwise to use [bson::RawDocument::get] and friends.
436#[derive(Clone, Debug)]
437pub enum MutableDocument<'a> {
438    Borrowed(&'a RawDocument),
439    Owned(ParsedDocument<'a>),
440}
441
442impl<'a> MutableDocument<'a> {
443    /// Try to convert the representation to a [`ParsedDocument`] from a [`RawDocument`](bson::RawDocument)
444    /// if necessary.
445    ///
446    /// May fail with a raw BSON parsing error.
447    // TODO: this should be a impl TryFrom<MutableDocument> for ParsedDocument
448    pub fn try_into_parsed(self) -> Result<Self, bson::raw::Error> {
449        match self {
450            Self::Owned(p) => Ok(p.into()),
451            Self::Borrowed(e) => ParsedDocument::try_from(e).map(Self::from),
452        }
453    }
454
455    /// Try to convert the representation to a [`ParsedArray`] from a [`RawArray`](bson::RawArray)
456    /// if necessary and return a mutable reference to the `ParsedArray`.
457    ///
458    /// May fail with a raw BSON parsing error.
459    pub fn to_parsed(&mut self) -> Result<&mut ParsedDocument<'a>, bson::raw::Error> {
460        if let Self::Borrowed(e) = self {
461            *self = Self::Owned(ParsedDocument::try_from(e as &RawDocument)?);
462        }
463        match self {
464            Self::Borrowed(_) => unreachable!(),
465            Self::Owned(p) => Ok(p),
466        }
467    }
468
469    fn raw_len(&self) -> usize {
470        match self {
471            Self::Borrowed(e) => e.as_bytes().len(),
472            Self::Owned(p) => p.raw_len(),
473        }
474    }
475
476    fn put(&self, buf: &mut impl BufMut) -> Result<(), bson::ser::Error> {
477        match self {
478            Self::Borrowed(e) => {
479                buf.put_slice(e.as_bytes());
480                Ok(())
481            }
482            Self::Owned(p) => p.put(buf),
483        }
484    }
485
486    /// Produce an encoded raw document.
487    pub fn to_vec(&self) -> Result<Vec<u8>, bson::ser::Error> {
488        // TODO: cache the raw length in all MutableValues where length computation is non-trivial.
489        // Leaving this uncache is a problem because we will call raw_len() twice on the root
490        // document: once to size the output buffer and once to emit the buffer, and this will be
491        // done for all mutable objects down the tree. The borrow checker should help us here as
492        // all mutable methods can ensure that the cached value is invalidated.
493        // This is easy for ParsedDocument, MutableArray::Owned would need a lot of work.
494        let len = self.raw_len();
495        if len >= 32 << 20 {
496            return Err(bson::ser::Error::Io(Arc::new(std::io::Error::new(
497                std::io::ErrorKind::InvalidData,
498                "Exceeded max document length",
499            ))));
500        }
501        let mut buf = Vec::with_capacity(len);
502        self.put(&mut buf).map(|_| buf)
503    }
504}
505
506impl<'a> From<&'a RawDocument> for MutableDocument<'a> {
507    fn from(value: &'a RawDocument) -> Self {
508        Self::Borrowed(value)
509    }
510}
511
512impl<'a> From<ParsedDocument<'a>> for MutableDocument<'a> {
513    fn from(value: ParsedDocument<'a>) -> Self {
514        Self::Owned(value)
515    }
516}
517
518impl From<Document> for MutableDocument<'_> {
519    fn from(value: Document) -> Self {
520        Self::Owned(value.into())
521    }
522}
523
524/// Contains either an encoded BSON array or a [`Vec`] of [`MutableValue`]s decoded from a raw array
525/// to allow fast access and mutation.
526///
527/// NB: while [bson::RawArray] provides indexed access, it does so by decoding from the beginning
528/// of the array so it is often unwise to use [bson::RawArray::get] and friends.
529#[derive(Clone, Debug)]
530pub enum MutableArray<'a> {
531    Borrowed(&'a RawArray),
532    Owned(Vec<MutableValue<'a>>),
533}
534
535impl<'a> MutableArray<'a> {
536    /// Try to convert the representation to a [`ParsedArray`] from a [`RawArray`](bson::RawArray)
537    /// if necessary.
538    ///
539    /// May fail with a raw BSON parsing error.
540    pub fn try_into_parsed(self) -> Result<Self, bson::raw::Error> {
541        match self {
542            Self::Owned(p) => Ok(p.into()),
543            Self::Borrowed(e) => Self::encoded_to_parsed(e).map(Self::from),
544        }
545    }
546
547    /// Try to convert the representation to a [`ParsedArray`] from a [`RawArray`](bson::RawArray)
548    /// if necessary and return a mutable reference to the `ParsedArray`.
549    ///
550    /// May fail with a raw BSON parsing error.
551    pub fn to_parsed(&mut self) -> Result<&mut Vec<MutableValue<'a>>, bson::raw::Error> {
552        if let Self::Borrowed(e) = self {
553            *self = Self::Owned(Self::encoded_to_parsed(e as &RawArray)?);
554        }
555        match self {
556            Self::Borrowed(_) => unreachable!(),
557            Self::Owned(p) => Ok(p),
558        }
559    }
560
561    fn encoded_to_parsed(raw: &RawArray) -> Result<Vec<MutableValue<'_>>, bson::raw::Error> {
562        let mut values = vec![];
563        for e in raw.into_iter() {
564            values.push((e?).into());
565        }
566        Ok(values)
567    }
568
569    fn raw_len(&self) -> usize {
570        match self {
571            Self::Borrowed(e) => e.as_bytes().len(),
572            Self::Owned(p) => {
573                // TODO: more efficient way of counting key bytes.
574                p.iter()
575                    .enumerate()
576                    .map(|(i, v)| 1 + raw_cstr_len(itoa::Buffer::new().format(i)) + v.raw_len())
577                    .sum::<usize>()
578                    // doc length
579                    + 4usize
580                    // doc null terminator
581                    + 1usize
582            }
583        }
584    }
585
586    fn put(&self, buf: &mut impl BufMut) -> Result<(), bson::ser::Error> {
587        match self {
588            Self::Borrowed(e) => {
589                buf.put_slice(e.as_bytes());
590                Ok(())
591            }
592            Self::Owned(p) => {
593                buf.put_i32_le(
594                    self.raw_len()
595                        .try_into()
596                        .expect("message len validated before put"),
597                );
598                for (i, v) in p.iter().enumerate() {
599                    buf.put_u8(v.element_type() as u8);
600                    put_raw_cstr(itoa::Buffer::new().format(i), buf)
601                        .expect("itoa does not contain nulls");
602                    v.put(buf)?;
603                }
604                buf.put_u8(0);
605                Ok(())
606            }
607        }
608    }
609}
610
611impl<'a> From<&'a RawArray> for MutableArray<'a> {
612    fn from(value: &'a RawArray) -> Self {
613        Self::Borrowed(value)
614    }
615}
616
617impl<'a> From<Vec<MutableValue<'a>>> for MutableArray<'a> {
618    fn from(value: Vec<MutableValue<'a>>) -> Self {
619        Self::Owned(value)
620    }
621}
622
623impl From<Vec<Bson>> for MutableArray<'_> {
624    fn from(value: Vec<Bson>) -> Self {
625        Self::Owned(value.into_iter().map(MutableValue::from).collect())
626    }
627}
628
629#[derive(Clone, Debug)]
630pub enum MutableBinary<'a> {
631    Borrowed(RawBinaryRef<'a>),
632    Owned(Binary),
633}
634
635impl MutableBinary<'_> {
636    fn raw_len(&self) -> usize {
637        let bytes = match self {
638            Self::Borrowed(v) => v.bytes,
639            Self::Owned(v) => v.bytes.as_ref(),
640        };
641        // length of the byte string + 4 bytes for length + 1 byte for subtype.
642        4 + bytes.len() + 1
643    }
644
645    fn put(&self, buf: &mut impl BufMut) {
646        let (bytes, subtype) = match self {
647            Self::Borrowed(v) => (v.bytes, v.subtype),
648            Self::Owned(v) => (v.bytes.as_ref(), v.subtype),
649        };
650        buf.put_i32_le(
651            bytes
652                .len()
653                .try_into()
654                .expect("message len verified before put"),
655        );
656        buf.put_u8(subtype.into());
657        buf.put_slice(bytes);
658    }
659}
660
661impl<'a> From<RawBinaryRef<'a>> for MutableBinary<'a> {
662    fn from(value: RawBinaryRef<'a>) -> Self {
663        Self::Borrowed(value)
664    }
665}
666
667impl From<Binary> for MutableBinary<'_> {
668    fn from(value: Binary) -> Self {
669        Self::Owned(value)
670    }
671}
672
673#[derive(Clone, Debug)]
674pub enum MutableRegex<'a> {
675    Borrowed(RawRegexRef<'a>),
676    Owned(Regex),
677}
678
679impl MutableRegex<'_> {
680    fn raw_len(&self) -> usize {
681        let (pattern, options) = self.parts();
682        raw_cstr_len(pattern) + raw_cstr_len(options)
683    }
684
685    fn put(&self, buf: &mut impl BufMut) -> Result<(), bson::ser::Error> {
686        let (pattern, options) = self.parts();
687        put_raw_cstr(pattern, buf)?;
688        put_raw_cstr(options, buf)
689    }
690
691    fn parts(&self) -> (&str, &str) {
692        match self {
693            Self::Borrowed(v) => (v.pattern, v.options),
694            Self::Owned(v) => (v.pattern.as_ref(), v.options.as_ref()),
695        }
696    }
697}
698
699impl<'a> From<RawRegexRef<'a>> for MutableRegex<'a> {
700    fn from(value: RawRegexRef<'a>) -> Self {
701        Self::Borrowed(value)
702    }
703}
704
705impl From<Regex> for MutableRegex<'_> {
706    fn from(value: Regex) -> Self {
707        Self::Owned(value)
708    }
709}
710
711#[derive(Clone, Debug)]
712pub enum MutableJavaScriptCodeWithScope<'a> {
713    Borrowed(RawJavaScriptCodeWithScopeRef<'a>),
714    Owned(JavaScriptCodeWithScope),
715}
716
717impl MutableJavaScriptCodeWithScope<'_> {
718    fn raw_len(&self) -> usize {
719        match self {
720            Self::Borrowed(v) => 4 + raw_str_len(v.code) + v.scope.as_bytes().len(),
721            Self::Owned(v) => {
722                // TODO: the owned object should be code + ParsedDocument scoped.
723                4 + raw_str_len(&v.code) + bson::to_vec(&v.scope).unwrap().len()
724            }
725        }
726    }
727
728    fn put(&self, buf: &mut impl BufMut) -> Result<(), bson::ser::Error> {
729        match self {
730            Self::Borrowed(v) => {
731                buf.put_i32_le(
732                    (raw_str_len(v.code) + v.scope.as_bytes().len() + 4)
733                        .try_into()
734                        .expect("document length verified before put()"),
735                );
736                put_raw_str(v.code, buf);
737                buf.put_slice(v.scope.as_bytes());
738            }
739            Self::Owned(v) => {
740                let encoded_scope = bson::to_vec(&v.scope)?;
741                buf.put_i32_le(
742                    (raw_str_len(&v.code) + encoded_scope.len() + 4)
743                        .try_into()
744                        .expect("document length verified before put()"),
745                );
746                put_raw_str(&v.code, buf);
747                buf.put_slice(&encoded_scope);
748            }
749        };
750        Ok(())
751    }
752}
753
754impl<'a> From<RawJavaScriptCodeWithScopeRef<'a>> for MutableJavaScriptCodeWithScope<'a> {
755    fn from(value: RawJavaScriptCodeWithScopeRef<'a>) -> Self {
756        Self::Borrowed(value)
757    }
758}
759
760impl From<JavaScriptCodeWithScope> for MutableJavaScriptCodeWithScope<'_> {
761    fn from(value: JavaScriptCodeWithScope) -> Self {
762        Self::Owned(value)
763    }
764}
765
766#[cfg(test)]
767mod tests {
768    #[test]
769    fn it_works() {}
770}