=htp add explicit result types to formField/parameter implicits
Otherwise, the applicability of the implicit conversions can depend on the order of compiler-internal loading/typing which is hardly predictable.
This commit is contained in:
parent
edab520787
commit
c417d727da
4 changed files with 31 additions and 36 deletions
|
|
@ -9,9 +9,6 @@ import akka.http.scaladsl.server.Route
|
||||||
import akka.http.scaladsl.model._
|
import akka.http.scaladsl.model._
|
||||||
|
|
||||||
class FormFieldDirectivesExamplesSpec extends RoutingSpec {
|
class FormFieldDirectivesExamplesSpec extends RoutingSpec {
|
||||||
// FIXME: investigate why it doesn't work without this import
|
|
||||||
import akka.http.scaladsl.server.directives.FormFieldDirectives.FieldMagnet
|
|
||||||
|
|
||||||
"formFields" in {
|
"formFields" in {
|
||||||
val route =
|
val route =
|
||||||
formFields('color, 'age.as[Int]) { (color, age) =>
|
formFields('color, 'age.as[Int]) { (color, age) =>
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,6 @@ import akka.http.scaladsl.model._
|
||||||
import akka.http.scaladsl.server.Route
|
import akka.http.scaladsl.server.Route
|
||||||
|
|
||||||
class ParameterDirectivesExamplesSpec extends RoutingSpec {
|
class ParameterDirectivesExamplesSpec extends RoutingSpec {
|
||||||
// FIXME: investigate why it doesn't work without this import
|
|
||||||
import akka.http.scaladsl.server.directives.ParameterDirectives.ParamMagnet
|
|
||||||
|
|
||||||
"example-1" in {
|
"example-1" in {
|
||||||
val route =
|
val route =
|
||||||
parameter('color) { color =>
|
parameter('color) { color =>
|
||||||
|
|
|
||||||
|
|
@ -35,20 +35,20 @@ object FormFieldDirectives extends FormFieldDirectives {
|
||||||
def apply(): Out
|
def apply(): Out
|
||||||
}
|
}
|
||||||
object FieldMagnet {
|
object FieldMagnet {
|
||||||
implicit def apply[T](value: T)(implicit fdef: FieldDef[T]) =
|
implicit def apply[T](value: T)(implicit fdef: FieldDef[T]): FieldMagnet { type Out = fdef.Out } =
|
||||||
new FieldMagnet {
|
new FieldMagnet {
|
||||||
type Out = fdef.Out
|
type Out = fdef.Out
|
||||||
def apply() = fdef(value)
|
def apply() = fdef(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type FieldDefAux[A, B] = FieldDef[A] { type Out = B }
|
||||||
sealed trait FieldDef[T] {
|
sealed trait FieldDef[T] {
|
||||||
type Out
|
type Out
|
||||||
def apply(value: T): Out
|
def apply(value: T): Out
|
||||||
}
|
}
|
||||||
|
|
||||||
object FieldDef {
|
object FieldDef {
|
||||||
def fieldDef[A, B](f: A ⇒ B) =
|
def fieldDef[A, B](f: A ⇒ B): FieldDefAux[A, B] =
|
||||||
new FieldDef[A] {
|
new FieldDef[A] {
|
||||||
type Out = B
|
type Out = B
|
||||||
def apply(value: A) = f(value)
|
def apply(value: A) = f(value)
|
||||||
|
|
@ -63,7 +63,7 @@ object FormFieldDirectives extends FormFieldDirectives {
|
||||||
|
|
||||||
//////////////////// "regular" formField extraction ////////////////////
|
//////////////////// "regular" formField extraction ////////////////////
|
||||||
|
|
||||||
private def extractField[A, B](f: A ⇒ Directive1[B]) = fieldDef(f)
|
private def extractField[A, B](f: A ⇒ Directive1[B]): FieldDefAux[A, Directive1[B]] = fieldDef(f)
|
||||||
private def fieldOfForm[T](fieldName: String, fu: Unmarshaller[Option[StrictForm.Field], T])(implicit sfu: SFU): RequestContext ⇒ Future[T] = { ctx ⇒
|
private def fieldOfForm[T](fieldName: String, fu: Unmarshaller[Option[StrictForm.Field], T])(implicit sfu: SFU): RequestContext ⇒ Future[T] = { ctx ⇒
|
||||||
import ctx.executionContext
|
import ctx.executionContext
|
||||||
sfu(ctx.request.entity).fast.flatMap(form ⇒ fu(form field fieldName))
|
sfu(ctx.request.entity).fast.flatMap(form ⇒ fu(form field fieldName))
|
||||||
|
|
@ -78,21 +78,21 @@ object FormFieldDirectives extends FormFieldDirectives {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
implicit def forString(implicit sfu: SFU, fu: FSFFU[String]) =
|
implicit def forString(implicit sfu: SFU, fu: FSFFU[String]): FieldDefAux[String, Directive1[String]] =
|
||||||
extractField[String, String] { fieldName ⇒ filter(fieldName, fu) }
|
extractField[String, String] { fieldName ⇒ filter(fieldName, fu) }
|
||||||
implicit def forSymbol(implicit sfu: SFU, fu: FSFFU[String]) =
|
implicit def forSymbol(implicit sfu: SFU, fu: FSFFU[String]): FieldDefAux[Symbol, Directive1[String]] =
|
||||||
extractField[Symbol, String] { symbol ⇒ filter(symbol.name, fu) }
|
extractField[Symbol, String] { symbol ⇒ filter(symbol.name, fu) }
|
||||||
implicit def forNR[T](implicit sfu: SFU, fu: FSFFU[T]) =
|
implicit def forNR[T](implicit sfu: SFU, fu: FSFFU[T]): FieldDefAux[NameReceptacle[T], Directive1[T]] =
|
||||||
extractField[NameReceptacle[T], T] { nr ⇒ filter(nr.name, fu) }
|
extractField[NameReceptacle[T], T] { nr ⇒ filter(nr.name, fu) }
|
||||||
implicit def forNUR[T](implicit sfu: SFU) =
|
implicit def forNUR[T](implicit sfu: SFU): FieldDefAux[NameUnmarshallerReceptacle[T], Directive1[T]] =
|
||||||
extractField[NameUnmarshallerReceptacle[T], T] { nr ⇒ filter(nr.name, StrictForm.Field.unmarshallerFromFSU(nr.um)) }
|
extractField[NameUnmarshallerReceptacle[T], T] { nr ⇒ filter(nr.name, StrictForm.Field.unmarshallerFromFSU(nr.um)) }
|
||||||
implicit def forNOR[T](implicit sfu: SFU, fu: FSFFOU[T]) =
|
implicit def forNOR[T](implicit sfu: SFU, fu: FSFFOU[T]): FieldDefAux[NameOptionReceptacle[T], Directive1[Option[T]]] =
|
||||||
extractField[NameOptionReceptacle[T], Option[T]] { nr ⇒ filter[Option[T]](nr.name, fu) }
|
extractField[NameOptionReceptacle[T], Option[T]] { nr ⇒ filter[Option[T]](nr.name, fu) }
|
||||||
implicit def forNDR[T](implicit sfu: SFU, fu: FSFFOU[T]) =
|
implicit def forNDR[T](implicit sfu: SFU, fu: FSFFOU[T]): FieldDefAux[NameDefaultReceptacle[T], Directive1[T]] =
|
||||||
extractField[NameDefaultReceptacle[T], T] { nr ⇒ filter(nr.name, fu withDefaultValue nr.default) }
|
extractField[NameDefaultReceptacle[T], T] { nr ⇒ filter(nr.name, fu withDefaultValue nr.default) }
|
||||||
implicit def forNOUR[T](implicit sfu: SFU) =
|
implicit def forNOUR[T](implicit sfu: SFU): FieldDefAux[NameOptionUnmarshallerReceptacle[T], Directive1[Option[T]]] =
|
||||||
extractField[NameOptionUnmarshallerReceptacle[T], Option[T]] { nr ⇒ filter[Option[T]](nr.name, StrictForm.Field.unmarshallerFromFSU(nr.um): FSFFOU[T]) }
|
extractField[NameOptionUnmarshallerReceptacle[T], Option[T]] { nr ⇒ filter[Option[T]](nr.name, StrictForm.Field.unmarshallerFromFSU(nr.um): FSFFOU[T]) }
|
||||||
implicit def forNDUR[T](implicit sfu: SFU) =
|
implicit def forNDUR[T](implicit sfu: SFU): FieldDefAux[NameDefaultUnmarshallerReceptacle[T], Directive1[T]] =
|
||||||
extractField[NameDefaultUnmarshallerReceptacle[T], T] { nr ⇒ filter(nr.name, (StrictForm.Field.unmarshallerFromFSU(nr.um): FSFFOU[T]) withDefaultValue nr.default) }
|
extractField[NameDefaultUnmarshallerReceptacle[T], T] { nr ⇒ filter(nr.name, (StrictForm.Field.unmarshallerFromFSU(nr.um): FSFFOU[T]) withDefaultValue nr.default) }
|
||||||
|
|
||||||
//////////////////// required formField support ////////////////////
|
//////////////////// required formField support ////////////////////
|
||||||
|
|
@ -105,9 +105,9 @@ object FormFieldDirectives extends FormFieldDirectives {
|
||||||
case _ ⇒ reject
|
case _ ⇒ reject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
implicit def forRVR[T](implicit sfu: SFU, fu: FSFFU[T]) =
|
implicit def forRVR[T](implicit sfu: SFU, fu: FSFFU[T]): FieldDefAux[RequiredValueReceptacle[T], Directive0] =
|
||||||
fieldDef[RequiredValueReceptacle[T], Directive0] { rvr ⇒ requiredFilter(rvr.name, fu, rvr.requiredValue) }
|
fieldDef[RequiredValueReceptacle[T], Directive0] { rvr ⇒ requiredFilter(rvr.name, fu, rvr.requiredValue) }
|
||||||
implicit def forRVDR[T](implicit sfu: SFU) =
|
implicit def forRVDR[T](implicit sfu: SFU): FieldDefAux[RequiredValueUnmarshallerReceptacle[T], Directive0] =
|
||||||
fieldDef[RequiredValueUnmarshallerReceptacle[T], Directive0] { rvr ⇒ requiredFilter(rvr.name, StrictForm.Field.unmarshallerFromFSU(rvr.um), rvr.requiredValue) }
|
fieldDef[RequiredValueUnmarshallerReceptacle[T], Directive0] { rvr ⇒ requiredFilter(rvr.name, StrictForm.Field.unmarshallerFromFSU(rvr.um), rvr.requiredValue) }
|
||||||
|
|
||||||
//////////////////// tuple support ////////////////////
|
//////////////////// tuple support ////////////////////
|
||||||
|
|
@ -115,11 +115,11 @@ object FormFieldDirectives extends FormFieldDirectives {
|
||||||
import akka.http.scaladsl.server.util.TupleOps._
|
import akka.http.scaladsl.server.util.TupleOps._
|
||||||
import akka.http.scaladsl.server.util.BinaryPolyFunc
|
import akka.http.scaladsl.server.util.BinaryPolyFunc
|
||||||
|
|
||||||
implicit def forTuple[T](implicit fold: FoldLeft[Directive0, T, ConvertParamDefAndConcatenate.type]) =
|
implicit def forTuple[T](implicit fold: FoldLeft[Directive0, T, ConvertParamDefAndConcatenate.type]): FieldDefAux[T, fold.Out] =
|
||||||
fieldDef[T, fold.Out](fold(pass, _))
|
fieldDef[T, fold.Out](fold(pass, _))
|
||||||
|
|
||||||
object ConvertParamDefAndConcatenate extends BinaryPolyFunc {
|
object ConvertParamDefAndConcatenate extends BinaryPolyFunc {
|
||||||
implicit def from[P, TA, TB](implicit fdef: FieldDef[P] { type Out = Directive[TB] }, ev: Join[TA, TB]) =
|
implicit def from[P, TA, TB](implicit fdef: FieldDefAux[P, Directive[TB]], ev: Join[TA, TB]) =
|
||||||
at[Directive[TA], P] { (a, t) ⇒ a & fdef(t) }
|
at[Directive[TA], P] { (a, t) ⇒ a & fdef(t) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -59,19 +59,20 @@ object ParameterDirectives extends ParameterDirectives {
|
||||||
def apply(): Out
|
def apply(): Out
|
||||||
}
|
}
|
||||||
object ParamMagnet {
|
object ParamMagnet {
|
||||||
implicit def apply[T](value: T)(implicit pdef: ParamDef[T]) =
|
implicit def apply[T](value: T)(implicit pdef: ParamDef[T]): ParamMagnet { type Out = pdef.Out } =
|
||||||
new ParamMagnet {
|
new ParamMagnet {
|
||||||
type Out = pdef.Out
|
type Out = pdef.Out
|
||||||
def apply() = pdef(value)
|
def apply() = pdef(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ParamDefAux[T, U] = ParamDef[T] { type Out = U }
|
||||||
sealed trait ParamDef[T] {
|
sealed trait ParamDef[T] {
|
||||||
type Out
|
type Out
|
||||||
def apply(value: T): Out
|
def apply(value: T): Out
|
||||||
}
|
}
|
||||||
object ParamDef {
|
object ParamDef {
|
||||||
def paramDef[A, B](f: A ⇒ B) =
|
def paramDef[A, B](f: A ⇒ B): ParamDefAux[A, B] =
|
||||||
new ParamDef[A] {
|
new ParamDef[A] {
|
||||||
type Out = B
|
type Out = B
|
||||||
def apply(value: A) = f(value)
|
def apply(value: A) = f(value)
|
||||||
|
|
@ -85,7 +86,7 @@ object ParameterDirectives extends ParameterDirectives {
|
||||||
|
|
||||||
//////////////////// "regular" parameter extraction //////////////////////
|
//////////////////// "regular" parameter extraction //////////////////////
|
||||||
|
|
||||||
private def extractParameter[A, B](f: A ⇒ Directive1[B]) = paramDef(f)
|
private def extractParameter[A, B](f: A ⇒ Directive1[B]): ParamDefAux[A, Directive1[B]] = paramDef(f)
|
||||||
private def filter[T](paramName: String, fsou: FSOU[T]): Directive1[T] =
|
private def filter[T](paramName: String, fsou: FSOU[T]): Directive1[T] =
|
||||||
extractRequestContext flatMap { ctx ⇒
|
extractRequestContext flatMap { ctx ⇒
|
||||||
import ctx.executionContext
|
import ctx.executionContext
|
||||||
|
|
@ -95,21 +96,21 @@ object ParameterDirectives extends ParameterDirectives {
|
||||||
case Failure(x) ⇒ reject(MalformedQueryParamRejection(paramName, x.getMessage.nullAsEmpty, Option(x.getCause)))
|
case Failure(x) ⇒ reject(MalformedQueryParamRejection(paramName, x.getMessage.nullAsEmpty, Option(x.getCause)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
implicit def forString(implicit fsu: FSU[String]) =
|
implicit def forString(implicit fsu: FSU[String]): ParamDefAux[String, Directive1[String]] =
|
||||||
extractParameter[String, String] { string ⇒ filter(string, fsu) }
|
extractParameter[String, String] { string ⇒ filter(string, fsu) }
|
||||||
implicit def forSymbol(implicit fsu: FSU[String]) =
|
implicit def forSymbol(implicit fsu: FSU[String]): ParamDefAux[Symbol, Directive1[String]] =
|
||||||
extractParameter[Symbol, String] { symbol ⇒ filter(symbol.name, fsu) }
|
extractParameter[Symbol, String] { symbol ⇒ filter(symbol.name, fsu) }
|
||||||
implicit def forNR[T](implicit fsu: FSU[T]) =
|
implicit def forNR[T](implicit fsu: FSU[T]): ParamDefAux[NameReceptacle[T], Directive1[T]] =
|
||||||
extractParameter[NameReceptacle[T], T] { nr ⇒ filter(nr.name, fsu) }
|
extractParameter[NameReceptacle[T], T] { nr ⇒ filter(nr.name, fsu) }
|
||||||
implicit def forNUR[T] =
|
implicit def forNUR[T]: ParamDefAux[NameUnmarshallerReceptacle[T], Directive1[T]] =
|
||||||
extractParameter[NameUnmarshallerReceptacle[T], T] { nr ⇒ filter(nr.name, nr.um) }
|
extractParameter[NameUnmarshallerReceptacle[T], T] { nr ⇒ filter(nr.name, nr.um) }
|
||||||
implicit def forNOR[T](implicit fsou: FSOU[T]) =
|
implicit def forNOR[T](implicit fsou: FSOU[T]): ParamDefAux[NameOptionReceptacle[T], Directive1[Option[T]]] =
|
||||||
extractParameter[NameOptionReceptacle[T], Option[T]] { nr ⇒ filter[Option[T]](nr.name, fsou) }
|
extractParameter[NameOptionReceptacle[T], Option[T]] { nr ⇒ filter[Option[T]](nr.name, fsou) }
|
||||||
implicit def forNDR[T](implicit fsou: FSOU[T]) =
|
implicit def forNDR[T](implicit fsou: FSOU[T]): ParamDefAux[NameDefaultReceptacle[T], Directive1[T]] =
|
||||||
extractParameter[NameDefaultReceptacle[T], T] { nr ⇒ filter[T](nr.name, fsou withDefaultValue nr.default) }
|
extractParameter[NameDefaultReceptacle[T], T] { nr ⇒ filter[T](nr.name, fsou withDefaultValue nr.default) }
|
||||||
implicit def forNOUR[T] =
|
implicit def forNOUR[T]: ParamDefAux[NameOptionUnmarshallerReceptacle[T], Directive1[Option[T]]] =
|
||||||
extractParameter[NameOptionUnmarshallerReceptacle[T], Option[T]] { nr ⇒ filter(nr.name, nr.um: FSOU[T]) }
|
extractParameter[NameOptionUnmarshallerReceptacle[T], Option[T]] { nr ⇒ filter(nr.name, nr.um: FSOU[T]) }
|
||||||
implicit def forNDUR[T] =
|
implicit def forNDUR[T]: ParamDefAux[NameDefaultUnmarshallerReceptacle[T], Directive1[T]] =
|
||||||
extractParameter[NameDefaultUnmarshallerReceptacle[T], T] { nr ⇒ filter[T](nr.name, (nr.um: FSOU[T]) withDefaultValue nr.default) }
|
extractParameter[NameDefaultUnmarshallerReceptacle[T], T] { nr ⇒ filter[T](nr.name, (nr.um: FSOU[T]) withDefaultValue nr.default) }
|
||||||
|
|
||||||
//////////////////// required parameter support ////////////////////
|
//////////////////// required parameter support ////////////////////
|
||||||
|
|
@ -122,9 +123,9 @@ object ParameterDirectives extends ParameterDirectives {
|
||||||
case _ ⇒ reject
|
case _ ⇒ reject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
implicit def forRVR[T](implicit fsu: FSU[T]) =
|
implicit def forRVR[T](implicit fsu: FSU[T]): ParamDefAux[RequiredValueReceptacle[T], Directive0] =
|
||||||
paramDef[RequiredValueReceptacle[T], Directive0] { rvr ⇒ requiredFilter(rvr.name, fsu, rvr.requiredValue) }
|
paramDef[RequiredValueReceptacle[T], Directive0] { rvr ⇒ requiredFilter(rvr.name, fsu, rvr.requiredValue) }
|
||||||
implicit def forRVDR[T] =
|
implicit def forRVDR[T]: ParamDefAux[RequiredValueUnmarshallerReceptacle[T], Directive0] =
|
||||||
paramDef[RequiredValueUnmarshallerReceptacle[T], Directive0] { rvr ⇒ requiredFilter(rvr.name, rvr.um, rvr.requiredValue) }
|
paramDef[RequiredValueUnmarshallerReceptacle[T], Directive0] { rvr ⇒ requiredFilter(rvr.name, rvr.um, rvr.requiredValue) }
|
||||||
|
|
||||||
//////////////////// tuple support ////////////////////
|
//////////////////// tuple support ////////////////////
|
||||||
|
|
@ -132,7 +133,7 @@ object ParameterDirectives extends ParameterDirectives {
|
||||||
import akka.http.scaladsl.server.util.TupleOps._
|
import akka.http.scaladsl.server.util.TupleOps._
|
||||||
import akka.http.scaladsl.server.util.BinaryPolyFunc
|
import akka.http.scaladsl.server.util.BinaryPolyFunc
|
||||||
|
|
||||||
implicit def forTuple[T](implicit fold: FoldLeft[Directive0, T, ConvertParamDefAndConcatenate.type]) =
|
implicit def forTuple[T](implicit fold: FoldLeft[Directive0, T, ConvertParamDefAndConcatenate.type]): ParamDefAux[T, fold.Out] =
|
||||||
paramDef[T, fold.Out](fold(BasicDirectives.pass, _))
|
paramDef[T, fold.Out](fold(BasicDirectives.pass, _))
|
||||||
|
|
||||||
object ConvertParamDefAndConcatenate extends BinaryPolyFunc {
|
object ConvertParamDefAndConcatenate extends BinaryPolyFunc {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue