diff --git a/README.md b/README.md index 8c1a88c2..3b8f9f6e 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ ivy"io.github.iltotore::iron:version" | iron | ✔️ | ✔️ | ✔️ | | iron-cats | ✔️ | ✔️ | ✔️ | | iron-circe | ✔️ | ✔️ | ✔️ | +| iron-jsoniter | ✔️ | ✔️ | ✔️ | | iron-zio | ✔️ | ✔️ | ❌ | | iron-zio-json | ✔️ | ✔️ | ❌ | diff --git a/docs/_docs/modules/index.md b/docs/_docs/modules/index.md index ab9acd46..2cef4e7c 100644 --- a/docs/_docs/modules/index.md +++ b/docs/_docs/modules/index.md @@ -11,5 +11,6 @@ These modules are mostly "support"/"interoperability" modules to provide out of ## Official modules - [Cats](cats.md): Typeclass instances and accumulative refinement methods. - [Circe](circe.md): Typeclass instances for refinement types. +- [Jsoniter](jsoniter.md): Typeclass instances for refinement types. - [ZIO](zio.md): Accumulative refinement method. - [ZIO-Json](zio-json.md): Typeclass instances for refinement types. diff --git a/docs/_docs/modules/jsoniter.md b/docs/_docs/modules/jsoniter.md new file mode 100644 index 00000000..6dbe3103 --- /dev/null +++ b/docs/_docs/modules/jsoniter.md @@ -0,0 +1,45 @@ +--- +title: "Jsoniter Support" +--- + +# Jsoniter Support + +This module provides refined types codec instances for [Jsoniter Scala](https://github.com/plokhotnyuk/jsoniter-scala). + +## Dependency + +SBT: + +```scala +libraryDependencies += "io.github.iltotore" %% "iron-jsoniter" % "version" +``` + +Mill: + +```scala +ivy"io.github.iltotore::iron-jsoniter:version" +``` + +## Encoder/Decoder instances + +Given `JsonValueCodec` for Iron enables using refined types for JSON serialization/deserialization: + +```scala +import com.github.plokhotnyuk.jsoniter_scala.macros.* +import com.github.plokhotnyuk.jsoniter_scala.core.* + +import io.github.iltotore.iron.* +import io.github.iltotore.iron.constraint.all.* +import io.github.iltotore.iron.jsoniter.given + +case class User(name: String :| Alphanumeric, age: Int :| Positive) + +given JsonValueCodec[User] = JsonCodecMaker.make + +//Encoding +writeToString[User](User("totore", 18)) + +//Decoding +readFromString[User]("""{"name":"totore","age":18}""") +readFromString[User]("""{"name":"totore","age":-18}""") //Error: "Should be positive" +``` diff --git a/docs/_docs/reference/constraint.md b/docs/_docs/reference/constraint.md index 6923050d..1264a407 100644 --- a/docs/_docs/reference/constraint.md +++ b/docs/_docs/reference/constraint.md @@ -9,6 +9,41 @@ instance of [[Constraint|io.github.iltotore.iron.Constraint]]. See [Refinement](refinement.md) for usage. +## Operations + +Usually, you can make your constraint out of existing ones. Iron provides several operators to help you to compose them. + +### Union and intersection + +Type union `C1 | C2` and intersection `C1 & C2` respectively act as a boolean OR/AND in Iron. For example, [[GreaterEqual|io.github.iltotore.iron.constraint.numeric.GreaterEqual]] is just a union of [[Greater|io.github.iltotore.iron.constraint.numeric.Greater]] and [[StrictEqual|io.github.iltotore.iron.constraint.numeric.StrictEqual]]: + +```scala +import io.github.iltotore.iron.* +import io.github.iltotore.iron.constraint.numeric.{Greater, StrictEqual} + +type GreaterEqual[V] = Greater[V] | StrictEqual[V] + +val x: Int :| GreaterEqual[0] = 1 //OK +val y: Int :| GreaterEqual[0] = 1 //OK +val z: Int :| GreaterEqual[0] = -1 //Compile-time error: (Should be greater than 0 | Should strictly equal to 0) +``` + +Same goes for intersection: + +```scala +type Between[Min, Max] = GreaterEqual[Min] & LessEqual[Max] +``` + +### Other operations + +Most constraint operators provided by Iron are "normal" constraints taking another constraint as parameter. + +Here is a list of the most used operators: +- [[Not\[C\]|io.github.iltotore.iron.constraint.any.Not]]: like a boolean "not". Negate the result of the `C` constraint. +- [[DescribedAs\[C, V\]|io.github.iltotore.iron.constraint.any.DescribedAs]]: attach a custom description `V` to `C`. +- [[ForAll\[C\]|io.github.iltotore.iron.constraint.collection.ForAll]]: check if the `C` constraint passes for all elements of a collection/String +- [[Exists\[C\]|io.github.iltotore.iron.constraint.collection.Exists]]: check if the `C` constraint passes for at least one element of a collection/String + ## Dummy type Usually, the dummy type is represented by a final class. Note that this class (or whatever entity you choose as a dummy) @@ -53,8 +88,8 @@ given PositiveConstraint[Double] with This constraint can now be used like any other: ```scala -var x: Int :| Positive = 1 -x = 0 //Compile-time error: Should be strictly positive +val x: Int :| Positive = 1 +val y: Int :| Positive = -1 //Compile-time error: Should be strictly positive ``` ## Constraint parameters @@ -85,26 +120,6 @@ This method is equivalent to `constValue[scala.compiletime.ops.any.ToString[V]]` Now testing the constraint: ```scala -var x: Int :| Greater[5] = 6 -x = 3 //Compile-time error: Should be greater than 5 -``` - -## Constraint aliases - -In some cases, you can make your constraint out of existing ones. -For example, a "greater or equal" constraint is just the `Greater` union `StrictEqual`. - -Like "classic" types, constraints can be aliased: - -```scala -type GreaterEqual[V] = Greater[V] | StrictEqual[V] -``` - -you can use the `DescribedAs` constraint enables attaching a custom description to our alias: - -```scala -//Allows to concatenate string types. -import io.github.iltotore.iron.compileTime.+ - -type GreaterEqual[V] = (Greater[V] | StrictEqual[V]) DescribedAs ("Should be greater or equal to " + V) +val x: Int :| Greater[5] = 6 +val y: Int :| Greater[5] = 3 //Compile-time error: Should be greater than 5 ``` \ No newline at end of file diff --git a/docs/sidebar.yml b/docs/sidebar.yml index fbaa7ecf..e24da114 100644 --- a/docs/sidebar.yml +++ b/docs/sidebar.yml @@ -18,5 +18,6 @@ subsection: subsection: - page: modules/cats.md - page: modules/circe.md + - page: modules/jsoniter.md - page: modules/zio.md - page: modules/zio-json.md