Last active
April 18, 2016 13:25
-
-
Save wolfendale/e72d7b1c9cb0e4a9f8cb to your computer and use it in GitHub Desktop.
Validation Shapeless
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package wolfendale | |
trait Enum { | |
type Value <: Singleton | |
} | |
object Enum { | |
trait Aux[A <: Singleton] extends Enum { type Value = A } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package wolfendale | |
import play.api.data.mapping._ | |
import shapeless.labelled.FieldType | |
import shapeless.{Path => _, _} | |
trait RuleInstances0 { | |
implicit def productR[I, A <: Product, H <: HList] | |
(implicit | |
gen: LabelledGeneric.Aux[A, H], | |
r: Lazy[Rule[I, H]] | |
): Rule[I, A] = | |
r.value fmap (gen.from) | |
implicit def coproductR[I, A, C <: Coproduct] | |
(implicit | |
gen: Generic.Aux[A, C], | |
r: Lazy[Rule[I, C]] | |
): Rule[I, A] = | |
r.value fmap (gen.from) | |
} | |
trait RuleInstances extends RuleInstances0 { | |
implicit def hnilR[I]: Rule[I, HNil] = Rule { | |
_ => Success(HNil) | |
} | |
implicit def cnilR[I]: Rule[I, CNil] = Rule { | |
_ => Failure(Seq(Path -> Seq(ValidationError("error.invalid")))) | |
} | |
implicit def hconsR[I, H, T <: HList] | |
(implicit | |
hR: Lazy[Rule[I, H]], | |
tR: Lazy[Rule[I, T]] | |
): Rule[I, H :: T] = | |
Rule[I, H :: T] { data => | |
(hR.value.validate(data), tR.value.validate(data)) match { | |
case (Success(_), Failure(e)) => Failure(e) | |
case (Failure(e), Success(_)) => Failure(e) | |
case (Failure(h), Failure(t)) => Failure(h ++ t) | |
case (Success(h), Success(t)) => Success(h :: t) | |
} | |
} | |
implicit def cconsR[I, H <: Enum, T <: Coproduct] | |
(implicit | |
p: Path => RuleLike[I, String], | |
wV: Witness.Aux[H#Value], | |
hR: Lazy[Rule[I, H]], | |
tR: Lazy[Rule[I, T]] | |
): Rule[I, H :+: T] = | |
Rule[I, H :+: T] { data => | |
(From[I] { __ => | |
import play.api.data.mapping.GenericRules._ | |
(__ \ "type").read(equalTo(wV.value.toString)) | |
}.validate(data) match { | |
case Success(_) => hR.value fmap Inl.apply | |
case _ => tR.value fmap Inr.apply | |
}).validate(data) | |
} | |
implicit def fieldR[I, K, O] | |
(implicit | |
wk: Witness.Aux[K], | |
p: Lazy[Path => RuleLike[I, O]] | |
): Rule[I, FieldType[K, O]] = | |
From[I] { | |
import labelled._ | |
val key = wk.value.toString.substring(1) | |
__ => (__ \ key).read[O](p.value) fmap (field[K](_)) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment