ciborium icon indicating copy to clipboard operation
ciborium copied to clipboard

[Bug]: v0.2.1 API is incompatible with v0.2.0 API

Open Pagten opened this issue 1 year ago • 6 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Code of Conduct

  • [X] I agree to follow this project's Code of Conduct

Current Behaviour

In v0.2.1 the signature of ciborium::de::from_reader() changed from

pub fn from_reader<'de, T: de::Deserialize<'de>, R: Read>(reader: R) -> Result<T, Error<R::Error>>

to

pub fn from_reader<T: de::DeserializeOwned, R: Read>(reader: R) -> Result<T, Error<R::Error>>

At first sight the new bound appears to be a looser bound than the original one, because in the serde crate we have

impl<T> DeserializeOwned for T where T: for<'de> Deserialize<'de> {}

so apparently anything that implements Deserialize also implements DeserializeOwned.

That is not a correct interpretation of the above blanket implementation, however, because it actually says that only types that implement Deserialize<'de> for any lifetime 'de also implement DeserializeOwned. Hence the signature change of ciborium::de::from_reader() is not a bound loosening and should therefore be considered a major change according to SemVer.

All this is to say that I think v0.2.1 should have actually gotten the version number 0.3.0.

Expected Behaviour

The signature change of ciborium::de::from_reader() is released under a new major version of the crate.

Environment Information

/

Steps To Reproduce

No response

Pagten avatar May 09 '23 12:05 Pagten

This bug impacts me and I stumbled upon this issue. In case it helps, here's a simple example to reproduce. This compiles on =0.2.0 but not on 0.2.1

use std::borrow::Cow;

fn main() {
    #[derive(serde::Deserialize, serde::Serialize, Debug, PartialEq)]
    pub struct MyMessage<'a> {
        #[serde(borrow)]
        pub value: Cow<'a, str>,
    }

    let string: String = "hello world!".to_string();

    let my_message = MyMessage {
        value: Cow::Borrowed(&string),
    };

    let mut cbor = Vec::new();
    ciborium::ser::into_writer(&my_message, &mut cbor).unwrap();

    let decoded = ciborium::de::from_reader(cbor.as_slice()).unwrap();
    assert_eq!(my_message, decoded);
}

error: implementation of `Deserialize` is not general enough
  --> src/main.rs:19:19
   |
19 |     let decoded = ciborium::de::from_reader(cbor.as_slice()).unwrap();
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Deserialize` is not general enough
   |
   = note: `MyMessage<'_>` must implement `Deserialize<'0>`, for any lifetime `'0`...
   = note: ...but `MyMessage<'_>` actually implements `Deserialize<'1>`, for some specific lifetime `'1`

thill avatar Nov 10 '23 19:11 thill

This seems to be an issue with how I did the release, I should have bumped the version to 0.3. How should this be corrected?

For context, this came from this PR: https://github.com/enarx/ciborium/pull/46 related to this issue https://github.com/enarx/ciborium/issues/45.

rjzak avatar Nov 12 '23 02:11 rjzak

Ah, I see. So Cow in my case was always copying instead of borrowing, which means it is owned anyways. In that case, yes, DeserializeOwned is appropriate to fix #45, but it probably should have been released as 0.3. That can't be undone, so maybe y'all should just consider some explicit documentation about this limitation.

Regardless of this issue and the #45 issue, I think it's important to call out the "no-borrowing" limitation of this crate early in the docs. Many other serde implementations do support zero-copy &str deserialization, including the old serde_cbor crate. Folks coming in expecting to be able to "just use cbor" in place of their existing serde-compatible format may have troubles if their codebase is already relying on a lot of borrow semantics to save time coping strings during deserialization workflows.

thill avatar Nov 12 '23 21:11 thill

I'm not asking anyone to do any work here, but would y'all consider a ciborium::de::from_slice PR in the future that addresses this limitation? Or is your intention to only ever support the current reader and writer semantics?

thill avatar Nov 12 '23 22:11 thill

PRs welcome! Would this be an additional function? We're happy to accept changes which make this crate more useful, we aren't set on doing things in a specific way, I don't think.

rjzak avatar Nov 13 '23 00:11 rjzak

Would this be an additional function?

I believe that that would be required given the current dependence on the Read trait in from_reader. More expressive borrowing is needed.

thill avatar Nov 13 '23 05:11 thill