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

deserialize Cow should be decoding into slices #224

Closed
RReverser opened this issue Jan 5, 2018 · 5 comments
Closed

deserialize Cow should be decoding into slices #224

RReverser opened this issue Jan 5, 2018 · 5 comments

Comments

@RReverser
Copy link

@RReverser RReverser commented Jan 5, 2018

Currently if I encode, for example, Cow<String>, and deserialize it back using deserialize (that is, passing a complete slice of bytes and not just a stream), I get a Cow::Owned back even though I own the entire buffer, and so could have a cheap allocation-free decoding into Cow::Borrowed.

Note that when decoding into explicit &str, this produces a reference as expected.

@dtolnay
Copy link
Collaborator

@dtolnay dtolnay commented Jan 5, 2018

#[serde(borrow)] gives you a borrowed Cow<str>. https://serde.rs/borrow.html

@RReverser
Copy link
Author

@RReverser RReverser commented Jan 5, 2018

Oh nice. Why isn't it a default for non-owned deserialization though?

@dtolnay
Copy link
Collaborator

@dtolnay dtolnay commented Jan 5, 2018

The deserialize impl is:

impl<'de, 'a, T: ?Sized> Deserialize<'de> for Cow<'a, T>

The borrow attribute effectively gives you:

impl<'de, T: ?Sized> Deserialize<'de> for Cow<'de, T>

In my experience the first one is usually what people want for the ways that Cow is commonly used. For example it lets you serialize and deserialize a struct containing Cow where the data is always borrowed on the way out and owned on the way in without needing to hold on to the serialized data.

The second one is relatively uncommonly used.

@RReverser
Copy link
Author

@RReverser RReverser commented Jan 6, 2018

It's just a bit surprising that we have two deserialization entry points, one that assumes holding onto the entire input (and so can decode &str, &[u8] etc.) and another that can't assume that as it operates on streams and so can produce only owned values. Yet both entry points produce owned values for Cow by default, even though its contents are subject to exactly same assumptions about having the actual data blob stored elsewhere.

Wouldn't it be possible / make sense to specialize Cow to parse references by default when entire data is available and only owned values otherwise, just like it does for "regular" data types?

If my struct consists of various fields some of which are pure references and some are Cows, it's already bound to the input data because of the former, and so could as well deserialize references in the latter case.

@ZoeyR
Copy link
Collaborator

@ZoeyR ZoeyR commented Mar 20, 2020

This issue would need to be raised with the serde repo itself since it controls how Cow is deserialized.

@ZoeyR ZoeyR closed this Mar 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants
You can’t perform that action at this time.