From ebdd3f5b02374f7839f60e426cbe29120be475c4 Mon Sep 17 00:00:00 2001 From: Lorenzo Delgado Date: Thu, 12 Dec 2024 23:10:07 +0100 Subject: [PATCH] feat: implement UUID v6, v7 and v8 fake value generation Signed-off-by: Lorenzo Delgado --- fake/Cargo.toml | 3 +- fake/src/impls/bson_oid/mod.rs | 2 +- fake/src/impls/ulid/mod.rs | 2 +- fake/src/impls/uuid/mod.rs | 90 ++++++++++++++++++++++++++++++---- fake/src/lib.rs | 42 +++++++++++++--- 5 files changed, 118 insertions(+), 21 deletions(-) diff --git a/fake/Cargo.toml b/fake/Cargo.toml index c21834a..7a83993 100644 --- a/fake/Cargo.toml +++ b/fake/Cargo.toml @@ -13,6 +13,7 @@ rust-version = "1.63" [package.metadata.docs.rs] all-features = true +rustdoc-args = ["--cfg", "docsrs"] [dependencies] dummy = { version = "0.9", path = "../dummy_derive", optional = true } @@ -28,7 +29,7 @@ http = { version = "1", optional = true } semver = { version = "1", optional = true } serde_json = { version = "1", optional = true } ulid = { version = "1", optional = true } -uuid = { version = "1", features = ["v1", "v3", "v4", "v5"], optional = true } +uuid = { version = "1", features = ["v1", "v3", "v4", "v5", "v6", "v7", "v8"], optional = true } time = { version = "0.3", features = ["formatting"], optional = true } num-traits = { version = "0.2", optional = true } rust_decimal = { version = "1", default-features = false, optional = true } diff --git a/fake/src/impls/bson_oid/mod.rs b/fake/src/impls/bson_oid/mod.rs index f7df036..ffc59d3 100644 --- a/fake/src/impls/bson_oid/mod.rs +++ b/fake/src/impls/bson_oid/mod.rs @@ -1,4 +1,4 @@ -//! bson_objectid +//! Fake _bson OID_ generation. use bson::oid::ObjectId; diff --git a/fake/src/impls/ulid/mod.rs b/fake/src/impls/ulid/mod.rs index a5d2e75..61397e2 100644 --- a/fake/src/impls/ulid/mod.rs +++ b/fake/src/impls/ulid/mod.rs @@ -1,4 +1,4 @@ -//! ulid +//! Fake _ulid_ generation. use ulid::Ulid; diff --git a/fake/src/impls/uuid/mod.rs b/fake/src/impls/uuid/mod.rs index e1edf09..aeb0ceb 100644 --- a/fake/src/impls/uuid/mod.rs +++ b/fake/src/impls/uuid/mod.rs @@ -1,27 +1,53 @@ -//! uuid +//! Fake _UUIDs_ generation. //! -//! please note that : -//! * all [`Dummy`] implementations for [`String`] use [to_hyphenated](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.to_hyphenated). -//! * [`Dummy`] implementation uses [from_u128](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.from_u128) +//! This module provides implementations for generating fake UUIDs (Universally Unique Identifiers) +//! using the [`uuid`] crate. +//! +//! Please note that: +//! * All [`Dummy`] implementations for [`String`] use [to_hyphenated](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.to_hyphenated). +//! * [`Dummy`] implementation uses [from_u128](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.from_u128). +//! +//! # Examples +//! +//! ```rust +//! use fake::{Fake, Faker}; +//! use fake::uuid::{UUIDv4, UUIDv7}; +//! # use uuid::Uuid; +//! +//! // Use the `Dummy` implementation +//! let uuid: Uuid = Faker.fake(); +//! +//! // Use the `Dummy` implementation to generate a UUID instance +//! let uuid: Uuid = UUIDv4.fake(); +//! +//! // Use the `Dummy` implementation to generate a UUID string +//! let uuid: String = UUIDv7.fake(); +//! ``` use uuid::{Builder, Uuid, Variant, Version}; use crate::{Dummy, Fake, Faker}; -/// as per [new_v1](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.new_v1) +/// As per [new_v1](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.new_v1) pub struct UUIDv1; -/// as per [new_v3](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.new_v3) +/// As per [new_v3](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.new_v3) pub struct UUIDv3; -/// as per [new_v4](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.new_v4) +/// As per [new_v4](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.new_v4) pub struct UUIDv4; -/// as per [new_v5](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.new_v5) +/// As per [new_v5](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.new_v5) pub struct UUIDv5; +/// As per [new_v6](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.new_v6) +pub struct UUIDv6; +/// As per [new_v7](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.new_v7) +pub struct UUIDv7; +/// As per [new_v8](https://docs.rs/uuid/latest/uuid/struct.Uuid.html#method.new_v8) +pub struct UUIDv8; impl Dummy for Uuid { fn dummy_with_rng(_: &UUIDv1, rng: &mut R) -> Self { let ticks = rng.gen_range(uuid::timestamp::UUID_TICKS_BETWEEN_EPOCHS..u64::MAX); let counter = Faker.fake_with_rng(rng); - let ts = uuid::timestamp::Timestamp::from_rfc4122(ticks, counter); + let ts = uuid::timestamp::Timestamp::from_gregorian(ticks, counter); let node_id: [u8; 6] = Faker.fake_with_rng(rng); Uuid::new_v1(ts, &node_id) } @@ -78,8 +104,52 @@ impl Dummy for String { } } +impl Dummy for Uuid { + fn dummy_with_rng(_: &UUIDv6, rng: &mut R) -> Self { + let ticks = rng.gen_range(uuid::timestamp::UUID_TICKS_BETWEEN_EPOCHS..u64::MAX); + let counter = Faker.fake_with_rng(rng); + let ts = uuid::timestamp::Timestamp::from_gregorian(ticks, counter); + let node_id: [u8; 6] = Faker.fake_with_rng(rng); + Uuid::new_v6(ts, &node_id) + } +} + +impl Dummy for String { + fn dummy_with_rng(config: &UUIDv6, rng: &mut R) -> Self { + Uuid::dummy_with_rng(config, rng).hyphenated().to_string() + } +} + +impl Dummy for Uuid { + fn dummy_with_rng(_: &UUIDv7, rng: &mut R) -> Self { + let ticks = rng.gen_range(uuid::timestamp::UUID_TICKS_BETWEEN_EPOCHS..u64::MAX); + let counter = Faker.fake_with_rng(rng); + let ts = uuid::timestamp::Timestamp::from_gregorian(ticks, counter); + Uuid::new_v7(ts) + } +} + +impl Dummy for String { + fn dummy_with_rng(config: &UUIDv7, rng: &mut R) -> Self { + Uuid::dummy_with_rng(config, rng).hyphenated().to_string() + } +} + +impl Dummy for Uuid { + fn dummy_with_rng(_: &UUIDv8, rng: &mut R) -> Self { + let buf: [u8; 16] = Faker.fake_with_rng(rng); + Uuid::new_v8(buf) + } +} + +impl Dummy for String { + fn dummy_with_rng(config: &UUIDv8, rng: &mut R) -> Self { + Uuid::dummy_with_rng(config, rng).hyphenated().to_string() + } +} + impl Dummy for Uuid { fn dummy_with_rng(_: &Faker, rng: &mut R) -> Self { - Self::from_u128(rng.gen()) + Uuid::from_u128(rng.gen()) } } diff --git a/fake/src/lib.rs b/fake/src/lib.rs index 9625d6d..a2ab781 100644 --- a/fake/src/lib.rs +++ b/fake/src/lib.rs @@ -2,11 +2,18 @@ //! //! # Feature flags //! -//! - `derive` provides `#[derive(Dummy)]` -//! - `chrono` [chrono](https://docs.rs/chrono) integration -//! - `http` [http](https://docs.rs/http) integration -//! - `ulid` [ulid](https://docs.rs/ulid) integration -//! - `uuid` [uuid](https://docs.rs/uuid) integration +//! - `derive`: Enable `#[derive(Dummy)]` macro +//! - `bigdecimal`: [bigdecimal](https://docs.rs/bigdecimal) integration +//! - `bson_oid`: [bson](https://docs.rs/bson) integration +//! - `chrono`: [chrono](https://docs.rs/chrono) integration +//! - `chrono-tz`: [chrono-tz](https://docs.rs/chrono-tz) integration +//! - `geo`: [geo-types](https://docs.rs/geo-types) integration +//! - `glam`: [glam](https://docs.rs/glam) integration +//! - `http`: [http](https://docs.rs/http) integration +//! - `rust-decimal`: [rust_decimal](https://docs.rs/rust_decimal) integration +//! - `time`: [time](https://docs.rs/time) integration +//! - `ulid`: [ulid](https://docs.rs/ulid) integration +//! - `uuid`: [uuid](https://docs.rs/uuid) integration //! //! # Usage //! @@ -32,7 +39,7 @@ //! println!("tuple {:?}", tuple); //! println!("String {:?}", Faker.fake::()); //! -//! // types U can used to generate fake value T, if `T: Dummy` +//! // types U can `be used to generate fake value T, if `T: Dummy` //! println!("String {:?}", (8..20).fake::()); //! println!("u32 {:?}", (8..20).fake::()); //! @@ -72,7 +79,7 @@ //! println!("value from fixed seed {}", v); //! } //! -//! # #[cfg(feture = "always-true-rng")] { +//! # #[cfg(feature = "always-true-rng")] { //! // Use an always true RNG so that optional types are always `Some` values. (Requires //! // always-true-rng feature). //! use fake::utils::AlwaysTrueRng; @@ -81,6 +88,10 @@ //! println!("Always Some: {}", result.unwrap()); //! # } //! ``` + +// Enable `doc_cfg` feature for `docs.rs` +#![cfg_attr(docsrs, feature(doc_cfg))] + #[doc(hidden)] pub use rand; #[doc(hidden)] @@ -139,7 +150,7 @@ pub struct Faker; /// /// # Derivable /// -/// The trait can be used with `#[derive]` if all of the type's fields +/// The trait can be used with `#[derive]` if all the type's fields /// implement [`Fake`]. See [`Dummy`][macro@Dummy] for more. pub trait Dummy: Sized { /// Generate a dummy value for a type. @@ -218,6 +229,7 @@ pub trait Fake: Sized { impl Fake for T {} #[cfg(feature = "geo")] +#[cfg_attr(docsrs, doc(cfg(feature = "geo")))] fn unique + PartialEq, R: Rng + ?Sized>(rng: &mut R, len: usize) -> Vec { let mut set = Vec::::new(); unique_append(&mut set, rng, len); @@ -225,6 +237,7 @@ fn unique + PartialEq, R: Rng + ?Sized>(rng: &mut R, len: usize) } #[cfg(feature = "geo")] +#[cfg_attr(docsrs, doc(cfg(feature = "geo")))] fn unique_append + PartialEq, R: Rng + ?Sized>( set: &mut Vec, rng: &mut R, @@ -252,30 +265,42 @@ pub use impls::std::result::ResultFaker; pub use impls::std::string::StringFaker; #[cfg(feature = "geo")] +#[cfg_attr(docsrs, doc(cfg(feature = "geo")))] pub use impls::geo; #[cfg(feature = "ulid")] +#[cfg_attr(docsrs, doc(cfg(feature = "ulid")))] pub use impls::ulid; #[cfg(feature = "uuid")] +#[cfg_attr(docsrs, doc(cfg(feature = "uuid")))] pub use impls::uuid; #[cfg(feature = "rust_decimal")] +#[cfg_attr(docsrs, doc(cfg(feature = "rust_decimal")))] pub use impls::decimal; #[cfg(any(feature = "bigdecimal", feature = "bigdecimal-rs"))] +#[cfg_attr( + docsrs, + doc(cfg(any(feature = "bigdecimal", feature = "bigdecimal-rs"))) +)] pub use impls::bigdecimal; #[cfg(feature = "serde_json")] +#[cfg_attr(docsrs, doc(cfg(feature = "serde_json")))] pub use impls::serde_json; #[cfg(feature = "time")] +#[cfg_attr(docsrs, doc(cfg(feature = "time")))] pub use impls::time; #[cfg(feature = "chrono")] +#[cfg_attr(docsrs, doc(cfg(feature = "chrono")))] pub use impls::chrono; #[cfg(feature = "bson_oid")] +#[cfg_attr(docsrs, doc(cfg(feature = "bson_oid")))] pub use impls::bson_oid; /// Fake value generation for specific formats. @@ -428,6 +453,7 @@ pub mod locales; /// let b: Bar = Faker.fake(); /// ``` #[cfg(feature = "derive")] +#[cfg_attr(docsrs, doc(cfg(feature = "derive")))] pub use dummy::Dummy; pub mod utils;