(minor) updated versions, normalized api around ranges
Some checks failed
/ Build and Test Library Snapshot (pull_request) Failing after 1m56s
Some checks failed
/ Build and Test Library Snapshot (pull_request) Failing after 1m56s
This commit is contained in:
parent
56bc62c333
commit
01a5207d50
12 changed files with 208 additions and 221 deletions
|
|
@ -62,16 +62,16 @@ those generators for `User`:
|
|||
|
||||
```scala
|
||||
import gs.datagen.v0._
|
||||
import gs.datagen.v0.generators.MinMax
|
||||
import gs.datagen.v0.generators.Size
|
||||
|
||||
val nameGen: Gen[Name] =
|
||||
Gen.string.alpha(4, 16).map(Name(_))
|
||||
|
||||
val dateOfBirthGen: Gen[LocalDate] =
|
||||
Gen.date.beforeToday(
|
||||
days = MinMax.Zero,
|
||||
months = MinMax.nonNegative(0, 11),
|
||||
years = MinMax.nonNegative(18, 80)
|
||||
days = Size.Zero,
|
||||
months = Size.between(0, 11),
|
||||
years = Size.between(18, 80)
|
||||
).map(DateOfBirth(_))
|
||||
|
||||
val karmaGen: Gen[Karma] =
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
val scala3: String = "3.7.2"
|
||||
val scala3: String = "3.7.4"
|
||||
|
||||
ThisBuild / scalaVersion := scala3
|
||||
ThisBuild / versionScheme := Some("semver-spec")
|
||||
|
|
@ -22,7 +22,7 @@ val sharedSettings = Seq(
|
|||
|
||||
lazy val testSettings = Seq(
|
||||
libraryDependencies ++= Seq(
|
||||
"org.scalameta" %% "munit" % "1.1.0" % Test
|
||||
"org.scalameta" %% "munit" % "1.2.1" % Test
|
||||
)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@ import gs.datagen.v0.generators.GenOption
|
|||
import gs.datagen.v0.generators.GenSet
|
||||
import gs.datagen.v0.generators.GenString
|
||||
import gs.datagen.v0.generators.GenUUID
|
||||
import gs.datagen.v0.generators.MinMax
|
||||
import gs.datagen.v0.generators.Size
|
||||
import gs.datagen.v0.generators.Range
|
||||
import gs.uuid.v0.UUID
|
||||
import java.time.Clock
|
||||
import java.time.Instant
|
||||
|
|
@ -154,7 +153,7 @@ object Gen:
|
|||
* The generator for the list elements.
|
||||
*/
|
||||
def list[A](
|
||||
size: Size,
|
||||
size: Range,
|
||||
gen: Gen[A]
|
||||
): Gen[List[A]] = new GenList[A](size, gen)
|
||||
|
||||
|
|
@ -169,7 +168,7 @@ object Gen:
|
|||
def list[A](
|
||||
fixedSize: Int,
|
||||
gen: Gen[A]
|
||||
): Gen[List[A]] = new GenList[A](Size.Fixed(fixedSize), gen)
|
||||
): Gen[List[A]] = new GenList[A](Range.Fixed(fixedSize), gen)
|
||||
|
||||
/** Generator for a list of some size based on a generator for the list
|
||||
* elements.
|
||||
|
|
@ -185,7 +184,7 @@ object Gen:
|
|||
minSize: Int,
|
||||
maxSize: Int,
|
||||
gen: Gen[A]
|
||||
): Gen[List[A]] = new GenList[A](Size.Between(minSize, maxSize), gen)
|
||||
): Gen[List[A]] = new GenList[A](Range.Between(minSize, maxSize), gen)
|
||||
|
||||
/** Generator for a set of some [[gs.datagen.v0.generators.Size]] based on a
|
||||
* generator for the set elements.
|
||||
|
|
@ -197,7 +196,7 @@ object Gen:
|
|||
* The generator for the list elements.
|
||||
*/
|
||||
def set[A](
|
||||
size: Size,
|
||||
size: Range,
|
||||
gen: Gen[A]
|
||||
): Gen[Set[A]] = new GenSet[A](size, gen)
|
||||
|
||||
|
|
@ -213,7 +212,7 @@ object Gen:
|
|||
def set[A](
|
||||
fixedSize: Int,
|
||||
gen: Gen[A]
|
||||
): Gen[Set[A]] = new GenSet[A](Size.Fixed(fixedSize), gen)
|
||||
): Gen[Set[A]] = new GenSet[A](Range.Fixed(fixedSize), gen)
|
||||
|
||||
/** Generator for a set of some size based on a generator for the set
|
||||
* elements.
|
||||
|
|
@ -229,7 +228,7 @@ object Gen:
|
|||
minSize: Int,
|
||||
maxSize: Int,
|
||||
gen: Gen[A]
|
||||
): Gen[Set[A]] = new GenSet[A](Size.Between(minSize, maxSize), gen)
|
||||
): Gen[Set[A]] = new GenSet[A](Range.Between(minSize, maxSize), gen)
|
||||
|
||||
/** Generators which pick a single random element from a collection.
|
||||
*/
|
||||
|
|
@ -300,7 +299,7 @@ object Gen:
|
|||
* The generator for values.
|
||||
*/
|
||||
def forKeysAndValues[K, V](
|
||||
size: Size,
|
||||
size: Range,
|
||||
keyGen: Gen[K],
|
||||
valueGen: Gen[V]
|
||||
): Gen[Map[K, V]] =
|
||||
|
|
@ -319,7 +318,7 @@ object Gen:
|
|||
* The generator for key/value pairs.
|
||||
*/
|
||||
def forTuples[K, V](
|
||||
size: Size,
|
||||
size: Range,
|
||||
keyValueGen: Gen[(K, V)]
|
||||
): Gen[Map[K, V]] =
|
||||
new GenMap.CoupledKeyValue[K, V](
|
||||
|
|
@ -343,7 +342,7 @@ object Gen:
|
|||
* The alphabet from which characters are selected.
|
||||
*/
|
||||
def alphabet(
|
||||
size: Size,
|
||||
size: Range,
|
||||
alphabet: Alphabet
|
||||
): Gen[String] =
|
||||
new GenString(
|
||||
|
|
@ -359,7 +358,7 @@ object Gen:
|
|||
* The size constraints for the generated string.
|
||||
*/
|
||||
def lowercaseAlpha(
|
||||
size: Size
|
||||
size: Range
|
||||
): Gen[String] =
|
||||
new GenString(
|
||||
alphabet = Alphabet.ASCII.LowerCaseAlpha,
|
||||
|
|
@ -374,7 +373,7 @@ object Gen:
|
|||
* The size constraints for the generated string.
|
||||
*/
|
||||
def uppercaseAlpha(
|
||||
size: Size
|
||||
size: Range
|
||||
): Gen[String] =
|
||||
new GenString(
|
||||
alphabet = Alphabet.ASCII.UpperCaseAlpha,
|
||||
|
|
@ -389,7 +388,7 @@ object Gen:
|
|||
* The size constraints for the generated string.
|
||||
*/
|
||||
def alpha(
|
||||
size: Size
|
||||
size: Range
|
||||
): Gen[String] =
|
||||
new GenString(
|
||||
alphabet = Alphabet.ASCII.Alpha,
|
||||
|
|
@ -404,7 +403,7 @@ object Gen:
|
|||
* The size constraints for the generated string.
|
||||
*/
|
||||
def alphaNumeric(
|
||||
size: Size
|
||||
size: Range
|
||||
): Gen[String] =
|
||||
new GenString(
|
||||
alphabet = Alphabet.ASCII.AlphaNumeric,
|
||||
|
|
@ -419,7 +418,7 @@ object Gen:
|
|||
* The size constraints for the generated string.
|
||||
*/
|
||||
def lowercaseAlphaNumeric(
|
||||
size: Size
|
||||
size: Range
|
||||
): Gen[String] =
|
||||
new GenString(
|
||||
alphabet = Alphabet.ASCII.LowerCaseAlphaNumeric,
|
||||
|
|
@ -434,7 +433,7 @@ object Gen:
|
|||
* The size constraints for the generated string.
|
||||
*/
|
||||
def uppercaseAlphaNumeric(
|
||||
size: Size
|
||||
size: Range
|
||||
): Gen[String] =
|
||||
new GenString(
|
||||
alphabet = Alphabet.ASCII.UpperCaseAlphaNumeric,
|
||||
|
|
@ -532,9 +531,9 @@ object Gen:
|
|||
* {{{
|
||||
* Gen.date.before(
|
||||
* date = LocalDate.now(),
|
||||
* days = MinMax.nonNegative(0, 10),
|
||||
* months = MinMax.nonNegative(1, 11),
|
||||
* years = MinMax.nonNegative(0, 30)
|
||||
* days = Size.between(0, 10),
|
||||
* months = Size.between(1, 11),
|
||||
* years = Size.between(0, 30)
|
||||
* )
|
||||
* }}}
|
||||
*
|
||||
|
|
@ -549,9 +548,9 @@ object Gen:
|
|||
*/
|
||||
def before(
|
||||
date: LocalDate,
|
||||
days: MinMax.NonNegative,
|
||||
months: MinMax.NonNegative = MinMax.Zero,
|
||||
years: MinMax.NonNegative = MinMax.Zero
|
||||
days: Range,
|
||||
months: Range = Range.Zero,
|
||||
years: Range = Range.Zero
|
||||
): Gen[LocalDate] =
|
||||
new GenLocalDate.Before(
|
||||
pivot = date,
|
||||
|
|
@ -576,9 +575,9 @@ object Gen:
|
|||
*
|
||||
* {{{
|
||||
* Gen.date.beforeToday(
|
||||
* days = MinMax.nonNegative(0, 10),
|
||||
* months = MinMax.nonNegative(1, 11),
|
||||
* years = MinMax.nonNegative(0, 30)
|
||||
* days = Size.between(0, 10),
|
||||
* months = Size.between(1, 11),
|
||||
* years = Size.between(0, 30)
|
||||
* )
|
||||
* }}}
|
||||
*
|
||||
|
|
@ -592,9 +591,9 @@ object Gen:
|
|||
* The range of years prior to today.
|
||||
*/
|
||||
def beforeToday(
|
||||
days: MinMax.NonNegative,
|
||||
months: MinMax.NonNegative = MinMax.Zero,
|
||||
years: MinMax.NonNegative = MinMax.Zero,
|
||||
days: Range,
|
||||
months: Range = Range.Zero,
|
||||
years: Range = Range.Zero,
|
||||
clock: Clock = DefaultClock
|
||||
): Gen[LocalDate] =
|
||||
new GenLocalDate.Before(
|
||||
|
|
@ -621,9 +620,9 @@ object Gen:
|
|||
* {{{
|
||||
* Gen.date.after(
|
||||
* date = LocalDate.now(),
|
||||
* days = MinMax.nonNegative(0, 10),
|
||||
* months = MinMax.nonNegative(1, 11),
|
||||
* years = MinMax.nonNegative(0, 30)
|
||||
* days = Size.between(0, 10),
|
||||
* months = Size.between(1, 11),
|
||||
* years = Size.between(0, 30)
|
||||
* )
|
||||
* }}}
|
||||
*
|
||||
|
|
@ -638,9 +637,9 @@ object Gen:
|
|||
*/
|
||||
def after(
|
||||
date: LocalDate,
|
||||
days: MinMax.NonNegative,
|
||||
months: MinMax.NonNegative = MinMax.Zero,
|
||||
years: MinMax.NonNegative = MinMax.Zero
|
||||
days: Range,
|
||||
months: Range = Range.Zero,
|
||||
years: Range = Range.Zero
|
||||
): Gen[LocalDate] =
|
||||
new GenLocalDate.After(
|
||||
pivot = date,
|
||||
|
|
@ -666,9 +665,9 @@ object Gen:
|
|||
*
|
||||
* {{{
|
||||
* Gen.date.afterToday(
|
||||
* days = MinMax.nonNegative(0, 10),
|
||||
* months = MinMax.nonNegative(1, 11),
|
||||
* years = MinMax.nonNegative(0, 30)
|
||||
* days = Size.between(0, 10),
|
||||
* months = Size.between(1, 11),
|
||||
* years = Size.between(0, 30)
|
||||
* )
|
||||
* }}}
|
||||
*
|
||||
|
|
@ -682,9 +681,9 @@ object Gen:
|
|||
* The range of years after today.
|
||||
*/
|
||||
def afterToday(
|
||||
days: MinMax.NonNegative,
|
||||
months: MinMax.NonNegative = MinMax.Zero,
|
||||
years: MinMax.NonNegative = MinMax.Zero,
|
||||
days: Range,
|
||||
months: Range = Range.Zero,
|
||||
years: Range = Range.Zero,
|
||||
clock: Clock = DefaultClock
|
||||
): Gen[LocalDate] =
|
||||
new GenLocalDate.After(
|
||||
|
|
@ -711,9 +710,9 @@ object Gen:
|
|||
* {{{
|
||||
* Gen.date.around(
|
||||
* date = LocalDate.now(),
|
||||
* days = MinMax.nonNegative(0, 10),
|
||||
* months = MinMax.nonNegative(1, 11),
|
||||
* years = MinMax.nonNegative(0, 30)
|
||||
* days = Size.between(0, 10),
|
||||
* months = Size.between(1, 11),
|
||||
* years = Size.between(0, 30)
|
||||
* )
|
||||
* }}}
|
||||
*
|
||||
|
|
@ -728,9 +727,9 @@ object Gen:
|
|||
*/
|
||||
def around(
|
||||
date: LocalDate,
|
||||
days: MinMax,
|
||||
months: MinMax = MinMax.Zero,
|
||||
years: MinMax = MinMax.Zero
|
||||
days: Range,
|
||||
months: Range = Range.Zero,
|
||||
years: Range = Range.Zero
|
||||
): Gen[LocalDate] =
|
||||
new GenLocalDate.Around(
|
||||
pivot = date,
|
||||
|
|
@ -755,9 +754,9 @@ object Gen:
|
|||
*
|
||||
* {{{
|
||||
* Gen.date.around(
|
||||
* days = MinMax.nonNegative(0, 10),
|
||||
* months = MinMax.nonNegative(1, 11),
|
||||
* years = MinMax.nonNegative(0, 30)
|
||||
* days = Size.between(0, 10),
|
||||
* months = Size.between(1, 11),
|
||||
* years = Size.between(0, 30)
|
||||
* )
|
||||
* }}}
|
||||
*
|
||||
|
|
@ -771,9 +770,9 @@ object Gen:
|
|||
* The range of years before or after today.
|
||||
*/
|
||||
def aroundToday(
|
||||
days: MinMax,
|
||||
months: MinMax = MinMax.Zero,
|
||||
years: MinMax = MinMax.Zero,
|
||||
days: Range,
|
||||
months: Range = Range.Zero,
|
||||
years: Range = Range.Zero,
|
||||
clock: Clock = DefaultClock
|
||||
): Gen[LocalDate] =
|
||||
new GenLocalDate.Around(
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ package gs.datagen.v0.generators
|
|||
import gs.datagen.v0.Gen
|
||||
|
||||
final class GenList[A](
|
||||
val size: Size,
|
||||
val range: Range,
|
||||
val generator: Gen[A]
|
||||
) extends Gen[List[A]]:
|
||||
|
||||
override def generate(input: Any): List[A] =
|
||||
List.fill(size.next(Gen.rng()))(generator.generate(()))
|
||||
List.fill(range.next(Gen.rng()))(generator.generate(()))
|
||||
|
|
|
|||
|
|
@ -26,9 +26,9 @@ object GenLocalDate:
|
|||
*/
|
||||
final class Before(
|
||||
val pivot: LocalDate,
|
||||
val days: MinMax,
|
||||
val months: MinMax,
|
||||
val years: MinMax
|
||||
val days: Range,
|
||||
val months: Range,
|
||||
val years: Range
|
||||
) extends GenLocalDate:
|
||||
|
||||
/** @inheritDocs
|
||||
|
|
@ -36,9 +36,9 @@ object GenLocalDate:
|
|||
override def generate(input: Any): LocalDate =
|
||||
val rng = Gen.rng()
|
||||
pivot
|
||||
.minusDays(days.select(rng).toInt)
|
||||
.minusMonths(months.select(rng).toInt)
|
||||
.minusYears(years.select(rng).toInt)
|
||||
.minusDays(days.next(rng).toInt)
|
||||
.minusMonths(months.next(rng).toInt)
|
||||
.minusYears(years.next(rng).toInt)
|
||||
|
||||
/** Implementation of [[GenLocalDate]] that selects random dates after some
|
||||
* given date.
|
||||
|
|
@ -54,9 +54,9 @@ object GenLocalDate:
|
|||
*/
|
||||
final class After(
|
||||
val pivot: LocalDate,
|
||||
val days: MinMax,
|
||||
val months: MinMax,
|
||||
val years: MinMax
|
||||
val days: Range,
|
||||
val months: Range,
|
||||
val years: Range
|
||||
) extends GenLocalDate:
|
||||
|
||||
/** @inheritDocs
|
||||
|
|
@ -64,9 +64,9 @@ object GenLocalDate:
|
|||
override def generate(input: Any): LocalDate =
|
||||
val rng = Gen.rng()
|
||||
pivot
|
||||
.plusDays(days.select(rng).toInt)
|
||||
.plusMonths(months.select(rng).toInt)
|
||||
.plusYears(years.select(rng).toInt)
|
||||
.plusDays(days.next(rng).toInt)
|
||||
.plusMonths(months.next(rng).toInt)
|
||||
.plusYears(years.next(rng).toInt)
|
||||
|
||||
/** Implementation of [[GenLocalDate]] that selects random dates centered on
|
||||
* some given date.
|
||||
|
|
@ -82,9 +82,9 @@ object GenLocalDate:
|
|||
*/
|
||||
final class Around(
|
||||
val pivot: LocalDate,
|
||||
val days: MinMax,
|
||||
val months: MinMax,
|
||||
val years: MinMax
|
||||
val days: Range,
|
||||
val months: Range,
|
||||
val years: Range
|
||||
) extends GenLocalDate:
|
||||
|
||||
/** @inheritDocs
|
||||
|
|
@ -109,10 +109,10 @@ object GenLocalDate:
|
|||
*/
|
||||
def plusOrMinusDays(
|
||||
rng: Random,
|
||||
range: MinMax
|
||||
range: Range
|
||||
): LocalDate =
|
||||
if rng.nextBoolean() then base.plusDays(range.select(rng).toInt)
|
||||
else base.minusDays(range.select(rng).toInt)
|
||||
if rng.nextBoolean() then base.plusDays(range.next(rng).toInt)
|
||||
else base.minusDays(range.next(rng).toInt)
|
||||
|
||||
/** Select a bounded random number of months before or after the base date.
|
||||
*
|
||||
|
|
@ -125,10 +125,10 @@ object GenLocalDate:
|
|||
*/
|
||||
def plusOrMinusMonths(
|
||||
rng: Random,
|
||||
range: MinMax
|
||||
range: Range
|
||||
): LocalDate =
|
||||
if rng.nextBoolean() then base.plusMonths(range.select(rng).toInt)
|
||||
else base.minusMonths(range.select(rng).toInt)
|
||||
if rng.nextBoolean() then base.plusMonths(range.next(rng).toInt)
|
||||
else base.minusMonths(range.next(rng).toInt)
|
||||
|
||||
/** Select a bounded random number of years before or after the base date.
|
||||
*
|
||||
|
|
@ -141,9 +141,9 @@ object GenLocalDate:
|
|||
*/
|
||||
def plusOrMinusYears(
|
||||
rng: Random,
|
||||
range: MinMax
|
||||
range: Range
|
||||
): LocalDate =
|
||||
if rng.nextBoolean() then base.plusYears(range.select(rng).toInt)
|
||||
else base.minusYears(range.select(rng).toInt)
|
||||
if rng.nextBoolean() then base.plusYears(range.next(rng).toInt)
|
||||
else base.minusYears(range.next(rng).toInt)
|
||||
|
||||
end GenLocalDate
|
||||
|
|
|
|||
|
|
@ -7,23 +7,23 @@ abstract class GenMap[K, V] extends Gen[Map[K, V]]
|
|||
object GenMap:
|
||||
|
||||
final class IndependentKeyValue[K, V](
|
||||
val size: Size,
|
||||
val range: Range,
|
||||
val keyGen: Gen[K],
|
||||
val valueGen: Gen[V]
|
||||
) extends Gen[Map[K, V]]:
|
||||
|
||||
override def generate(input: Any): Map[K, V] =
|
||||
List.fill(size.next(Gen.rng()))(generateTuple()).toMap
|
||||
List.fill(range.next(Gen.rng()))(generateTuple()).toMap
|
||||
|
||||
private def generateTuple(): (K, V) =
|
||||
keyGen.generate(()) -> valueGen.generate(())
|
||||
|
||||
final class CoupledKeyValue[K, V](
|
||||
val size: Size,
|
||||
val range: Range,
|
||||
val keyValueGen: Gen[(K, V)]
|
||||
) extends Gen[Map[K, V]]:
|
||||
|
||||
override def generate(input: Any): Map[K, V] =
|
||||
List.fill(size.next(Gen.rng()))(keyValueGen.generate(())).toMap
|
||||
List.fill(range.next(Gen.rng()))(keyValueGen.generate(())).toMap
|
||||
|
||||
end GenMap
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ package gs.datagen.v0.generators
|
|||
import gs.datagen.v0.Gen
|
||||
|
||||
final class GenSet[A](
|
||||
val size: Size,
|
||||
val range: Range,
|
||||
val generator: Gen[A]
|
||||
) extends Gen[Set[A]]:
|
||||
|
||||
override def generate(input: Any): Set[A] =
|
||||
Set.fill(size.next(Gen.rng()))(generator.generate(()))
|
||||
Set.fill(range.next(Gen.rng()))(generator.generate(()))
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import gs.datagen.v0.Gen
|
|||
|
||||
final class GenString(
|
||||
val alphabet: Alphabet,
|
||||
val size: Size
|
||||
val size: Range
|
||||
) extends Gen[String]:
|
||||
|
||||
override def generate(input: Any): String =
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
package gs.datagen.v0.generators
|
||||
|
||||
import java.util.Random
|
||||
|
||||
sealed trait MinMax:
|
||||
def min: Int
|
||||
def max: Int
|
||||
|
||||
def select(random: Random): Int =
|
||||
if min == 0 && max == 0 then 0
|
||||
else random.nextInt(min, max)
|
||||
|
||||
object MinMax:
|
||||
|
||||
val Zero: MinMax.NonNegative = NonNegative(0, 0)
|
||||
|
||||
def apply(
|
||||
min: Int,
|
||||
max: Int
|
||||
): MinMax = Generic(min, max)
|
||||
|
||||
def nonNegative(
|
||||
min: Int,
|
||||
max: Int
|
||||
): MinMax.NonNegative =
|
||||
NonNegative(min, max)
|
||||
|
||||
final class Generic private (
|
||||
val min: Int,
|
||||
val max: Int
|
||||
) extends MinMax
|
||||
|
||||
object Generic:
|
||||
|
||||
def apply(
|
||||
min: Int,
|
||||
max: Int
|
||||
): Generic =
|
||||
if min <= max then new Generic(min, max)
|
||||
else new Generic(max, min)
|
||||
|
||||
end Generic
|
||||
|
||||
final class NonNegative private (
|
||||
val min: Int,
|
||||
val max: Int
|
||||
) extends MinMax
|
||||
|
||||
object NonNegative:
|
||||
|
||||
def apply(
|
||||
min: Int,
|
||||
max: Int
|
||||
): NonNegative =
|
||||
if min < 0 || max < 0 then
|
||||
throw new IllegalArgumentException(
|
||||
"Only values >= 0 are allowed in this min/max pair."
|
||||
)
|
||||
else if min <= max then new NonNegative(min, max)
|
||||
else new NonNegative(max, min)
|
||||
|
||||
end NonNegative
|
||||
|
||||
end MinMax
|
||||
116
modules/core/src/main/scala/gs/datagen/v0/generators/Range.scala
Normal file
116
modules/core/src/main/scala/gs/datagen/v0/generators/Range.scala
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
package gs.datagen.v0.generators
|
||||
|
||||
import java.util.Random
|
||||
|
||||
/** Represents a boundd value which must be greater than or equal to 0.
|
||||
*/
|
||||
abstract class Range:
|
||||
def next(random: Random): Int
|
||||
|
||||
object Range:
|
||||
|
||||
given CanEqual[Range, Range] = CanEqual.derived
|
||||
|
||||
/** Fixed range with the value 0.
|
||||
*/
|
||||
val Zero: Range = fixed(0)
|
||||
|
||||
/** Fixed range with the value 1.
|
||||
*/
|
||||
val One: Range = fixed(1)
|
||||
|
||||
/** Fixed range that always produces a single value.
|
||||
*
|
||||
* @param value
|
||||
* The fixed value of the range.
|
||||
* @return
|
||||
* Fixed range that always produces the given value.
|
||||
*/
|
||||
def fixed(value: Int): Range = Fixed(value)
|
||||
|
||||
/** Variable range that produces a value within some lower and upper bound.
|
||||
*
|
||||
* Ranges are _inclusive_ of the bounds.
|
||||
*
|
||||
* @param lower
|
||||
* The lower bound of the range.
|
||||
* @param upper
|
||||
* The upper bound of the range.
|
||||
* @return
|
||||
* Variable range that produces a value inclusive to the given bounds.
|
||||
*/
|
||||
def between(
|
||||
lower: Int,
|
||||
upper: Int
|
||||
): Range = Between(lower, upper)
|
||||
|
||||
final class Fixed private (
|
||||
val value: Int
|
||||
) extends Range:
|
||||
override def next(random: Random): Int = value
|
||||
|
||||
override def equals(that: Any): Boolean =
|
||||
that match
|
||||
case other: Fixed => other.value == value
|
||||
case _ => false
|
||||
|
||||
override def hashCode(): Int = value.hashCode()
|
||||
|
||||
override def toString(): String = value.toString()
|
||||
|
||||
object Fixed:
|
||||
|
||||
given CanEqual[Fixed, Fixed] = CanEqual.derived
|
||||
|
||||
def apply(
|
||||
value: Int
|
||||
): Range =
|
||||
if value < 0 then
|
||||
throw new IllegalArgumentException(
|
||||
s"The fixed range value must be greater than or equal to 0. Received: '$value'"
|
||||
)
|
||||
else new Fixed(value)
|
||||
|
||||
end Fixed
|
||||
|
||||
final class Between private (
|
||||
val lowerBound: Int,
|
||||
val upperBound: Int
|
||||
) extends Range:
|
||||
|
||||
override def next(random: Random): Int =
|
||||
random.nextInt(lowerBound, upperBound + 1)
|
||||
|
||||
override def equals(that: Any): Boolean =
|
||||
that match
|
||||
case other: Between =>
|
||||
other.lowerBound == lowerBound && other.upperBound == upperBound
|
||||
case _ => false
|
||||
|
||||
override def hashCode(): Int =
|
||||
java.util.Objects.hash(lowerBound, upperBound)
|
||||
|
||||
override def toString(): String =
|
||||
s"[$lowerBound, $upperBound]"
|
||||
|
||||
object Between:
|
||||
|
||||
given CanEqual[Between, Between] = CanEqual.derived
|
||||
|
||||
def apply(
|
||||
lowerBound: Int,
|
||||
upperBound: Int
|
||||
): Range =
|
||||
if lowerBound < 0 then
|
||||
throw new IllegalArgumentException(
|
||||
s"The lower bound of a range must be greater than or equal to 0. Received: '$lowerBound'"
|
||||
)
|
||||
else if lowerBound > upperBound then
|
||||
throw new IllegalArgumentException(
|
||||
s"The lower bound of a range must less than the upper bound. Received lowerBound='$lowerBound' and upperBound='$upperBound'"
|
||||
)
|
||||
else new Between(lowerBound, upperBound)
|
||||
|
||||
end Between
|
||||
|
||||
end Range
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
package gs.datagen.v0.generators
|
||||
|
||||
import java.util.Random
|
||||
|
||||
/** Represents a variable size which must (usually) be greater than or equal to
|
||||
* 0.
|
||||
*/
|
||||
abstract class Size:
|
||||
def next(random: Random): Int
|
||||
|
||||
object Size:
|
||||
|
||||
def fixed(size: Int): Size = Fixed(size)
|
||||
|
||||
def between(
|
||||
lower: Int,
|
||||
upper: Int
|
||||
): Size = Between(lower, upper)
|
||||
|
||||
final class Fixed private (
|
||||
size: Int
|
||||
) extends Size:
|
||||
override def next(random: Random): Int = size
|
||||
|
||||
object Fixed:
|
||||
|
||||
def apply(
|
||||
size: Int
|
||||
): Size =
|
||||
if size < 0 then
|
||||
throw new IllegalArgumentException(
|
||||
s"The size must be greater than or equal to 0. Received: '$size'"
|
||||
)
|
||||
else new Fixed(size)
|
||||
|
||||
end Fixed
|
||||
|
||||
final class Between private (
|
||||
lowerBound: Int,
|
||||
upperBound: Int
|
||||
) extends Size:
|
||||
|
||||
override def next(random: Random): Int =
|
||||
random.nextInt(lowerBound, upperBound + 1)
|
||||
|
||||
object Between:
|
||||
|
||||
def apply(
|
||||
lowerBound: Int,
|
||||
upperBound: Int
|
||||
): Size =
|
||||
if lowerBound < 0 then
|
||||
throw new IllegalArgumentException(
|
||||
s"The lower bound of a size must be greater than or equal to 0. Received: '$lowerBound'"
|
||||
)
|
||||
else if lowerBound > upperBound then
|
||||
throw new IllegalArgumentException(
|
||||
s"The lower bound of a size must less than the upper bound. Received lowerBound='$lowerBound' and upperBound='$upperBound'"
|
||||
)
|
||||
else new Between(lowerBound, upperBound)
|
||||
|
||||
end Between
|
||||
|
||||
end Size
|
||||
|
|
@ -1 +1 @@
|
|||
sbt.version=1.11.6
|
||||
sbt.version=1.12.0
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue