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

[Bug]: Uuid unable to deserialize from string #138

Open
2 tasks done
mdtusz opened this issue Aug 15, 2024 · 3 comments
Open
2 tasks done

[Bug]: Uuid unable to deserialize from string #138

mdtusz opened this issue Aug 15, 2024 · 3 comments
Labels
bug Something isn't working

Comments

@mdtusz
Copy link

mdtusz commented Aug 15, 2024

Is there an existing issue for this?

  • I have searched the existing issues

Code of Conduct

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

Current Behaviour

When trying to deserialize to a struct containing a Uuid from a string representation, deserializing fails.

#[derive(Serialize, Deserialize)]
struct Foo {
 id: Uuid
}

let id = Uuid:new_v4();
let c = cbor!({ "id" => id.to_string() }).unwrap();

let parsed: Foo = c.deserialized().unwrap();

assert_eq!(parsed.id, id);

This previously worked, but I am unable to track down when exactly the issue arose, where exactly the issue lives, or whether it is indeed an issue with ciborium, or an issue with serde or uuid - any guidance will be appreciated.

Expected Behaviour

I would expect for ciborium/serde to allow for parsing string UUID values into Uuid's, as they will often be written as strings by CBOR clients.

@mdtusz mdtusz added the bug Something isn't working label Aug 15, 2024
@hoxxep
Copy link
Contributor

hoxxep commented Nov 26, 2024

@mdtusz are you using the Uuid serde feature flag in cargo.toml?

#[derive(Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
struct Example {
    a: uuid::Uuid,
}

fn main() {
    let e = Example { a: "b018ff77-2011-477c-85ea-05f134744d27".parse().unwrap() };
    let serialized = serde_json::to_string(&e).unwrap();
    println!("{}", serialized);
    
    let deserialized = serde_json::from_str(&serialized).unwrap();
    assert_eq!(e, deserialized);
}

@mdtusz
Copy link
Author

mdtusz commented Nov 27, 2024

As far as I know, there's no feature flag for uuid in serde, but yes, I have the serde flag present for the uuid dependency.

[dependencies]
ciborium = "=0.2.2"
serde = { version = "1.0", features = ["derive"] }
uuid = { version = "1.5", features = ["serde", "v4"] }

This configuration causes the example I included above to fail, but downgrading to ciborium = "=0.2.1" will resolve the failures and allow for the string to be parsed. In your example, it works because you're serializing and deserializing to json (and the uuid is being converted to a string as the serialized form). Converting your example to use ciborium, it will work, but this is again due to using a UUID when constructing the serialized CBOR bytes - the UUID is serialized using tag 37 (Binary UUID), rather than as text. If you construct the CBOR with a string representation of the UUID, parsing it back into a UUID will fail.

I haven't been able to track down the source of this in ciborium yet, but this seems to be a bug as far as I'm able to tell since it was more permissive in the 0.2.1 release, and in general, parsing strings to UUID's is fairly common and "accepted".

@hoxxep
Copy link
Contributor

hoxxep commented Nov 28, 2024

I wasn't able to get this test to work on 0.2.1 either by the way, so I don't think it's a 0.2.1 to 0.2.2 change? Tested on both the ciborium v0.2.1 and v0.2.0 git tag commits.

#[test]
fn uuid() {
    let uuid = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();

    // encode to bytes
    let mut encoded = Vec::new();
    into_writer(&uuid, &mut encoded).unwrap();
    assert_eq!(encoded, hex::decode("50550e8400e29b41d4a716446655440000").unwrap());

    // decode from bytes
    let encoded = hex::decode("50550e8400e29b41d4a716446655440000").unwrap();
    let decoded: Uuid = from_reader(&encoded[..]).unwrap();
    assert_eq!(uuid, decoded);

    // decode from string
    let encoded = hex::decode("782435353065383430302D653239622D343164342D613731362D343436363535343430303030").unwrap();
    let decoded: Uuid = from_reader(&encoded[..]).unwrap();
    assert_eq!(uuid, decoded);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants