bson/raw/
array_buf.rs

1use std::{
2    borrow::{Borrow, Cow},
3    fmt::Debug,
4};
5
6use crate::{RawArray, RawBsonRef, RawDocumentBuf};
7
8use super::{document_buf::BindRawBsonRef, RawArrayIter};
9
10/// An owned BSON array value (akin to [`std::path::PathBuf`]), backed by a buffer of raw BSON
11/// bytes. This type can be used to construct owned array values, which can be used to append to
12/// [`RawDocumentBuf`] or as a field in a [`Deserialize`](serde::Deserialize) struct.
13///
14/// Iterating over a [`RawArrayBuf`] yields either an error or a [`RawBson`](crate::raw::RawBson)
15/// value that borrows from the original document without making any additional allocations.
16/// ```
17/// # use bson::error::Error;
18/// use bson::raw::RawArrayBuf;
19///
20/// let mut array = RawArrayBuf::new();
21/// array.push("a string");
22/// array.push(12_i32);
23///
24/// let mut iter = array.into_iter();
25///
26/// let value = iter.next().unwrap()?;
27/// assert_eq!(value.as_str(), Some("a string"));
28///
29/// let value = iter.next().unwrap()?;
30/// assert_eq!(value.as_i32(), Some(12));
31///
32/// assert!(iter.next().is_none());
33/// # Ok::<(), Error>(())
34/// ```
35///
36/// This type implements [`Deref`](std::ops::Deref) to [`RawArray`], meaning that all methods on
37/// [`RawArray`] are available on [`RawArrayBuf`] values as well. This includes [`RawArray::get`] or
38/// any of the type-specific getters, such as [`RawArray::get_object_id`] or [`RawArray::get_str`].
39/// Note that accessing elements is an O(N) operation, as it requires iterating through the document
40/// from the beginning to find the requested key.
41#[derive(Clone, PartialEq)]
42pub struct RawArrayBuf {
43    inner: RawDocumentBuf,
44    len: usize,
45}
46
47impl RawArrayBuf {
48    /// Construct a new, empty [`RawArrayBuf`].
49    pub fn new() -> RawArrayBuf {
50        Self {
51            inner: RawDocumentBuf::new(),
52            len: 0,
53        }
54    }
55
56    /// Construct a new [`RawArrayBuf`] from the provided [`Vec`] of bytes.
57    ///
58    /// This involves a traversal of the array to count the values.
59    pub(crate) fn from_raw_document_buf(doc: RawDocumentBuf) -> Self {
60        let len = doc.iter().count();
61        Self { inner: doc, len }
62    }
63
64    /// Append a value to the end of the array.
65    ///
66    /// ```
67    /// # use bson::error::Error;
68    /// use bson::raw::{cstr, RawArrayBuf, RawDocumentBuf};
69    ///
70    /// let mut array = RawArrayBuf::new();
71    /// array.push("a string");
72    /// array.push(12_i32);
73    ///
74    /// let mut doc = RawDocumentBuf::new();
75    /// doc.append(cstr!("a key"), "a value");
76    /// array.push(doc.clone());
77    ///
78    /// let mut iter = array.into_iter();
79    ///
80    /// let value = iter.next().unwrap()?;
81    /// assert_eq!(value.as_str(), Some("a string"));
82    ///
83    /// let value = iter.next().unwrap()?;
84    /// assert_eq!(value.as_i32(), Some(12));
85    ///
86    /// let value = iter.next().unwrap()?;
87    /// assert_eq!(value.as_document(), Some(doc.as_ref()));
88    ///
89    /// assert!(iter.next().is_none());
90    /// # Ok::<(), Error>(())
91    /// ```
92    pub fn push(&mut self, value: impl BindRawBsonRef) {
93        self.inner.append(
94            super::CString::from_string_unchecked(self.len.to_string()),
95            value,
96        );
97        self.len += 1;
98    }
99}
100
101impl<B: BindRawBsonRef> FromIterator<B> for RawArrayBuf {
102    fn from_iter<T: IntoIterator<Item = B>>(iter: T) -> Self {
103        let mut array_buf = RawArrayBuf::new();
104        for item in iter {
105            array_buf.push(item);
106        }
107        array_buf
108    }
109}
110
111impl Debug for RawArrayBuf {
112    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
113        f.debug_struct("RawArrayBuf")
114            .field("data", &hex::encode(self.as_bytes()))
115            .field("len", &self.len)
116            .finish()
117    }
118}
119
120impl std::ops::Deref for RawArrayBuf {
121    type Target = RawArray;
122
123    fn deref(&self) -> &Self::Target {
124        RawArray::from_doc(&self.inner)
125    }
126}
127
128impl AsRef<RawArray> for RawArrayBuf {
129    fn as_ref(&self) -> &RawArray {
130        RawArray::from_doc(&self.inner)
131    }
132}
133
134impl Borrow<RawArray> for RawArrayBuf {
135    fn borrow(&self) -> &RawArray {
136        self.as_ref()
137    }
138}
139
140impl<'a> IntoIterator for &'a RawArrayBuf {
141    type IntoIter = RawArrayIter<'a>;
142    type Item = super::Result<RawBsonRef<'a>>;
143
144    fn into_iter(self) -> RawArrayIter<'a> {
145        self.as_ref().into_iter()
146    }
147}
148
149impl From<RawArrayBuf> for Cow<'_, RawArray> {
150    fn from(rd: RawArrayBuf) -> Self {
151        Cow::Owned(rd)
152    }
153}
154
155impl<'a> From<&'a RawArrayBuf> for Cow<'a, RawArray> {
156    fn from(rd: &'a RawArrayBuf) -> Self {
157        Cow::Borrowed(rd.as_ref())
158    }
159}
160
161#[cfg(feature = "serde")]
162impl<'de> serde::Deserialize<'de> for RawArrayBuf {
163    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
164    where
165        D: serde::Deserializer<'de>,
166    {
167        Ok(super::serde::OwnedOrBorrowedRawArray::deserialize(deserializer)?.into_owned())
168    }
169}
170
171#[cfg(feature = "serde")]
172impl serde::Serialize for RawArrayBuf {
173    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
174    where
175        S: serde::Serializer,
176    {
177        self.as_ref().serialize(serializer)
178    }
179}
180
181impl Default for RawArrayBuf {
182    fn default() -> Self {
183        Self::new()
184    }
185}
186
187impl TryFrom<&crate::Array> for RawArrayBuf {
188    type Error = crate::error::Error;
189
190    fn try_from(value: &crate::Array) -> Result<Self, Self::Error> {
191        Self::try_from(value.clone())
192    }
193}
194
195impl TryFrom<crate::Array> for RawArrayBuf {
196    type Error = crate::error::Error;
197
198    fn try_from(value: crate::Array) -> Result<Self, Self::Error> {
199        let mut tmp = RawArrayBuf::new();
200        for val in value {
201            let raw: super::RawBson = val.try_into()?;
202            tmp.push(raw);
203        }
204        Ok(tmp)
205    }
206}