bson2/raw/
array.rs

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