(patch) add byte utilities to rng
All checks were successful
/ Build and Test Library Snapshot (pull_request) Successful in 2m27s
All checks were successful
/ Build and Test Library Snapshot (pull_request) Successful in 2m27s
This commit is contained in:
parent
2771c42969
commit
fb34707c4a
2 changed files with 90 additions and 0 deletions
|
|
@ -24,6 +24,19 @@ object ByteCount:
|
|||
*/
|
||||
final val OneGigabyte: ByteCount = 1000000000
|
||||
|
||||
/** Provide integer representations for common sizes in terms of number of
|
||||
* bytes. These values are useful for things like array sizing that depend on
|
||||
* the `Int` type.
|
||||
*/
|
||||
object IntSizes:
|
||||
|
||||
final val Zero: Int = 0
|
||||
final val OneKilobyte: Int = 1000
|
||||
final val OneMegabyte: Int = 1000000
|
||||
final val OneGigabyte: Int = 1000000000
|
||||
|
||||
end IntSizes
|
||||
|
||||
/** Express the given number as a byte count. All values are normalized to the
|
||||
* absolute value -- negative values are coerced to positive.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ package gs.std.v0.effect
|
|||
import cats.Applicative
|
||||
import cats.effect.Sync
|
||||
import cats.syntax.all.*
|
||||
import fs2.Chunk
|
||||
import fs2.Stream
|
||||
import gs.std.v0.core.Blob
|
||||
import gs.std.v0.core.ByteCount
|
||||
import java.security.SecureRandom
|
||||
import java.util.Random
|
||||
|
||||
|
|
@ -154,6 +157,29 @@ trait Rng[F[_]]:
|
|||
bound: Double
|
||||
): Stream[F, Double]
|
||||
|
||||
/** Produce an array of random bytes.
|
||||
*
|
||||
* @param count
|
||||
* The number of bytes to produce.
|
||||
* @return
|
||||
* The array of randomly generated bytes.
|
||||
*/
|
||||
def nextByteArray(count: Int): F[Array[Byte]]
|
||||
|
||||
/** @return
|
||||
* Infinite stream of random bytes.
|
||||
*/
|
||||
def nextBytes(): Stream[F, Byte]
|
||||
|
||||
/** Produce a blob of random bytes.
|
||||
*
|
||||
* @param size
|
||||
* The number of bytes to produce.
|
||||
* @return
|
||||
* The blob of randomly generated bytes.
|
||||
*/
|
||||
def nextBlob(size: Int): F[Blob]
|
||||
|
||||
object Rng:
|
||||
|
||||
/** Instantiate [[Rng]] using a new `java.util.Random` instance.
|
||||
|
|
@ -212,6 +238,42 @@ object Rng:
|
|||
*/
|
||||
final class JavaRandom[F[_]: Sync](random: Random) extends Rng[F]:
|
||||
|
||||
/** @inheritDocs
|
||||
*/
|
||||
override def nextBytes(): Stream[F, Byte] =
|
||||
Stream
|
||||
.evalUnChunk[F, Byte](Sync[F].delay {
|
||||
// Allocate space for the random data. Generate 1kb at once.
|
||||
val bytes = new Array[Byte](ByteCount.IntSizes.OneKilobyte)
|
||||
val _ = random.nextBytes(bytes)
|
||||
// This chunk is _backed by_ the array -- the data isn't copied, so we
|
||||
// allocate a new array each time and cede it to the chunk.
|
||||
Chunk.array(bytes)
|
||||
})
|
||||
.repeat
|
||||
|
||||
/** @inheritDocs
|
||||
*/
|
||||
override def nextByteArray(count: Int): F[Array[Byte]] =
|
||||
if count < 0 then
|
||||
Sync[F].raiseError(
|
||||
new IllegalArgumentException(
|
||||
"Cannot generate a negative number of bytes."
|
||||
)
|
||||
)
|
||||
else if count == 0 then Sync[F].pure(Array.empty)
|
||||
else
|
||||
Sync[F].delay {
|
||||
val bytes = new Array[Byte](count)
|
||||
val _ = random.nextBytes(bytes)
|
||||
bytes
|
||||
}
|
||||
|
||||
/** @inheritDocs
|
||||
*/
|
||||
override def nextBlob(size: Int): F[Blob] =
|
||||
nextByteArray(size).map(new Blob(_))
|
||||
|
||||
/** @inheritDocs
|
||||
*/
|
||||
override def updateSeed(seed: Long): F[Rng[F]] =
|
||||
|
|
@ -306,6 +368,21 @@ object Rng:
|
|||
*/
|
||||
final class Zero[F[_]: Applicative] extends Rng[F]:
|
||||
|
||||
/** @inheritDocs
|
||||
*/
|
||||
override def nextByteArray(count: Int): F[Array[Byte]] =
|
||||
Applicative[F].pure(Array.fill[Byte](count)(0))
|
||||
|
||||
/** @inheritDocs
|
||||
*/
|
||||
override def nextBytes(): Stream[F, Byte] =
|
||||
Stream[F, Byte](0).repeat
|
||||
|
||||
/** @inheritDocs
|
||||
*/
|
||||
override def nextBlob(size: Int): F[Blob] =
|
||||
nextByteArray(size).map(new Blob(_))
|
||||
|
||||
/** @inheritDocs
|
||||
*/
|
||||
override def updateSeed(seed: Long): F[Rng[F]] = Applicative[F].pure(this)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue