use std::{borrow::Cow, convert::TryFrom};
use super::{
Error as RawError,
RawBinaryRef,
RawBsonRef,
RawDocument,
RawIter,
RawRegexRef,
Result as RawResult,
};
use crate::{
error::{Error, Result},
oid::ObjectId,
spec::ElementType,
Bson,
DateTime,
RawArrayBuf,
Timestamp,
};
#[derive(PartialEq)]
#[repr(transparent)]
pub struct RawArray {
pub(crate) doc: RawDocument,
}
impl RawArray {
pub(crate) fn from_doc(doc: &RawDocument) -> &RawArray {
unsafe { &*(doc as *const RawDocument as *const RawArray) }
}
#[cfg(feature = "serde")]
pub(crate) fn as_doc(&self) -> &RawDocument {
&self.doc
}
pub fn get(&self, index: usize) -> RawResult<Option<RawBsonRef<'_>>> {
self.into_iter().nth(index).transpose()
}
fn get_with<'a, T>(
&'a self,
index: usize,
expected_type: ElementType,
f: impl FnOnce(RawBsonRef<'a>) -> Option<T>,
) -> Result<T> {
let bson = self
.get(index)
.map_err(|e| Error::value_access_invalid_bson(format!("{:?}", e)))?
.ok_or_else(Error::value_access_not_present)
.map_err(|e| e.with_index(index))?;
match f(bson) {
Some(t) => Ok(t),
None => Err(
Error::value_access_unexpected_type(bson.element_type(), expected_type)
.with_index(index),
),
}
}
pub fn get_f64(&self, index: usize) -> Result<f64> {
self.get_with(index, ElementType::Double, RawBsonRef::as_f64)
}
pub fn get_str(&self, index: usize) -> Result<&str> {
self.get_with(index, ElementType::String, RawBsonRef::as_str)
}
pub fn get_document(&self, index: usize) -> Result<&RawDocument> {
self.get_with(
index,
ElementType::EmbeddedDocument,
RawBsonRef::as_document,
)
}
pub fn get_array(&self, index: usize) -> Result<&RawArray> {
self.get_with(index, ElementType::Array, RawBsonRef::as_array)
}
pub fn get_binary(&self, index: usize) -> Result<RawBinaryRef<'_>> {
self.get_with(index, ElementType::Binary, RawBsonRef::as_binary)
}
pub fn get_object_id(&self, index: usize) -> Result<ObjectId> {
self.get_with(index, ElementType::ObjectId, RawBsonRef::as_object_id)
}
pub fn get_bool(&self, index: usize) -> Result<bool> {
self.get_with(index, ElementType::Boolean, RawBsonRef::as_bool)
}
pub fn get_datetime(&self, index: usize) -> Result<DateTime> {
self.get_with(index, ElementType::DateTime, RawBsonRef::as_datetime)
}
pub fn get_regex(&self, index: usize) -> Result<RawRegexRef<'_>> {
self.get_with(index, ElementType::RegularExpression, RawBsonRef::as_regex)
}
pub fn get_timestamp(&self, index: usize) -> Result<Timestamp> {
self.get_with(index, ElementType::Timestamp, RawBsonRef::as_timestamp)
}
pub fn get_i32(&self, index: usize) -> Result<i32> {
self.get_with(index, ElementType::Int32, RawBsonRef::as_i32)
}
pub fn get_i64(&self, index: usize) -> Result<i64> {
self.get_with(index, ElementType::Int64, RawBsonRef::as_i64)
}
pub fn as_bytes(&self) -> &[u8] {
self.doc.as_bytes()
}
pub fn is_empty(&self) -> bool {
self.doc.is_empty()
}
pub fn iter_elements(&self) -> RawIter<'_> {
RawIter::new(&self.doc)
}
}
impl std::fmt::Debug for RawArray {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RawArray")
.field("data", &hex::encode(self.doc.as_bytes()))
.finish()
}
}
impl TryFrom<&RawArray> for Vec<Bson> {
type Error = RawError;
fn try_from(arr: &RawArray) -> RawResult<Vec<Bson>> {
arr.into_iter()
.map(|result| {
let rawbson = result?;
Bson::try_from(rawbson)
})
.collect()
}
}
impl ToOwned for RawArray {
type Owned = RawArrayBuf;
fn to_owned(&self) -> Self::Owned {
RawArrayBuf::from_raw_document_buf(self.doc.to_owned())
}
}
impl<'a> From<&'a RawArray> for Cow<'a, RawArray> {
fn from(rdr: &'a RawArray) -> Self {
Cow::Borrowed(rdr)
}
}
impl<'a> IntoIterator for &'a RawArray {
type IntoIter = RawArrayIter<'a>;
type Item = RawResult<RawBsonRef<'a>>;
fn into_iter(self) -> RawArrayIter<'a> {
RawArrayIter {
inner: RawIter::new(&self.doc),
}
}
}
pub struct RawArrayIter<'a> {
inner: RawIter<'a>,
}
impl<'a> Iterator for RawArrayIter<'a> {
type Item = RawResult<RawBsonRef<'a>>;
fn next(&mut self) -> Option<RawResult<RawBsonRef<'a>>> {
match self.inner.next() {
Some(Ok(elem)) => match elem.value() {
Ok(value) => Some(Ok(value)),
Err(e) => Some(Err(e)),
},
Some(Err(e)) => Some(Err(e)),
None => None,
}
}
}
#[cfg(feature = "serde")]
impl<'de: 'a, 'a> serde::Deserialize<'de> for &'a RawArray {
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
use super::serde::OwnedOrBorrowedRawArray;
match OwnedOrBorrowedRawArray::deserialize(deserializer)? {
OwnedOrBorrowedRawArray::Borrowed(b) => Ok(b),
o => Err(serde::de::Error::custom(format!(
"expected borrowed raw array, instead got owned {:?}",
o
))),
}
}
}
#[cfg(feature = "serde")]
impl serde::Serialize for &RawArray {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
struct SeqSerializer<'a>(&'a RawArray);
impl serde::Serialize for SeqSerializer<'_> {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeSeq as _;
if serializer.is_human_readable() {
let mut seq = serializer.serialize_seq(None)?;
for v in self.0 {
let v = v.map_err(serde::ser::Error::custom)?;
seq.serialize_element(&v)?;
}
seq.end()
} else {
serializer.serialize_bytes(self.0.as_bytes())
}
}
}
serializer.serialize_newtype_struct(crate::raw::RAW_ARRAY_NEWTYPE, &SeqSerializer(self))
}
}