Expanding library to effectful operations.
All checks were successful
/ Build and Release Library (push) Successful in 1m31s
All checks were successful
/ Build and Release Library (push) Successful in 1m31s
This commit is contained in:
parent
9abef2d8ce
commit
eedf6e8f04
3 changed files with 289 additions and 9 deletions
13
build.sbt
13
build.sbt
|
|
@ -45,7 +45,7 @@ lazy val testSettings = Seq(
|
||||||
|
|
||||||
lazy val `gs-std` = project
|
lazy val `gs-std` = project
|
||||||
.in(file("."))
|
.in(file("."))
|
||||||
.aggregate(core, io, effect, stream)
|
.aggregate(core, io, effect)
|
||||||
.settings(sharedSettings)
|
.settings(sharedSettings)
|
||||||
.settings(testSettings)
|
.settings(testSettings)
|
||||||
.settings(name := s"${gsProjectName.value}-v${semVerMajor.value}")
|
.settings(name := s"${gsProjectName.value}-v${semVerMajor.value}")
|
||||||
|
|
@ -75,11 +75,6 @@ lazy val effect = project
|
||||||
.settings(sharedSettings)
|
.settings(sharedSettings)
|
||||||
.settings(testSettings)
|
.settings(testSettings)
|
||||||
.settings(name := s"${gsProjectName.value}-effect-v${semVerMajor.value}")
|
.settings(name := s"${gsProjectName.value}-effect-v${semVerMajor.value}")
|
||||||
.settings(libraryDependencies ++= Seq(Deps.Cats.Core, Deps.Cats.Effect))
|
.settings(
|
||||||
|
libraryDependencies ++= Seq(Deps.Cats.Core, Deps.Cats.Effect, Deps.Fs2.Core)
|
||||||
lazy val stream = project
|
)
|
||||||
.in(file("modules/stream"))
|
|
||||||
.settings(sharedSettings)
|
|
||||||
.settings(testSettings)
|
|
||||||
.settings(name := s"${gsProjectName.value}-stream-v${semVerMajor.value}")
|
|
||||||
.settings(libraryDependencies ++= Seq(Deps.Fs2.Core))
|
|
||||||
|
|
|
||||||
168
modules/effect/src/main/scala/src/gs/std/v0/effect/RNG.scala
Normal file
168
modules/effect/src/main/scala/src/gs/std/v0/effect/RNG.scala
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
package gs.std.v0.effect
|
||||||
|
|
||||||
|
import cats.Applicative
|
||||||
|
import cats.effect.Sync
|
||||||
|
import fs2.Stream
|
||||||
|
import java.security.SecureRandom
|
||||||
|
import java.util.Random
|
||||||
|
|
||||||
|
trait RNG[F[_]]:
|
||||||
|
def nextInt(): F[Int]
|
||||||
|
def nextInt(bound: Int): F[Int]
|
||||||
|
|
||||||
|
def nextInt(
|
||||||
|
origin: Int,
|
||||||
|
bound: Int
|
||||||
|
): F[Int]
|
||||||
|
|
||||||
|
def nextLong(): F[Long]
|
||||||
|
def nextLong(bound: Long): F[Long]
|
||||||
|
|
||||||
|
def nextLong(
|
||||||
|
origin: Long,
|
||||||
|
bound: Long
|
||||||
|
): F[Long]
|
||||||
|
|
||||||
|
def nextDouble(): F[Double]
|
||||||
|
def nextDouble(bound: Double): F[Double]
|
||||||
|
|
||||||
|
def nextDouble(
|
||||||
|
origin: Double,
|
||||||
|
bound: Double
|
||||||
|
): F[Double]
|
||||||
|
|
||||||
|
def nextBoolean(): F[Boolean]
|
||||||
|
|
||||||
|
def nextInts(
|
||||||
|
origin: Int,
|
||||||
|
bound: Int
|
||||||
|
): Stream[F, Int]
|
||||||
|
|
||||||
|
def nextLongs(
|
||||||
|
origin: Long,
|
||||||
|
bound: Long
|
||||||
|
): Stream[F, Long]
|
||||||
|
|
||||||
|
def nextDoubles(
|
||||||
|
origin: Double,
|
||||||
|
bound: Double
|
||||||
|
): Stream[F, Double]
|
||||||
|
|
||||||
|
object RNG:
|
||||||
|
|
||||||
|
def secure[F[_]: Sync]: RNG[F] =
|
||||||
|
new JavaRandom[F](new SecureRandom())
|
||||||
|
|
||||||
|
final class JavaRandom[F[_]: Sync](random: Random) extends RNG[F]:
|
||||||
|
|
||||||
|
override def nextInt(): F[Int] =
|
||||||
|
Sync[F].delay(random.nextInt())
|
||||||
|
|
||||||
|
override def nextInt(bound: Int): F[Int] =
|
||||||
|
Sync[F].delay(random.nextInt(bound))
|
||||||
|
|
||||||
|
override def nextInt(
|
||||||
|
origin: Int,
|
||||||
|
bound: Int
|
||||||
|
): F[Int] =
|
||||||
|
Sync[F].delay(random.nextInt(origin, bound))
|
||||||
|
|
||||||
|
override def nextLong(): F[Long] =
|
||||||
|
Sync[F].delay(random.nextLong())
|
||||||
|
|
||||||
|
override def nextLong(bound: Long): F[Long] =
|
||||||
|
Sync[F].delay(random.nextLong(bound))
|
||||||
|
|
||||||
|
override def nextLong(
|
||||||
|
origin: Long,
|
||||||
|
bound: Long
|
||||||
|
): F[Long] =
|
||||||
|
Sync[F].delay(random.nextLong(origin, bound))
|
||||||
|
|
||||||
|
override def nextDouble(): F[Double] =
|
||||||
|
Sync[F].delay(random.nextDouble())
|
||||||
|
|
||||||
|
override def nextDouble(bound: Double): F[Double] =
|
||||||
|
Sync[F].delay(random.nextDouble(bound))
|
||||||
|
|
||||||
|
override def nextDouble(
|
||||||
|
origin: Double,
|
||||||
|
bound: Double
|
||||||
|
): F[Double] =
|
||||||
|
Sync[F].delay(random.nextDouble(origin, bound))
|
||||||
|
|
||||||
|
override def nextBoolean(): F[Boolean] =
|
||||||
|
Sync[F].delay(random.nextBoolean())
|
||||||
|
|
||||||
|
override def nextInts(
|
||||||
|
origin: Int,
|
||||||
|
bound: Int
|
||||||
|
): Stream[F, Int] =
|
||||||
|
Stream.repeatEval(nextInt(origin, bound))
|
||||||
|
|
||||||
|
override def nextLongs(
|
||||||
|
origin: Long,
|
||||||
|
bound: Long
|
||||||
|
): Stream[F, Long] =
|
||||||
|
Stream.repeatEval(nextLong(origin, bound))
|
||||||
|
|
||||||
|
override def nextDoubles(
|
||||||
|
origin: Double,
|
||||||
|
bound: Double
|
||||||
|
): Stream[F, Double] =
|
||||||
|
Stream.repeatEval(nextDouble(origin, bound))
|
||||||
|
|
||||||
|
end JavaRandom
|
||||||
|
|
||||||
|
final class Zero[F[_]: Applicative] extends RNG[F]:
|
||||||
|
|
||||||
|
override def nextInt(): F[Int] = Applicative[F].pure(0)
|
||||||
|
|
||||||
|
override def nextInt(bound: Int): F[Int] = Applicative[F].pure(0)
|
||||||
|
|
||||||
|
override def nextInt(
|
||||||
|
origin: Int,
|
||||||
|
bound: Int
|
||||||
|
): F[Int] = Applicative[F].pure(0)
|
||||||
|
|
||||||
|
override def nextLong(): F[Long] = Applicative[F].pure(0)
|
||||||
|
|
||||||
|
override def nextLong(bound: Long): F[Long] = Applicative[F].pure(0)
|
||||||
|
|
||||||
|
override def nextLong(
|
||||||
|
origin: Long,
|
||||||
|
bound: Long
|
||||||
|
): F[Long] = Applicative[F].pure(0)
|
||||||
|
|
||||||
|
override def nextDouble(): F[Double] = Applicative[F].pure(0.0)
|
||||||
|
|
||||||
|
override def nextDouble(bound: Double): F[Double] = Applicative[F].pure(0.0)
|
||||||
|
|
||||||
|
override def nextDouble(
|
||||||
|
origin: Double,
|
||||||
|
bound: Double
|
||||||
|
): F[Double] = Applicative[F].pure(0.0)
|
||||||
|
|
||||||
|
override def nextBoolean(): F[Boolean] = Applicative[F].pure(false)
|
||||||
|
|
||||||
|
override def nextInts(
|
||||||
|
origin: Int,
|
||||||
|
bound: Int
|
||||||
|
): Stream[F, Int] =
|
||||||
|
Stream.repeatEval(Applicative[F].pure(0))
|
||||||
|
|
||||||
|
override def nextLongs(
|
||||||
|
origin: Long,
|
||||||
|
bound: Long
|
||||||
|
): Stream[F, Long] =
|
||||||
|
Stream.repeatEval(Applicative[F].pure(0))
|
||||||
|
|
||||||
|
override def nextDoubles(
|
||||||
|
origin: Double,
|
||||||
|
bound: Double
|
||||||
|
): Stream[F, Double] =
|
||||||
|
Stream.repeatEval(Applicative[F].pure(0.0))
|
||||||
|
|
||||||
|
end Zero
|
||||||
|
|
||||||
|
end RNG
|
||||||
117
modules/io/src/main/scala/src/gs/std/v0/io/Files.scala
Normal file
117
modules/io/src/main/scala/src/gs/std/v0/io/Files.scala
Normal file
|
|
@ -0,0 +1,117 @@
|
||||||
|
package gs.std.v0.io
|
||||||
|
|
||||||
|
import cats.effect.Resource
|
||||||
|
import cats.effect.Sync
|
||||||
|
import java.io.InputStream
|
||||||
|
import java.io.OutputStream
|
||||||
|
import java.nio.charset.Charset
|
||||||
|
import java.nio.charset.StandardCharsets
|
||||||
|
import java.nio.file.OpenOption
|
||||||
|
import java.nio.file.Path
|
||||||
|
import java.nio.file.StandardOpenOption
|
||||||
|
import scala.jdk.CollectionConverters.*
|
||||||
|
|
||||||
|
/** Common operations on files, wrapped using Cats Effect. If you want to Stream
|
||||||
|
* files, the `fs2-io` package is the place to go.
|
||||||
|
*
|
||||||
|
* Includes wrappers around some `java.nio.file.Files` functionality.
|
||||||
|
*/
|
||||||
|
object Files:
|
||||||
|
|
||||||
|
def readFileAsString[F[_]: Sync](
|
||||||
|
path: Path,
|
||||||
|
charset: Charset = StandardCharsets.UTF_8
|
||||||
|
): F[String] =
|
||||||
|
Sync[F].delay(java.nio.file.Files.readString(path, charset))
|
||||||
|
|
||||||
|
def readFileAsBytes[F[_]: Sync](path: Path): F[Array[Byte]] =
|
||||||
|
Sync[F].delay(java.nio.file.Files.readAllBytes(path))
|
||||||
|
|
||||||
|
def readFileAsLines[F[_]: Sync](
|
||||||
|
path: Path,
|
||||||
|
charset: Charset = StandardCharsets.UTF_8
|
||||||
|
): F[List[String]] =
|
||||||
|
Sync[F].delay(
|
||||||
|
java.nio.file.Files.readAllLines(path, charset).asScala.toList
|
||||||
|
)
|
||||||
|
|
||||||
|
def overwriteFileWithString[F[_]: Sync](
|
||||||
|
path: Path,
|
||||||
|
data: String
|
||||||
|
): F[Unit] =
|
||||||
|
Sync[F].delay(
|
||||||
|
java.nio.file.Files.writeString(
|
||||||
|
path,
|
||||||
|
data,
|
||||||
|
StandardOpenOption.WRITE,
|
||||||
|
StandardOpenOption.TRUNCATE_EXISTING
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def overwriteFileWithBytes[F[_]: Sync](
|
||||||
|
path: Path,
|
||||||
|
data: Array[Byte]
|
||||||
|
): F[Unit] =
|
||||||
|
Sync[F].delay(
|
||||||
|
java.nio.file.Files.write(
|
||||||
|
path,
|
||||||
|
data,
|
||||||
|
StandardOpenOption.WRITE,
|
||||||
|
StandardOpenOption.TRUNCATE_EXISTING
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def appendFileWithString[F[_]: Sync](
|
||||||
|
path: Path,
|
||||||
|
data: String
|
||||||
|
): F[Unit] =
|
||||||
|
Sync[F].delay(
|
||||||
|
java.nio.file.Files.writeString(
|
||||||
|
path,
|
||||||
|
data,
|
||||||
|
StandardOpenOption.WRITE,
|
||||||
|
StandardOpenOption.APPEND
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
def appendFileWithBytes[F[_]: Sync](
|
||||||
|
path: Path,
|
||||||
|
data: Array[Byte]
|
||||||
|
): F[Unit] =
|
||||||
|
Sync[F].delay(
|
||||||
|
java.nio.file.Files
|
||||||
|
.write(path, data, StandardOpenOption.WRITE, StandardOpenOption.APPEND)
|
||||||
|
)
|
||||||
|
|
||||||
|
def isRegularFile[F[_]: Sync](path: Path): F[Boolean] =
|
||||||
|
Sync[F].delay(java.nio.file.Files.isRegularFile(path))
|
||||||
|
|
||||||
|
def isReadable[F[_]: Sync](path: Path): F[Boolean] =
|
||||||
|
Sync[F].delay(java.nio.file.Files.isReadable(path))
|
||||||
|
|
||||||
|
def isWritable[F[_]: Sync](path: Path): F[Boolean] =
|
||||||
|
Sync[F].delay(java.nio.file.Files.isWritable(path))
|
||||||
|
|
||||||
|
def isDirectory[F[_]: Sync](path: Path): F[Boolean] =
|
||||||
|
Sync[F].delay(java.nio.file.Files.isDirectory(path))
|
||||||
|
|
||||||
|
def isExecutable[F[_]: Sync](path: Path): F[Boolean] =
|
||||||
|
Sync[F].delay(java.nio.file.Files.isExecutable(path))
|
||||||
|
|
||||||
|
def openInputStream[F[_]: Sync](
|
||||||
|
path: Path,
|
||||||
|
openOptions: OpenOption*
|
||||||
|
): Resource[F, InputStream] =
|
||||||
|
Resource.make(
|
||||||
|
Sync[F].delay(java.nio.file.Files.newInputStream(path, openOptions*))
|
||||||
|
)(inputStream => Sync[F].delay(inputStream.close()))
|
||||||
|
|
||||||
|
def openOutputStream[F[_]: Sync](
|
||||||
|
path: Path,
|
||||||
|
openOptions: OpenOption*
|
||||||
|
): Resource[F, OutputStream] =
|
||||||
|
Resource.make(
|
||||||
|
Sync[F].delay(java.nio.file.Files.newOutputStream(path, openOptions*))
|
||||||
|
)(outputStream => Sync[F].delay(outputStream.close()))
|
||||||
|
|
||||||
|
end Files
|
||||||
Loading…
Add table
Reference in a new issue