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

RUST-1045 Support appending to RawDocumentBuf #326

Merged

Conversation

patrickfreed
Copy link
Contributor

RUST-1045

This PR adds a RawDocumentBuf::append method which enables RawDocumentBufs to be created and mutated without having to go through Document.

To achieve this, a number of public API additions/changes were needed:

  • An OwnedRawBson type was added
    • This is essentially the same as Bson, except the cases that hold documents/arrays use RawDocumentBuf and RawArrayBuf (also new type)
    • A OwnedRawJavaScriptCodeWithScope was also added, since the existing JavaScriptCodeWithScope stored its scope as a Document
  • A RawDocumentBuf can now de deserialized from arbitrary maps
    • Ditto for RawArrayBuf and arbitrary sequences
  • RawDocumentBuf::new was renamed to RawDocumentBuf::from_bytes
    • This allowed RawDocumentBuf::new() to be added for constructing brand new documents
    • RawDocument::new was also renamed to be consistent with this
  • RawDocumentBuf and RawArrayBuf now implement FromIterator
  • RawBson and OwnedRawBson both implement a number of From traits

use serde::{Deserialize, Serialize};

#[test]
fn all_types_json() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this test was moved without modification from test.rs. The one after it is new though.

@@ -648,13 +648,20 @@ impl<'d, 'de> serde::de::Deserializer<'de> for DocumentKeyDeserializer<'d, 'de>
}
}

fn deserialize_newtype_struct<V>(self, _name: &'static str, visitor: V) -> Result<V::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.

This was needed to support deserializing the Cow wrappers used in deserialization now. It just forwards deserialization to the wrapped type.

}

/// A visitor used to deserialize types backed by raw BSON.
pub(crate) struct RawBsonVisitor;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was moved to src/raw/serde.rs and slightly modified so that it could be shared with OwnedRawBson.

/// assert_eq!(doc.to_document()?, expected);
/// # Ok::<(), Error>(())
/// ```
pub fn append(&mut self, key: impl Into<String>, value: impl Into<OwnedRawBson>) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since this only appends to the end, we can't call it insert (which would imply key lookup). I opted for something different than push though which seems to be coupled with stacks/lists rather than key-value stores. Let me know if these seems right.


/// A BSON value backed by owned raw BSON bytes.
#[derive(Debug, Clone, PartialEq)]
pub enum OwnedRawBson {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This type was needed to have something to append to documents. I originally tried using a RawBson<'a> for this, but it was clunky / awkward, and it would potentially make the rawdoc! macro impossible.

Regarding the name, I originally opted for RawBson being the owned one and RawBsonRef being the borrowed one, but I ended up going with OwnedRawBson and RawBson to match how we added the suffix to the owned variants of RawDocument and RawArray. I'm still not certain this is the correct naming scheme for RawBson though, would love to hear your all's thoughts on this.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think I'd prefer RawBson / RawBsonRef in this case, although I have a hard time explaining why. OwnedX seems more unusual than XRef as Rust type names go.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think I agree. I originally thought it would be confusing to have RawDocument typically be borrowed and RawBson be owned, but OwnedRawBson does seem odd enough to warrant the inconsistency. Also, RawDocument technically isn't a borrowed type anyways, though it's always accessed as a wide-pointer (&RawDocument).

Copy link
Contributor

Choose a reason for hiding this comment

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

agreed here, RawBson and RawBsonRef feel more intuitive to me

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to be RawBsonRef and RawBson. I also updated RawBinary<'a> et al to be RawBinaryRef<'a> and what not. OwnedRawJavaScriptCodeWithScope dropped the Owned prefix. I also renamed RawBsonRef::to_owned_raw_bson to just RawBsonRef::to_raw_bson.

}

/// Gets a [`RawBson`] value referencing this owned raw BSON value.
pub fn as_raw_bson(&self) -> RawBson<'_> {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Unfortunately, we can't implement Deref, AsRef, Borrow, or ToOwned between these two types, the first three because the trait requires a reference to be returned and the last one due to the blanket implementation for Clone types. See rust-lang/rust#44950 for more info.

}

/// A visitor used to deserialize types backed by raw BSON.
pub(crate) struct OwnedOrBorrowedRawBsonVisitor;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is essentially the same as the old RawBsonVisitor, but it now can handle owned stuff (e.g. visit_string, visit_byte_buf) and arbitrary maps and sequences.

@patrickfreed patrickfreed marked this pull request as ready for review November 19, 2021 17:08
/// bytes. This type can be used to construct owned array values, which can be used to append to
/// [`RawDocumentBuf`] or as a field in a `Deserialize` struct.
///
/// Iterating over a [`RawArrayBuf`] yields either an error or a key-value pair that borrows from
Copy link
Contributor

Choose a reason for hiding this comment

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

key-value pair?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed


/// A BSON value backed by owned raw BSON bytes.
#[derive(Debug, Clone, PartialEq)]
pub enum OwnedRawBson {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think I'd prefer RawBson / RawBsonRef in this case, although I have a hard time explaining why. OwnedX seems more unusual than XRef as Rust type names go.


/// Gets a reference to the [`RawArrayBuf`] that's wrapped or returns `None` if the wrapped
/// value isn't a BSON array.
pub fn as_array(&self) -> Option<&'_ RawArray> {
Copy link
Contributor

Choose a reason for hiding this comment

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

Since there are now mutating methods for those, I think it'd be good to have as_array_mut -> Option<&mut RawArrayBuf> and similar for as_document_mut.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good idea, added

Copy link
Contributor

@abr-egn abr-egn left a comment

Choose a reason for hiding this comment

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

LGTM modulo naming questions.

@patrickfreed patrickfreed merged commit 17dc632 into mongodb:master Nov 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants