Skip to content

Commit 9294ee5

Browse files
authored
provide lazy iterator implementation (#449)
1 parent d044889 commit 9294ee5

File tree

6 files changed

+359
-249
lines changed

6 files changed

+359
-249
lines changed

src/raw/array.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ use super::{
66
error::{ValueAccessError, ValueAccessErrorKind, ValueAccessResult},
77
serde::OwnedOrBorrowedRawArray,
88
Error,
9-
Iter,
109
RawBinaryRef,
1110
RawBsonRef,
1211
RawDocument,
12+
RawIter,
1313
RawRegexRef,
1414
Result,
1515
};
@@ -260,22 +260,25 @@ impl<'a> IntoIterator for &'a RawArray {
260260

261261
fn into_iter(self) -> RawArrayIter<'a> {
262262
RawArrayIter {
263-
inner: self.doc.into_iter(),
263+
inner: RawIter::new(&self.doc),
264264
}
265265
}
266266
}
267267

268268
/// An iterator over borrowed raw BSON array values.
269269
pub struct RawArrayIter<'a> {
270-
inner: Iter<'a>,
270+
inner: RawIter<'a>,
271271
}
272272

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

276276
fn next(&mut self) -> Option<Result<RawBsonRef<'a>>> {
277277
match self.inner.next() {
278-
Some(Ok((_, v))) => Some(Ok(v)),
278+
Some(Ok(elem)) => match elem.value() {
279+
Ok(value) => Some(Ok(value)),
280+
Err(e) => Some(Err(e)),
281+
},
279282
Some(Err(e)) => Some(Err(e)),
280283
None => None,
281284
}

src/raw/document.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ use crate::{
1515
use super::{
1616
error::{ValueAccessError, ValueAccessErrorKind, ValueAccessResult},
1717
i32_from_slice,
18+
iter::Iter,
19+
try_to_str,
1820
Error,
19-
Iter,
2021
RawArray,
2122
RawBinaryRef,
2223
RawBsonRef,
2324
RawDocumentBuf,
25+
RawIter,
2426
RawRegexRef,
2527
Result,
2628
};
@@ -170,10 +172,10 @@ impl RawDocument {
170172
/// # Ok::<(), Error>(())
171173
/// ```
172174
pub fn get(&self, key: impl AsRef<str>) -> Result<Option<RawBsonRef<'_>>> {
173-
for result in self.into_iter() {
174-
let (k, v) = result?;
175-
if key.as_ref() == k {
176-
return Ok(Some(v));
175+
for elem in RawIter::new(self) {
176+
let elem = elem?;
177+
if key.as_ref() == elem.key() {
178+
return Ok(Some(elem.try_into()?));
177179
}
178180
}
179181
Ok(None)
@@ -492,6 +494,22 @@ impl RawDocument {
492494
pub fn is_empty(&self) -> bool {
493495
self.as_bytes().len() == MIN_BSON_DOCUMENT_SIZE as usize
494496
}
497+
498+
pub(crate) fn read_cstring_at(&self, start_at: usize) -> Result<&str> {
499+
let buf = &self.as_bytes()[start_at..];
500+
501+
let mut splits = buf.splitn(2, |x| *x == 0);
502+
let value = splits
503+
.next()
504+
.ok_or_else(|| Error::new_without_key(ErrorKind::new_malformed("no value")))?;
505+
if splits.next().is_some() {
506+
Ok(try_to_str(value)?)
507+
} else {
508+
Err(Error::new_without_key(ErrorKind::new_malformed(
509+
"expected null terminator",
510+
)))
511+
}
512+
}
495513
}
496514

497515
impl<'de: 'a, 'a> Deserialize<'de> for &'a RawDocument {

src/raw/document_buf.rs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,13 @@ use crate::{
1717

1818
use super::{
1919
bson::RawBson,
20+
iter::Iter,
2021
serde::OwnedOrBorrowedRawDocument,
2122
Error,
2223
ErrorKind,
23-
Iter,
2424
RawBsonRef,
2525
RawDocument,
26+
RawIter,
2627
Result,
2728
};
2829

@@ -147,7 +148,27 @@ impl RawDocumentBuf {
147148
/// elements that might need to allocate, you must explicitly convert
148149
/// them to owned types yourself.
149150
pub fn iter(&self) -> Iter<'_> {
150-
self.into_iter()
151+
Iter::new(self)
152+
}
153+
154+
/// Gets an iterator over the elements in the [`RawDocumentBuf`],
155+
/// which yields `Result<RawElement<'_>>` values. These hold a
156+
/// reference to the underlying document but do not explicitly
157+
/// resolve the values.
158+
///
159+
/// This iterator, which underpins the implementation of the
160+
/// default iterator, produces `RawElement` objects, which
161+
/// hold a view onto the document but do not parse out or
162+
/// construct values until the `.value()` or `.try_into()` methods
163+
/// are called.
164+
///
165+
/// # Note:
166+
///
167+
/// There is no owning iterator for [`RawDocumentBuf`]. If you
168+
/// need ownership over elements that might need to allocate, you
169+
/// must explicitly convert them to owned types yourself.
170+
pub fn iter_elements(&self) -> RawIter<'_> {
171+
RawIter::new(self)
151172
}
152173

153174
/// Return the contained data as a `Vec<u8>`

src/raw/error.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,14 @@ pub enum ErrorKind {
4848
Utf8EncodingError(Utf8Error),
4949
}
5050

51+
impl ErrorKind {
52+
pub(crate) fn new_malformed(e: impl ToString) -> Self {
53+
ErrorKind::MalformedValue {
54+
message: e.to_string(),
55+
}
56+
}
57+
}
58+
5159
impl std::fmt::Display for Error {
5260
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
5361
let p = self

0 commit comments

Comments
 (0)