uuid-rs / uuid

Generate and parse UUIDs.

Home Page:https://www.crates.io/crates/uuid

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Backport Arbitrary support to 0.7.x and 0.6.x versions

greyblake opened this issue · comments

Motivation
We're using Diesel 1.x ,which depends on uuid 0.7.x. This forces our project to use uuid 0.7.x too.
We'd really love to use Arbitrary to simplify testing in the project, but uuid started supporting Arbitrary only in 1.0 (which we cannot use at the moment due to the Diesel).

Solution
Backport support of Arbitrary to 0.7.x and 0.8.x version of UUID.

Alternatives

  • Update to Diesel 2.x (which is not possible for us)
  • Wait until Arbitrary implements support for custom fields (rust-fuzz/arbitrary#33) - the issue stays there for a while already.
  • Wrap UUIDs into newtype and implement Arbitrary for the newtype - we probably gonna this way if the idea will be rejected.

Is it blocking?
I would not say that is blocking. Rather nice to have.

Anything else?

We're fine to contribute and open pull requests if the maintainer gives us a positive signal.

Thank you!

Sorry for never replying on this one @greyblake, but it looks like rust-fuzz/arbitrary#33 did get resolved, so I'll go ahead and close this one. If you do still find yourself needing to backport this support though I would be happy to accept a PR for it.

@KodrAus No worries, I know what it is to maintain an open source project.
Right, so I've added that ability to Arbitrary and luckily it was merged.

No we can workaround it with the following:

use uuid:uuid;
use arbitrary::Arbitrary;

#[derive(Arbitrary)]
struct User {
    #[arbitrary(with = arbitrary_uuid)]
    id: Uuid,
}

pub fn arbitrary_uuid(u: &mut Unstructured<'_>) -> arbitrary::Result<Uuid> {
    let bytes: [u8; 16] = u
        .bytes(16)?
        .try_into()
        .map_err(|_| arbitrary::Error::NotEnoughData)?;
    Uuid::from_bytes(&bytes).map_err(|_| arbitrary::Error::IncorrectFormat)
}

For the case if, let's say, the uuid is within a container (Option, Vec, HashMap, etc), one can use arbitrary_ext that helps to deal with that.

For example:

use uuid:uuid;
use arbitrary::Arbitrary;
use arbitrary_ext::{arbitrary_vec, arbitrary_option};

#[derive(Arbitrary)]
struct Group {
    #[arbitrary(with = arbitrary_option(arbitrary_uuid))]
    admin_id: Option<Uuid>,

    #[arbitrary(with = arbitrary_vec(arbitrary_uuid))]
    members_ids: Vec<Uuid>,
}

Of course, this can be helpful not only for old versions of UUID crate, but for other crates, which do not support arbitrary as well.