summaryrefslogtreecommitdiff
path: root/cask/src/cask/main/Decorators.scala
blob: 91cf92fabe9afbcd5e9261d40eea22f5eaa08ccb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package cask.main

import cask.internal.Router.ArgReader
import cask.model.ParamContext


trait Endpoint[R] extends BaseDecorator{

  val path: String
  val methods: Seq[String]
  def subpath: Boolean = false
  def wrapMethodOutput(ctx: ParamContext,t: R): cask.internal.Router.Result[Any] = {
    cask.internal.Router.Result.Success(t)
  }

  def wrapPathSegment(s: String): Input

}

/**
  * The core interface of decorator annotations: the decorator provides "raw"
  * values to the annotated function via `getRawParams`, which then get
  * processed by `getParamParser` into the correct argument types before
  * being passed to the function.
  *
  * For a trivial "provide value" decorator, `getRawParams` would return the
  * final param value and `getParamParser` would return a no-op parser. For
  * a decorator that takes its input as query-params, JSON, or similar,
  * `getRawParams` would provide raw query/JSON/etc. values and
  * `getParamParser` would be responsible for processing those into the
  * correct parameter types.
  */
trait BaseDecorator{
  type Input
  type InputParser[T] <: ArgReader[Input, T, ParamContext]
  def getRawParams(ctx: ParamContext): Either[cask.model.Response, Map[String, Input]]
  def getParamParser[T](implicit p: InputParser[T]) = p

}

trait Decorator extends BaseDecorator {
  type Input = Any
  type InputParser[T] = NoOpParser[Input, T]
}

class NoOpParser[Input, T] extends ArgReader[Input, T, ParamContext] {
  def arity = 1

  def read(ctx: ParamContext, label: String, input: Input) = input.asInstanceOf[T]
}
object NoOpParser{
  implicit def instance[Input, T] = new NoOpParser[Input, T]
}