bson/raw/
array.rs

1use std::{borrow::Cow, convert::TryFrom};
2
3use super::{
4    Error as RawError,
5    RawBinaryRef,
6    RawBsonRef,
7    RawDocument,
8    RawIter,
9    RawRegexRef,
10    Result as RawResult,
11};
12use crate::{
13    error::{Error, Result},
14    oid::ObjectId,
15    spec::ElementType,
16    Bson,
17    DateTime,
18    RawArrayBuf,
19    Timestamp,
20};
21
22/// A slice of a BSON document containing a BSON array value (akin to [`std::str`]). This can be
23/// retrieved from a [`RawDocument`] via [`RawDocument::get`].
24///
25/// This is an _unsized_ type, meaning that it must always be used behind a pointer like `&`.
26///
27/// Accessing elements within a [`RawArray`] is similar to element access in [`crate::Document`],
28/// but because the contents are parsed during iteration instead of at creation time, format errors
29/// can happen at any time during use.
30///
31/// Iterating over a [`RawArray`] yields either an error or a value that borrows from the
32/// original document without making any additional allocations.
33///
34/// ```
35/// use bson::{doc, raw::RawDocument};
36///
37/// let doc = doc! {
38///     "x": [1, true, "two", 5.5]
39/// };
40/// let bytes = bson::serialize_to_vec(&doc)?;
41///
42/// let rawdoc = RawDocument::from_bytes(bytes.as_slice())?;
43/// let rawarray = rawdoc.get_array("x")?;
44///
45/// for v in rawarray {
46///     println!("{:?}", v?);
47/// }
48/// # Ok::<(), Box<dyn std::error::Error>>(())
49/// ```
50///
51/// Individual elements can be accessed using [`RawArray::get`] or any of
52/// the type-specific getters, such as [`RawArray::get_object_id`] or
53/// [`RawArray::get_str`]. Note that accessing elements is an O(N) operation, as it
54/// requires iterating through the array from the beginning to find the requested index.
55///
56/// ```
57/// use bson::{doc, raw::RawDocument};
58///
59/// let doc = doc! {
60///     "x": [1, true, "two", 5.5]
61/// };
62/// let bytes = doc.to_vec()?;
63///
64/// let rawdoc = RawDocument::from_bytes(bytes.as_slice())?;
65/// let rawarray = rawdoc.get_array("x")?;
66///
67/// assert_eq!(rawarray.get_bool(1)?, true);
68/// # Ok::<(), Box<dyn std::error::Error>>(())
69/// ```
70#[derive(PartialEq)]
71#[repr(transparent)]
72pub struct RawArray {
73    pub(crate) doc: RawDocument,
74}
75
76impl RawArray {
77    pub(crate) fn from_doc(doc: &RawDocument) -> &RawArray {
78        // SAFETY:
79        //
80        // Dereferencing a raw pointer requires unsafe due to the potential that the pointer is
81        // null, dangling, or misaligned. We know the pointer is not null or dangling due to the
82        // fact that it's created by a safe reference. Converting &RawDocument to *const
83        // RawDocument will be properly aligned due to them being references to the same type,
84        // and converting *const RawDocument to *const RawArray is aligned due to the fact that
85        // the only field in a RawArray is a RawDocument, meaning the structs are represented
86        // identically at the byte level.
87        unsafe { &*(doc as *const RawDocument as *const RawArray) }
88    }
89
90    #[cfg(feature = "serde")]
91    pub(crate) fn as_doc(&self) -> &RawDocument {
92        &self.doc
93    }
94
95    /// Gets a reference to the value at the given index.
96    pub fn get(&self, index: usize) -> RawResult<Option<RawBsonRef<'_>>> {
97        self.into_iter().nth(index).transpose()
98    }
99
100    fn get_with<'a, T>(
101        &'a self,
102        index: usize,
103        expected_type: ElementType,
104        f: impl FnOnce(RawBsonRef<'a>) -> Option<T>,
105    ) -> Result<T> {
106        let bson = self
107            .get(index)
108            .map_err(|e| Error::value_access_invalid_bson(format!("{:?}", e)))?
109            .ok_or_else(Error::value_access_not_present)
110            .map_err(|e| e.with_index(index))?;
111        match f(bson) {
112            Some(t) => Ok(t),
113            None => Err(
114                Error::value_access_unexpected_type(bson.element_type(), expected_type)
115                    .with_index(index),
116            ),
117        }
118    }
119
120    /// Gets the BSON double at the given index or returns an error if the value at that index isn't
121    /// a double.
122    pub fn get_f64(&self, index: usize) -> Result<f64> {
123        self.get_with(index, ElementType::Double, RawBsonRef::as_f64)
124    }
125
126    /// Gets a reference to the string at the given index or returns an error if the
127    /// value at that index isn't a string.
128    pub fn get_str(&self, index: usize) -> Result<&str> {
129        self.get_with(index, ElementType::String, RawBsonRef::as_str)
130    }
131
132    /// Gets a reference to the document at the given index or returns an error if the
133    /// value at that index isn't a document.
134    pub fn get_document(&self, index: usize) -> Result<&RawDocument> {
135        self.get_with(
136            index,
137            ElementType::EmbeddedDocument,
138            RawBsonRef::as_document,
139        )
140    }
141
142    /// Gets a reference to the array at the given index or returns an error if the
143    /// value at that index isn't a array.
144    pub fn get_array(&self, index: usize) -> Result<&RawArray> {
145        self.get_with(index, ElementType::Array, RawBsonRef::as_array)
146    }
147
148    /// Gets a reference to the BSON binary value at the given index or returns an error if the
149    /// value at that index isn't a binary.
150    pub fn get_binary(&self, index: usize) -> Result<RawBinaryRef<'_>> {
151        self.get_with(index, ElementType::Binary, RawBsonRef::as_binary)
152    }
153
154    /// Gets the ObjectId at the given index or returns an error if the value at that index isn't an
155    /// ObjectId.
156    pub fn get_object_id(&self, index: usize) -> Result<ObjectId> {
157        self.get_with(index, ElementType::ObjectId, RawBsonRef::as_object_id)
158    }
159
160    /// Gets the boolean at the given index or returns an error if the value at that index isn't a
161    /// boolean.
162    pub fn get_bool(&self, index: usize) -> Result<bool> {
163        self.get_with(index, ElementType::Boolean, RawBsonRef::as_bool)
164    }
165
166    /// Gets the DateTime at the given index or returns an error if the value at that index isn't a
167    /// DateTime.
168    pub fn get_datetime(&self, index: usize) -> Result<DateTime> {
169        self.get_with(index, ElementType::DateTime, RawBsonRef::as_datetime)
170    }
171
172    /// Gets a reference to the BSON regex at the given index or returns an error if the
173    /// value at that index isn't a regex.
174    pub fn get_regex(&self, index: usize) -> Result<RawRegexRef<'_>> {
175        self.get_with(index, ElementType::RegularExpression, RawBsonRef::as_regex)
176    }
177
178    /// Gets a reference to the BSON timestamp at the given index or returns an error if the
179    /// value at that index isn't a timestamp.
180    pub fn get_timestamp(&self, index: usize) -> Result<Timestamp> {
181        self.get_with(index, ElementType::Timestamp, RawBsonRef::as_timestamp)
182    }
183
184    /// Gets the BSON int32 at the given index or returns an error if the value at that index isn't
185    /// a 32-bit integer.
186    pub fn get_i32(&self, index: usize) -> Result<i32> {
187        self.get_with(index, ElementType::Int32, RawBsonRef::as_i32)
188    }
189
190    /// Gets BSON int64 at the given index or returns an error if the value at that index isn't a
191    /// 64-bit integer.
192    pub fn get_i64(&self, index: usize) -> Result<i64> {
193        self.get_with(index, ElementType::Int64, RawBsonRef::as_i64)
194    }
195
196    /// Gets a reference to the raw bytes of the [`RawArray`].
197    pub fn as_bytes(&self) -> &[u8] {
198        self.doc.as_bytes()
199    }
200
201    /// Whether this array contains any elements or not.
202    pub fn is_empty(&self) -> bool {
203        self.doc.is_empty()
204    }
205
206    /// Gets an iterator over the elements in the [`RawArray`],
207    /// which yields `Result<RawElement<'_>>` values. These hold a
208    /// reference to the underlying array but do not explicitly
209    /// resolve the values.
210    ///
211    /// This iterator, which underpins the implementation of the
212    /// default iterator, produces `RawElement` objects that hold a
213    /// view onto the array but do not parse out or construct
214    /// values until the `.value()` or `.try_into()` methods are
215    /// called.
216    pub fn iter_elements(&self) -> RawIter<'_> {
217        RawIter::new(&self.doc)
218    }
219}
220
221impl std::fmt::Debug for RawArray {
222    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
223        f.debug_struct("RawArray")
224            .field("data", &hex::encode(self.doc.as_bytes()))
225            .finish()
226    }
227}
228
229impl TryFrom<&RawArray> for Vec<Bson> {
230    type Error = RawError;
231
232    fn try_from(arr: &RawArray) -> RawResult<Vec<Bson>> {
233        arr.into_iter()
234            .map(|result| {
235                let rawbson = result?;
236                Bson::try_from(rawbson)
237            })
238            .collect()
239    }
240}
241
242impl ToOwned for RawArray {
243    type Owned = RawArrayBuf;
244
245    fn to_owned(&self) -> Self::Owned {
246        RawArrayBuf::from_raw_document_buf(self.doc.to_owned())
247    }
248}
249
250impl<'a> From<&'a RawArray> for Cow<'a, RawArray> {
251    fn from(rdr: &'a RawArray) -> Self {
252        Cow::Borrowed(rdr)
253    }
254}
255
256impl<'a> IntoIterator for &'a RawArray {
257    type IntoIter = RawArrayIter<'a>;
258    type Item = RawResult<RawBsonRef<'a>>;
259
260    fn into_iter(self) -> RawArrayIter<'a> {
261        RawArrayIter {
262            inner: RawIter::new(&self.doc),
263        }
264    }
265}
266
267/// An iterator over borrowed raw BSON array values.
268pub struct RawArrayIter<'a> {
269    inner: RawIter<'a>,
270}
271
272impl<'a> Iterator for RawArrayIter<'a> {
273    type Item = RawResult<RawBsonRef<'a>>;
274
275    fn next(&mut self) -> Option<RawResult<RawBsonRef<'a>>> {
276        match self.inner.next() {
277            Some(Ok(elem)) => match elem.value() {
278                Ok(value) => Some(Ok(value)),
279                Err(e) => Some(Err(e)),
280            },
281            Some(Err(e)) => Some(Err(e)),
282            None => None,
283        }
284    }
285}
286
287#[cfg(feature = "serde")]
288impl<'de: 'a, 'a> serde::Deserialize<'de> for &'a RawArray {
289    fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
290    where
291        D: serde::Deserializer<'de>,
292    {
293        use super::serde::OwnedOrBorrowedRawArray;
294        match OwnedOrBorrowedRawArray::deserialize(deserializer)? {
295            OwnedOrBorrowedRawArray::Borrowed(b) => Ok(b),
296            o => Err(serde::de::Error::custom(format!(
297                "expected borrowed raw array, instead got owned {:?}",
298                o
299            ))),
300        }
301    }
302}
303
304#[cfg(feature = "serde")]
305impl serde::Serialize for &RawArray {
306    fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
307    where
308        S: serde::Serializer,
309    {
310        struct SeqSerializer<'a>(&'a RawArray);
311
312        impl serde::Serialize for SeqSerializer<'_> {
313            fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
314            where
315                S: serde::Serializer,
316            {
317                use serde::ser::SerializeSeq as _;
318                if serializer.is_human_readable() {
319                    let mut seq = serializer.serialize_seq(None)?;
320                    for v in self.0 {
321                        let v = v.map_err(serde::ser::Error::custom)?;
322                        seq.serialize_element(&v)?;
323                    }
324                    seq.end()
325                } else {
326                    serializer.serialize_bytes(self.0.as_bytes())
327                }
328            }
329        }
330
331        serializer.serialize_newtype_struct(crate::raw::RAW_ARRAY_NEWTYPE, &SeqSerializer(self))
332    }
333}