Skip to content

RUST-1992 Make serde an optional feature #554

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

Merged
merged 24 commits into from
Jun 17, 2025

Conversation

abr-egn
Copy link
Contributor

@abr-egn abr-egn commented Jun 11, 2025

RUST-1992

This splits everything serde-related into feature-gated optional functionality, with a whole lot of downstream changes:

  • Functions got renamed to make it clear which of the encode/decode or serialize/deserialize family they were part of (things like to_vec existed in both and were way too easy to confuse otherwise)
  • Document::to_writer previously round-tripped through serde for ... reasons? ... and now just directly encodes (and I added a convenience encode_to_vec method because 99% of the time that's the writer target).
  • A lot of things that were calling bson::to_vec(doc) are now directly encoding
  • RawDocumentBuf::append and RawArrayBuf::push previously would panic if given a value that couldn't be encoded, which made for a slightly more convenient API but is also egregiously unrustacean, so they now return Result<()>.
  • The rawdoc! macro, which uses the above, still has the panic behavior because there's not really anything else it can do. Everywhere else downstream of those is properly fallible now.
  • Core functionality (constants, utility functions) to binary bson handling was moved out of serde modules.

Things under the umbrella of RUST-1992 to come in follow-up PRs:

  • user documentation for the distinction between "encode" (concrete bson type to bytestream) and "serialize" (arbitrary type, possibly containing bson, to arbitrary format)
  • serde_json might also be reasonable to be an optional dependency. I'm less certain of this, though, it'll need some exploration.
  • clean up and consolidation of the core binary-format bson bytestream handling functions, they're still a bit scattered

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The examples/ directory had some very basic and very stale examples that AFAICT weren't set up to be tested or linked to by anything, so I removed them in favor of relying on the main rustdoc.

@@ -56,6 +53,19 @@ impl RawArrayBuf {
}
}

#[allow(clippy::should_implement_trait)]
pub fn from_iter<B, I>(iter: I) -> crate::error::Result<Self>
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, there's no TryFromIterator trait (it's been proposed a couple of times over the years and discussions always end up in the weeds), so a constructor function is the best we can do.

Clippy gets grumpy that this is named the same as the FromIterator trait method but I think it's the discoverable thing to do, hence the allow.

pub fn from_document(doc: &Document) -> Result<Self> {
let mut out = RawDocumentBuf::new();
for (k, v) in doc {
let val: RawBson = v.clone().try_into()?;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In theory, RawDocumentBuf::from_document should be able to iterate over a borrowed Document and build the new RawDocumentBuf without any intermediate copies needed. Where this breaks down is that appending to a bson byte buffer is defined at its core in terms of RawBsonRefs, and there's no way to get one of those from a managed-type &Bson without allocating intermediate storage.

We could add logic to translate the managed &Bson type directly to bytes, but we've already got too many slightly-different versions of that logic already. If the clone() here turns out to be a profiling hotspot we can revisit.

Copy link
Contributor

Choose a reason for hiding this comment

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

We could add logic to translate the managed &Bson type directly to bytes

Is this something you think will land for 3.0? If not, the update to TryFrom<Document> for RawDocumentBuf got me thinking that maybe this method should take an owned Document - that way, we can avoid unnecessary clones for owned data, and it will be more clear for users with borrowed documents that their data is going to be cloned. As-is, it doesn't seem obvious that RawDocumentBuf::from_document(document) is less performant than RawDocumentBuf::from(document) for an owned document (which is also an argument against my earlier suggestion to make the input here impl Borrow<Document>).

Alternatively, we could remove this method entirely in favor of the TryFrom impls, but it does seem like a nice utility from a discoverability standpoint.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My preference would be to remove from_document entirely in favor of the TryFrom impls and have a big documentation stanza as part of the work for RUST-2228.

Copy link
Contributor

Choose a reason for hiding this comment

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

sounds good to me

@abr-egn abr-egn marked this pull request as ready for review June 12, 2025 15:28
@abr-egn abr-egn requested a review from a team as a code owner June 12, 2025 15:28
@abr-egn abr-egn requested a review from isabelatkinson June 12, 2025 15:28
type Error = crate::error::Error;

fn try_from(value: crate::Array) -> Result<Self, Self::Error> {
Self::try_from(&value)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: suggest iterating over value.into_iter() here to avoid cloning each element

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 call; also updated the similar impl for RawDocumentBuf.

@abr-egn abr-egn requested a review from isabelatkinson June 16, 2025 18:08
isabelatkinson
isabelatkinson previously approved these changes Jun 17, 2025
Copy link
Contributor

@isabelatkinson isabelatkinson left a comment

Choose a reason for hiding this comment

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

LGTM, I can re-approve if you want to do the from_document removal as part of this PR

@abr-egn
Copy link
Contributor Author

abr-egn commented Jun 17, 2025

LGTM, I can re-approve if you want to do the from_document removal as part of this PR

I think this PR's big enough so I'll leave that for later, but I did have to do a rebase :)

@abr-egn abr-egn requested a review from isabelatkinson June 17, 2025 19:27
@abr-egn abr-egn merged commit 1669bc0 into mongodb:main Jun 17, 2025
11 checks passed
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.

2 participants