Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

provide lazy iterator implementation #449

Merged
merged 17 commits into from
Jan 18, 2024
11 changes: 7 additions & 4 deletions src/raw/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use super::{
error::{ValueAccessError, ValueAccessErrorKind, ValueAccessResult},
serde::OwnedOrBorrowedRawArray,
Error,
Iter,
RawBinaryRef,
RawBsonRef,
RawDocument,
RawIter,
RawRegexRef,
Result,
};
Expand Down Expand Up @@ -260,22 +260,25 @@ impl<'a> IntoIterator for &'a RawArray {

fn into_iter(self) -> RawArrayIter<'a> {
RawArrayIter {
inner: self.doc.into_iter(),
inner: RawIter::new(&self.doc),
}
}
}

/// An iterator over borrowed raw BSON array values.
pub struct RawArrayIter<'a> {
inner: Iter<'a>,
inner: RawIter<'a>,
}

impl<'a> Iterator for RawArrayIter<'a> {
type Item = Result<RawBsonRef<'a>>;

fn next(&mut self) -> Option<Result<RawBsonRef<'a>>> {
match self.inner.next() {
Some(Ok((_, v))) => Some(Ok(v)),
Some(Ok(elem)) => match elem.value() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this just be Some(Ok(elem)) => Some(elem.value()) ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yup!

Ok(value) => Some(Ok(value)),
Err(e) => Some(Err(e)),
},
Some(Err(e)) => Some(Err(e)),
None => None,
}
Expand Down
28 changes: 23 additions & 5 deletions src/raw/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ use crate::{
use super::{
error::{ValueAccessError, ValueAccessErrorKind, ValueAccessResult},
i32_from_slice,
iter::Iter,
try_to_str,
Error,
Iter,
RawArray,
RawBinaryRef,
RawBsonRef,
RawDocumentBuf,
RawIter,
RawRegexRef,
Result,
};
Expand Down Expand Up @@ -170,10 +172,10 @@ impl RawDocument {
/// # Ok::<(), Error>(())
/// ```
pub fn get(&self, key: impl AsRef<str>) -> Result<Option<RawBsonRef<'_>>> {
for result in self.into_iter() {
let (k, v) = result?;
if key.as_ref() == k {
return Ok(Some(v));
for elem in RawIter::new(self) {
let elem = elem?;
if key.as_ref() == elem.key() {
return Ok(Some(elem.try_into()?));
}
}
Ok(None)
Expand Down Expand Up @@ -492,6 +494,22 @@ impl RawDocument {
pub fn is_empty(&self) -> bool {
self.as_bytes().len() == MIN_BSON_DOCUMENT_SIZE as usize
}

pub(crate) fn read_cstring_at(&self, start_at: usize) -> Result<&str> {
let buf = &self.as_bytes()[start_at..];

let mut splits = buf.splitn(2, |x| *x == 0);
let value = splits
.next()
.ok_or_else(|| Error::new_without_key(ErrorKind::new_malformed("no value")))?;
if splits.next().is_some() {
Ok(try_to_str(value)?)
} else {
Err(Error::new_without_key(ErrorKind::new_malformed(
"expected null terminator",
)))
}
}
}

impl<'de: 'a, 'a> Deserialize<'de> for &'a RawDocument {
Expand Down
25 changes: 23 additions & 2 deletions src/raw/document_buf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ use crate::{

use super::{
bson::RawBson,
iter::Iter,
serde::OwnedOrBorrowedRawDocument,
Error,
ErrorKind,
Iter,
RawBsonRef,
RawDocument,
RawIter,
Result,
};

Expand Down Expand Up @@ -147,7 +148,27 @@ impl RawDocumentBuf {
/// elements that might need to allocate, you must explicitly convert
/// them to owned types yourself.
pub fn iter(&self) -> Iter<'_> {
self.into_iter()
Iter::new(self)
}

/// Gets an iterator over the elements in the [`RawDocumentBuf`],
/// which yields `Result<RawElement<'_>>` values. These hold a
/// reference to the underlying document but do not explicitly
/// resolve the values.
///
/// This iterator, which underpins the implementation of the
/// default iterator, produces `RawElement` objects, which
/// hold a view onto the document but do not parse out or
/// construct values until the `.value()` or `.try_into()` methods
/// are called.
///
/// # Note:
///
/// There is no owning iterator for [`RawDocumentBuf`]. If you
/// need ownership over elements that might need to allocate, you
/// must explicitly convert them to owned types yourself.
pub fn iter_elements(&self) -> RawIter<'_> {
RawIter::new(self)
}

/// Return the contained data as a `Vec<u8>`
Expand Down
8 changes: 8 additions & 0 deletions src/raw/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ pub enum ErrorKind {
Utf8EncodingError(Utf8Error),
}

impl ErrorKind {
pub(crate) fn new_malformed(e: impl ToString) -> Self {
ErrorKind::MalformedValue {
message: e.to_string(),
}
}
}

impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let p = self
Expand Down
Loading