Created
February 24, 2015 09:40
-
-
Save ovechkin-dm/7b566ae66dca6f8832e9 to your computer and use it in GitHub Desktop.
Request get required parameters with shapeless
This file contains hidden or 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
import scala.util.Try | |
import shapeless._ | |
object ReqOps extends App { | |
trait ParamMapper[A <: HList, R <: HList] { | |
def map(hl: A): R | |
} | |
trait ParamChecker[A <: HList] { | |
def check(all: List[String], failed: Boolean, rest: A): Unit | |
} | |
implicit def nilChecker = new ParamChecker[HNil] { | |
def check(all: List[String], failed: Boolean, rest: HNil): Unit = if (failed) throw new Exception( s"""required params are: ${all.mkString(",")}""") | |
} | |
implicit def consChecker[P, A <: HList](implicit tChecker: ParamChecker[A]) = new ParamChecker[ReqParam[P] :: A] { | |
def check(all: List[String], failed: Boolean, rest: ReqParam[P] :: A): Unit = { | |
val empty = rest.head.value.isEmpty | |
tChecker.check(rest.head.name :: all, empty || failed, rest.tail) | |
} | |
} | |
implicit def nilParamMapper = new ParamMapper[HNil, HNil] { | |
def map(hl: HNil): HNil = HNil | |
} | |
implicit def consParamMapper[H, T <: HList, TOUT <: HList](implicit tmap: ParamMapper[T, TOUT]): ParamMapper[ReqParam[H] :: T, H :: TOUT] = | |
new ParamMapper[ReqParam[H] :: T, H :: TOUT] { | |
def map(hl: ReqParam[H] :: T): H :: TOUT = hl.head.value.get :: tmap.map(hl.tail) | |
} | |
trait ParamParser[A] { | |
def parse(s: String): A | |
} | |
implicit def intParser: ParamParser[Int] = new ParamParser[Int] { | |
def parse(s: String): Int = s.toInt | |
} | |
implicit def stringParser: ParamParser[String] = new ParamParser[String] { | |
def parse(s: String): String = s | |
} | |
case class ReqParam[T](name: String, value: Option[T]) | |
case class Request(params: Map[String, String]) { | |
def getRequiredParams[A <: HList, R <: HList](a: A)(implicit checker: ParamChecker[A], mapper: ParamMapper[A, R]): R = { | |
checker.check(Nil, false, a) | |
mapper.map(a) | |
} | |
def asParam[A](s: String)(implicit p: ParamParser[A]): ReqParam[A] = { | |
ReqParam(s, Try(p.parse(params(s))).toOption) | |
} | |
} | |
val rawParams = Map(("1" -> "123"), ("2" -> "test")) | |
val req = Request(rawParams) | |
val h = req.asParam[Int]("1") :: req.asParam[String]("2") :: HNil | |
req.getRequiredParams(h) match { | |
case first :: second :: _ => | |
println(first) // 123, type Int at compile | |
println(second) // test, type String at compile | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment