Skip to content

Commit

Permalink
Merge pull request #146 from saiintbrisson/master
Browse files Browse the repository at this point in the history
feat: add precision to time and chrono
  • Loading branch information
cksac authored Aug 31, 2023
2 parents 1036f7f + 494291a commit 6651a39
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 52 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Default:

```toml
[dependencies]
fake = { version = "2.8", features = ["derive"] }
fake = { version = "2.9", features = ["derive"] }
```

Available features:
Expand Down
3 changes: 2 additions & 1 deletion fake/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "fake"
version = "2.8.0"
version = "2.9.0"
authors = ["cksac <cs.cksac@gmail.com>"]
description = "An easy to use library for generating fake data like name, number, address, lorem, dates, etc."
keywords = ["faker", "data", "generator", "random"]
Expand All @@ -9,6 +9,7 @@ readme = "README.md"
repository = "https://github.com/cksac/fake-rs"
homepage = "https://github.com/cksac/fake-rs"
edition = "2021"
rust-version = "1.56"

[package.metadata.docs.rs]
all-features = true
Expand Down
2 changes: 1 addition & 1 deletion fake/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Default:

```toml
[dependencies]
fake = { version = "2.8", features = ["derive"] }
fake = { version = "2.9", features = ["derive"] }
```

Available features:
Expand Down
48 changes: 25 additions & 23 deletions fake/src/impls/bigdecimal/mod.rs
Original file line number Diff line number Diff line change
@@ -1,51 +1,53 @@
use crate::decimal::*;
use crate::{Dummy, Fake, Faker};
use bigdecimal_rs as bd;
use bigdecimal_rs::num_bigint::{BigInt, Sign};
use rand::Rng;
use rust_decimal;
use std::str::FromStr;

pub struct BigDecimal;
pub struct NegativeBigDecimal;
pub struct PositiveBigDecimal;
pub struct NoBigDecimalPoints;

