72 lines
1.7 KiB
Scala
72 lines
1.7 KiB
Scala
package gs.predicate.v0.api
|
|
|
|
import cats.Applicative
|
|
import cats.syntax.all.*
|
|
import gs.predicate.v0.serde.json.JsonKeys
|
|
import io.circe.Decoder
|
|
import io.circe.DecodingFailure
|
|
import io.circe.Encoder
|
|
import io.circe.Json
|
|
import io.circe.syntax.*
|
|
|
|
/** Implements logical OR.
|
|
*
|
|
* @param ps
|
|
* The predicates to evaluate.
|
|
*/
|
|
final class Or[F[_]: Applicative](
|
|
val ps: List[Predicate[F]]
|
|
) extends Predicate[F]:
|
|
|
|
/** @inheritDocs
|
|
*/
|
|
override def predicateType: String = Or.PredicateType
|
|
|
|
/** @inheritDocs
|
|
*/
|
|
override def eval(): F[Predicate.Result] =
|
|
ps.map(_.eval()).sequence.map(_.anyMatch())
|
|
|
|
object Or:
|
|
|
|
final val PredicateType: String = "or"
|
|
|
|
def empty[F[_]: Applicative]: Predicate[F] = False[F]
|
|
|
|
def apply[F[_]: Applicative, A](ps: Predicate[F]*): Predicate[F] =
|
|
ps.toList match
|
|
case Nil => False[F]
|
|
case p :: Nil => p
|
|
case list => new Or(list)
|
|
|
|
given orEncoder[F[_]](
|
|
using
|
|
Encoder[Predicate[F]]
|
|
): Encoder[Or[F]] =
|
|
Encoder.instance[Or[F]] { p =>
|
|
Json.obj(
|
|
(JsonKeys.predicateType, Json.fromString(PredicateType)),
|
|
(JsonKeys.predicates, p.ps.asJson)
|
|
)
|
|
}
|
|
|
|
given orDecoder[F[_]: Applicative](
|
|
using
|
|
Decoder[Predicate[F]]
|
|
): Decoder[Or[F]] =
|
|
Decoder.instance[Or[F]] { cursor =>
|
|
cursor.downField(JsonKeys.predicateType).as[String].flatMap {
|
|
case PredicateType =>
|
|
for ps <- cursor.downField(JsonKeys.predicates).as[List[Predicate[F]]]
|
|
yield new Or(ps)
|
|
case candidate =>
|
|
Left(
|
|
DecodingFailure(
|
|
Messages.invalidPredicateType(candidate, PredicateType),
|
|
Nil
|
|
)
|
|
)
|
|
}
|
|
}
|
|
|
|
end Or
|