Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2021 Tamer Abdulradi
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use a file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mazboot
package validations
import scala.util.CommandLineParser
import com.abdulradi.happypath.ErrorCase
/**
* Module that can define a newtype together with validation logic
*
* All instances of this trait anywhere in the codebase can be retrieved
* given a Valid type via the `Validation.Of` typeclass
*/
trait Validation[Raw]:
outer =>
opaque type Valid <: Raw = Raw
given Validation.Of[Valid] with
type R = Raw
def validation = outer
final case class Error(raw: Raw) extends ValidationError(outer.formatErrorMessage(raw))
def validateWith[A](raw: Raw, handleSuccess: Valid => A, handleError: this.Error => A): A
final def validate(raw: Raw): this.Error | Valid =
validateWith(raw, identity, identity)
final def validateEither(raw: Raw): Either[this.Error, Valid] =
validateWith(raw, Right.apply, Left.apply)
protected def formatErrorMessage(raw: Raw): String
final def unapply(raw: Raw): Option[Valid] =
validateWith(raw, Some.apply, _ => None)
given (using Raw: CommandLineParser.FromString[Raw]): CommandLineParser.FromString[Valid] with
def fromString(s: String): Valid = validateWith(Raw.fromString(s), identity, e => throw IllegalArgumentException(e.message))
object Validation:
def fromPredicate[Raw, V <: Raw](predicate: Raw => Boolean, predicateName: String): FromPredicate.Aux[Raw, V] =
FromPredicate.aux(predicate, predicateName)
/**
* Typeclass that allows lookup of a validation given a Valid type
*/
sealed trait Of[V]:
type R
def validation: Validation[R] { type Valid = V }
abstract class FromPredicate0[Raw](
val predicate: Raw => Boolean,
val predicateName: String) extends Validation[Raw]:
override opaque type Valid <: Raw = Raw
final def validateWith[A](raw: Raw, handleSuccess: Valid => A, handleError: this.Error => A): A =
if predicate(raw) then handleSuccess(raw) else handleError(this.Error(raw))
protected def formatErrorMessage(raw: Raw): String =
s"'$raw' doesn't pass the predicate: $predicateName"
open class FromPredicate[Raw]( // Doesn't know that Valid is actually Raw
predicate: Raw => Boolean,
predicateName: String) extends FromPredicate0[Raw](predicate, predicateName):
infix def or[Valid2 <: Raw](that: FromPredicate.Aux[Raw, Valid2]): FromPredicate.Aux[Raw, Valid | Valid2] =
FromPredicate.aux(
raw => this.predicate(raw) || that.predicate(raw),
s"${this.predicateName} or ${that.predicateName}"
)
infix def and[Valid2 <: Raw](that: FromPredicate.Aux[Raw, Valid2]): FromPredicate.Aux[Raw, Valid & Valid2] =
FromPredicate.aux(
raw => this.predicate(raw) && that.predicate(raw),
s"${this.predicateName} and ${that.predicateName}"
)
def negate: FromPredicate[Raw] =
new FromPredicate[Raw](raw => ! predicate(raw), s"not $predicateName")
object FromPredicate:
type Aux[Raw, V] = FromPredicate[Raw] { type Valid = V }
def aux[Raw, V <: Raw](predicate: Raw => Boolean, predicateName: String): Aux[Raw, V] =
new FromPredicate[Raw](predicate, predicateName) {
override type Valid = V
}
/** checks if a value equals to the specified reference */
open class EqualsTo[A](a: A) extends FromPredicate[A](_ == a, s"equals $a")