impl Dummy<Faker> for bd::BigDecimal {
fn create_big_decimal<R: Rng + ?Sized>(rng: &mut R, sign: Sign) -> bigdecimal_rs::BigDecimal {
let parts: [u32; 4] = Faker.fake_with_rng(rng);
let int = BigInt::from_slice(sign, &parts);
let scale = (0..64).fake_with_rng(rng);

bigdecimal_rs::BigDecimal::new(int, scale)
}

impl Dummy<Faker> for bigdecimal_rs::BigDecimal {
fn dummy_with_rng<R: Rng + ?Sized>(_: &Faker, rng: &mut R) -> Self {
let decimal: rust_decimal::Decimal = Faker.fake_with_rng(rng);
let sign = if Faker.fake_with_rng(rng) {
Sign::Plus
} else {
Sign::Minus
};

bd::BigDecimal::from_str(&decimal.to_string()).unwrap()
create_big_decimal(rng, sign)
}
}

impl Dummy<BigDecimal> for bd::BigDecimal {
impl Dummy<BigDecimal> for bigdecimal_rs::BigDecimal {
fn dummy_with_rng<R: Rng + ?Sized>(_: &BigDecimal, rng: &mut R) -> Self {
let decimal: rust_decimal::Decimal = Decimal.fake_with_rng(rng);

bd::BigDecimal::from_str(&decimal.to_string()).unwrap()
Faker.fake_with_rng(rng)
}
}

impl Dummy<NegativeBigDecimal> for bd::BigDecimal {
impl Dummy<NegativeBigDecimal> for bigdecimal_rs::BigDecimal {
fn dummy_with_rng<R: Rng + ?Sized>(_: &NegativeBigDecimal, rng: &mut R) -> Self {
let decimal: rust_decimal::Decimal = NegativeDecimal.fake_with_rng(rng);

bd::BigDecimal::from_str(&decimal.to_string()).unwrap()
create_big_decimal(rng, Sign::Minus)
}
}

impl Dummy<PositiveBigDecimal> for bd::BigDecimal {
impl Dummy<PositiveBigDecimal> for bigdecimal_rs::BigDecimal {
fn dummy_with_rng<R: Rng + ?Sized>(_: &PositiveBigDecimal, rng: &mut R) -> Self {
let decimal: rust_decimal::Decimal = PositiveDecimal.fake_with_rng(rng);

bd::BigDecimal::from_str(&decimal.to_string()).unwrap()
create_big_decimal(rng, Sign::Plus)
}
}

impl Dummy<NoBigDecimalPoints> for bd::BigDecimal {
impl Dummy<NoBigDecimalPoints> for bigdecimal_rs::BigDecimal {
fn dummy_with_rng<R: Rng + ?Sized>(_: &NoBigDecimalPoints, rng: &mut R) -> Self {
let decimal: rust_decimal::Decimal = NoDecimalPoints.fake_with_rng(rng);

bd::BigDecimal::from_str(&decimal.to_string()).unwrap()
let decimal: bigdecimal_rs::BigDecimal = Faker.fake_with_rng(rng);
decimal.with_scale(0)
}
}
49 changes: 49 additions & 0 deletions fake/src/impls/chrono/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,52 @@ impl Dummy<Faker> for NaiveDateTime {
NaiveDateTime::new(date, time)
}
}

pub struct Precision<const N: usize>;

trait AllowedPrecision {
const SCALE: i64;

fn to_scale(nanos: i64) -> i64 {
if nanos != 0 {
nanos / Self::SCALE * Self::SCALE
} else {
nanos
}
}
}
macro_rules! allow_precision {
($($precision:expr),*) => {
$(impl AllowedPrecision for Precision<$precision> {
const SCALE: i64 = 10i64.pow(9 - $precision);
})*
};
}
allow_precision!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);

impl<const N: usize> Dummy<Precision<N>> for NaiveTime
where
Precision<N>: AllowedPrecision,
{
fn dummy_with_rng<R: Rng + ?Sized>(_: &Precision<N>, rng: &mut R) -> Self {
let hour = (0..24).fake_with_rng(rng);
let min = (0..60).fake_with_rng(rng);
let sec = (0..60).fake_with_rng(rng);
let nanos: i64 = (0..1_000_000_000).fake_with_rng(rng);
let nanos = Precision::<N>::to_scale(nanos) as u32;
NaiveTime::from_hms_nano_opt(hour, min, sec, nanos).expect("failed to create time")
}
}

impl<Tz, const N: usize> Dummy<Precision<N>> for DateTime<Tz>
where
Tz: TimeZone + Dummy<Faker>,
Precision<N>: AllowedPrecision,
{
fn dummy_with_rng<R: Rng + ?Sized>(_: &Precision<N>, rng: &mut R) -> Self {
let nanos: i64 = Faker.fake_with_rng(rng);
let utc: DateTime<Utc> = Utc.timestamp_nanos(Precision::<N>::to_scale(nanos));
let tz: Tz = Faker.fake_with_rng(rng);
utc.with_timezone(&tz)
}
}
6 changes: 3 additions & 3 deletions fake/src/impls/decimal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ impl Dummy<PositiveDecimal> for rust_decimal::Decimal {

impl Dummy<NoDecimalPoints> for rust_decimal::Decimal {
fn dummy_with_rng<R: Rng + ?Sized>(_: &NoDecimalPoints, rng: &mut R) -> Self {
Faker
.fake_with_rng::<rust_decimal::Decimal, R>(rng)
.round_dp(0)
let mut decimal: rust_decimal::Decimal = Faker.fake_with_rng(rng);
decimal.set_scale(0).expect("failed to set scale");
decimal
}
}
29 changes: 7 additions & 22 deletions fake/src/impls/std/array.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,11 @@
use crate::{Dummy, Fake};
use rand::Rng;

macro_rules! array_impl {
{$n:expr, $t:ident $($ts:ident)*} => {
impl<T, U> Dummy<U> for [T; $n] where T: Dummy<U> {
fn dummy_with_rng<R: Rng + ?Sized>(config: &U, rng: &mut R) -> Self {
[Fake::fake_with_rng::<$t, _>(config, rng), $(Fake::fake_with_rng::<$ts, _>(config, rng)),*]
}
}
array_impl!{($n - 1), $($ts)*}
};
{$n:expr,} => {
impl<T, U> Dummy<U> for [T; $n] where T: Dummy<U> {
fn dummy(_: &U) -> Self {
[]
}

fn dummy_with_rng<R: Rng + ?Sized>(_: &U, _rng: &mut R) -> Self {
[]
}
}
};
impl<T, U, const N: usize> Dummy<U> for [T; N]
where
T: Dummy<U>,
{
fn dummy_with_rng<R: Rng + ?Sized>(config: &U, rng: &mut R) -> Self {
std::array::from_fn(|_| Fake::fake_with_rng::<T, _>(config, rng))
}
}

array_impl! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
58 changes: 58 additions & 0 deletions fake/src/impls/time/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,61 @@ impl Dummy<Faker> for PrimitiveDateTime {
PrimitiveDateTime::new(date, time)
}
}

pub struct Precision<const N: usize>;

trait AllowedPrecision {
const SCALE: i128;

fn to_scale(nanos: i128) -> i128 {
if nanos != 0 {
nanos / Self::SCALE * Self::SCALE
} else {
nanos
}
}
}
macro_rules! allow_precision {
($($precision:expr),*) => {
$(impl AllowedPrecision for Precision<$precision> {
const SCALE: i128 = 10i128.pow(9 - $precision);
})*
};
}
allow_precision!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9);

impl<const N: usize> Dummy<Precision<N>> for Time
where
Precision<N>: AllowedPrecision,
{
fn dummy_with_rng<R: Rng + ?Sized>(_: &Precision<N>, rng: &mut R) -> Self {
let hour = (0..24).fake_with_rng(rng);
let min = (0..60).fake_with_rng(rng);
let sec = (0..60).fake_with_rng(rng);
let nanos: i128 = (0..1_000_000_000).fake_with_rng(rng);
let nanos = Precision::<N>::to_scale(nanos) as u32;
Time::from_hms_nano(hour, min, sec, nanos).expect("failed to create time")
}
}

impl<const N: usize> Dummy<Precision<N>> for PrimitiveDateTime
where
Precision<N>: AllowedPrecision,
{
fn dummy_with_rng<R: Rng + ?Sized>(_: &Precision<N>, rng: &mut R) -> Self {
let date = Faker.fake_with_rng(rng);
let time = Precision::<N>.fake_with_rng(rng);
PrimitiveDateTime::new(date, time)
}
}

impl<const N: usize> Dummy<Precision<N>> for OffsetDateTime
where
Precision<N>: AllowedPrecision,
{
fn dummy_with_rng<R: Rng + ?Sized>(_: &Precision<N>, rng: &mut R) -> Self {
let nanos = (MIN_NANOS..MAX_NANOS).fake_with_rng(rng);
let nanos = Precision::<N>::to_scale(nanos);
OffsetDateTime::from_unix_timestamp_nanos(nanos).unwrap()
}
}

0 comments on commit 6651a39

Please sign in to comment.