Skip to content

Commit

Permalink
Least powerful type classes + Endpoint.mapF (#1089)
Browse files Browse the repository at this point in the history
* Least powerful type classes + Endpoint.mapF

* Fix compilation

* Add mapF scaladoc

* Rename mapF to transformF
  • Loading branch information
sergeykolbasov authored Feb 26, 2019
1 parent 14e2cd6 commit 21b143b
Show file tree
Hide file tree
Showing 18 changed files with 175 additions and 147 deletions.
100 changes: 59 additions & 41 deletions core/src/main/scala/io/finch/Endpoint.scala

Large diffs are not rendered by default.

80 changes: 40 additions & 40 deletions core/src/main/scala/io/finch/EndpointModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package io.finch

import cats.Applicative
import cats.data.NonEmptyList
import cats.effect.{ContextShift, Effect, Resource, Sync}
import cats.effect.{ContextShift, Resource, Sync}
import com.twitter.finagle.http.{Cookie, Request}
import com.twitter.finagle.http.exp.Multipart
import com.twitter.io.Buf
Expand Down Expand Up @@ -99,34 +99,34 @@ trait EndpointModule[F[_]] {
* An alias for [[Endpoint.fromInputStream]].
*/
def fromInputStream(stream: Resource[F, InputStream])(
implicit F: Effect[F], S: ContextShift[F]
implicit F: Sync[F], S: ContextShift[F]
): Endpoint[F, Buf] =
Endpoint.fromInputStream[F](stream)

/**
* An alias for [[Endpoint.fromFile]].
*/
def fromFile(file: File)(
implicit F: Effect[F], S: ContextShift[F]
implicit F: Sync[F], S: ContextShift[F]
): Endpoint[F, Buf] =
Endpoint.fromFile[F](file)

/**
* An alias for [[Endpoint.classpathAsset]].
*/
def classpathAsset(path: String)(implicit F: Effect[F], S: ContextShift[F]): Endpoint[F, Buf] =
def classpathAsset(path: String)(implicit F: Sync[F], S: ContextShift[F]): Endpoint[F, Buf] =
Endpoint.classpathAsset[F](path)

/**
* An alias for [[Endpoint.classpathAsset]].
*/
def filesystemAsset(path: String)(implicit F: Effect[F], S: ContextShift[F]): Endpoint[F, Buf] =
def filesystemAsset(path: String)(implicit F: Sync[F], S: ContextShift[F]): Endpoint[F, Buf] =
Endpoint.filesystemAsset[F](path)

/**
* An alias for [[Endpoint.root]].
*/
def root(implicit F: Effect[F]): Endpoint[F, Request] =
def root(implicit F: Sync[F]): Endpoint[F, Request] =
Endpoint.root[F]

/**
Expand All @@ -144,13 +144,13 @@ trait EndpointModule[F[_]] {
/**
* An alias for [[Endpoint.path]].
*/
def path[A: DecodePath: ClassTag](implicit F: Effect[F]): Endpoint[F, A] =
def path[A: DecodePath: ClassTag](implicit F: Sync[F]): Endpoint[F, A] =
Endpoint.path[F, A]

/**
* An alias for [[Endpoint.paths]].
*/
def paths[A: DecodePath: ClassTag](implicit F: Effect[F]): Endpoint[F, List[A]] =
def paths[A: DecodePath: ClassTag](implicit F: Sync[F]): Endpoint[F, List[A]] =
Endpoint.paths[F, A]

/**
Expand All @@ -159,7 +159,7 @@ trait EndpointModule[F[_]] {
* @note This method is implicit such that an implicit conversion `String => Endpoint[F, HNil]`
* works.
*/
implicit def path(s: String)(implicit F: Effect[F]): Endpoint[F, HNil] =
implicit def path(s: String)(implicit F: Sync[F]): Endpoint[F, HNil] =
Endpoint.path[F](s)

/**
Expand Down Expand Up @@ -213,96 +213,96 @@ trait EndpointModule[F[_]] {
/**
* An alias for [[Endpoint.header]].
*/
def header[A: DecodeEntity: ClassTag](name: String)(implicit F: Effect[F]): Endpoint[F, A] =
def header[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, A] =
Endpoint.header[F, A](name)

/**
* An alias for [[Endpoint.headerOption]].
*/
def headerOption[A: DecodeEntity: ClassTag](name: String)(implicit F: Effect[F]): Endpoint[F, Option[A]] =
def headerOption[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, Option[A]] =
Endpoint.headerOption[F, A](name)

/**
* An alias for [[Endpoint.binaryBodyOption]].
*/
def binaryBodyOption(implicit F: Effect[F]): Endpoint[F, Option[Array[Byte]]] =
def binaryBodyOption(implicit F: Sync[F]): Endpoint[F, Option[Array[Byte]]] =
Endpoint.binaryBodyOption[F]

/**
* An alias for [[Endpoint.binaryBody]].
*/
def binaryBody(implicit F: Effect[F]): Endpoint[F, Array[Byte]] =
def binaryBody(implicit F: Sync[F]): Endpoint[F, Array[Byte]] =
Endpoint.binaryBody[F]

/**
* An alias for [[Endpoint.stringBodyOption]].
*/
def stringBodyOption(implicit F: Effect[F]): Endpoint[F, Option[String]] =
def stringBodyOption(implicit F: Sync[F]): Endpoint[F, Option[String]] =
Endpoint.stringBodyOption[F]

/**
* An alias for [[Endpoint.stringBody]].
*/
def stringBody(implicit F: Effect[F]): Endpoint[F, String] =
def stringBody(implicit F: Sync[F]): Endpoint[F, String] =
Endpoint.stringBody[F]

/**
* An alias for [[Endpoint.bodyOption]].
*/
def bodyOption[A: ClassTag, CT](implicit F: Effect[F], D: Decode.Dispatchable[A, CT]): Endpoint[F, Option[A]] =
def bodyOption[A: ClassTag, CT](implicit F: Sync[F], D: Decode.Dispatchable[A, CT]): Endpoint[F, Option[A]] =
Endpoint.bodyOption[F, A, CT]

/**
* An alias for [[Endpoint.body]].
*/
def body[A: ClassTag, CT](implicit D: Decode.Dispatchable[A, CT], F: Effect[F]): Endpoint[F, A] =
def body[A: ClassTag, CT](implicit D: Decode.Dispatchable[A, CT], F: Sync[F]): Endpoint[F, A] =
Endpoint.body[F, A, CT]

/**
* An alias for [[Endpoint.jsonBody]].
*/
def jsonBody[A: Decode.Json: ClassTag](implicit F: Effect[F]): Endpoint[F, A] =
def jsonBody[A: Decode.Json: ClassTag](implicit F: Sync[F]): Endpoint[F, A] =
Endpoint.jsonBody[F, A]

/**
* An alias for [[Endpoint.jsonBodyOption]].
*/
def jsonBodyOption[A: Decode.Json: ClassTag](implicit F: Effect[F]): Endpoint[F, Option[A]] =
def jsonBodyOption[A: Decode.Json: ClassTag](implicit F: Sync[F]): Endpoint[F, Option[A]] =
Endpoint.jsonBodyOption[F, A]

/**
* An alias for [[Endpoint.textBody]].
*/
def textBody[A: Decode.Text: ClassTag](implicit F: Effect[F]): Endpoint[F, A] =
def textBody[A: Decode.Text: ClassTag](implicit F: Sync[F]): Endpoint[F, A] =
Endpoint.textBody[F, A]

/**
* An alias for [[Endpoint.textBodyOption]].
*/
def textBodyOption[A: Decode.Text: ClassTag](implicit F: Effect[F]): Endpoint[F, Option[A]] =
def textBodyOption[A: Decode.Text: ClassTag](implicit F: Sync[F]): Endpoint[F, Option[A]] =
Endpoint.textBodyOption[F, A]

/**
* An alias for [[Endpoint.binaryBodyStream]].
*/
def binaryBodyStream[S[_[_], _]](implicit
F: Effect[F],
F: Sync[F],
LR: LiftReader[S, F]
): Endpoint[F, S[F, Array[Byte]]] = Endpoint.binaryBodyStream[F, S]

/**
* An alias for [[Endpoint.stringBodyStream]].
*/
def stringBodyStream[S[_[_], _]](implicit
F: Effect[F],
F: Sync[F],
LR: LiftReader[S, F]
): Endpoint[F, S[F, String]] = Endpoint.stringBodyStream[F, S]

/**
* An alias for [[Endpoint.bodyStream]].
*/
def bodyStream[S[_[_], _], A, CT <: String](implicit
F: Effect[F],
F: Sync[F],
LR: LiftReader[S, F],
A: DecodeStream.Aux[S, F, A, CT]
): Endpoint[F, S[F, A]] = Endpoint.bodyStream[F, S, A, CT]
Expand All @@ -311,7 +311,7 @@ trait EndpointModule[F[_]] {
* An alias for [[Endpoint.jsonBodyStream]].
*/
def jsonBodyStream[S[_[_], _], A](implicit
F: Effect[F],
F: Sync[F],
LR: LiftReader[S, F],
A: DecodeStream.Aux[S, F, A, Application.Json]
): Endpoint[F, S[F, A]] = Endpoint.jsonBodyStream[F, S, A]
Expand All @@ -320,93 +320,93 @@ trait EndpointModule[F[_]] {
* An alias for [[Endpoint.textBodyStream]].
*/
def textBodyStream[S[_[_], _], A](implicit
F: Effect[F],
F: Sync[F],
LR: LiftReader[S, F],
A: DecodeStream.Aux[S, F, A, Text.Plain]
): Endpoint[F, S[F, A]] = Endpoint.textBodyStream[F, S, A]

/**
* An alias for [[Endpoint.cookieOption]].
*/
def cookieOption(name: String)(implicit F: Effect[F]): Endpoint[F, Option[Cookie]] =
def cookieOption(name: String)(implicit F: Sync[F]): Endpoint[F, Option[Cookie]] =
Endpoint.cookieOption[F](name)

/**
* An alias for [[Endpoint.cookie]].
*/
def cookie(name: String)(implicit F: Effect[F]): Endpoint[F, Cookie] =
def cookie(name: String)(implicit F: Sync[F]): Endpoint[F, Cookie] =
Endpoint.cookie[F](name)

/**
* An alias for [[Endpoint.paramOption]].
*/
def paramOption[A: DecodeEntity: ClassTag](name: String)(implicit F: Effect[F]): Endpoint[F, Option[A]] =
def paramOption[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, Option[A]] =
Endpoint.paramOption[F, A](name)

/**
* An alias for [[Endpoint.param]].
*/
def param[A: DecodeEntity: ClassTag](name: String)(implicit F: Effect[F]): Endpoint[F, A] =
def param[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, A] =
Endpoint.param[F, A](name)

/**
* An alias for [[Endpoint.params]].
*/
def params[A: DecodeEntity: ClassTag](name: String)(implicit F: Effect[F]): Endpoint[F, List[A]] =
def params[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, List[A]] =
Endpoint.params[F, A](name)

/**
* An alias for [[Endpoint.paramsNel]].
*/
def paramsNel[A: DecodeEntity: ClassTag](name: String)(implicit F: Effect[F]): Endpoint[F, NonEmptyList[A]] =
def paramsNel[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, NonEmptyList[A]] =
Endpoint.paramsNel[F, A](name)

/**
* An alias for [[Endpoint.multipartFileUploadOption]].
*/
def multipartFileUploadOption(name: String)(implicit F: Effect[F]): Endpoint[F, Option[Multipart.FileUpload]] =
def multipartFileUploadOption(name: String)(implicit F: Sync[F]): Endpoint[F, Option[Multipart.FileUpload]] =
Endpoint.multipartFileUploadOption[F](name)

/**
* An alias for [[Endpoint.multipartFileUpload]].
*/
def multipartFileUpload(name: String)(implicit F: Effect[F]): Endpoint[F, Multipart.FileUpload] =
def multipartFileUpload(name: String)(implicit F: Sync[F]): Endpoint[F, Multipart.FileUpload] =
Endpoint.multipartFileUpload[F](name)

/**
* An alias for [[Endpoint.multipartFileUploads]].
*/
def multipartFileUploads(name: String)(implicit F: Effect[F]): Endpoint[F, List[Multipart.FileUpload]] =
def multipartFileUploads(name: String)(implicit F: Sync[F]): Endpoint[F, List[Multipart.FileUpload]] =
Endpoint.multipartFileUploads[F](name)

/**
* An alias for [[Endpoint.multipartFileUploadsNel]].
*/
def multipartFileUploadsNel(name: String)(implicit F: Effect[F]): Endpoint[F, NonEmptyList[Multipart.FileUpload]] =
def multipartFileUploadsNel(name: String)(implicit F: Sync[F]): Endpoint[F, NonEmptyList[Multipart.FileUpload]] =
Endpoint.multipartFileUploadsNel[F](name)

/**
* An alias for [[Endpoint.multipartAttribute]].
*/
def multipartAttribute[A: DecodeEntity: ClassTag](name: String)(implicit F: Effect[F]): Endpoint[F, A] =
def multipartAttribute[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, A] =
Endpoint.multipartAttribute[F, A](name)

/**
* An alias for [[Endpoint.multipartAttributeOption]].
*/
def multipartAttributeOption[A: DecodeEntity: ClassTag](name: String)(implicit F: Effect[F]): Endpoint[F, Option[A]] =
def multipartAttributeOption[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, Option[A]] =
Endpoint.multipartAttributeOption[F, A](name)

/**
* An alias for [[Endpoint.multipartAttributes]].
*/
def multipartAttributes[A: DecodeEntity: ClassTag](name: String)(implicit F: Effect[F]): Endpoint[F, List[A]] =
def multipartAttributes[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, List[A]] =
Endpoint.multipartAttributes[F, A](name)

/**
* An alias for [[Endpoint.multipartAttributesNel]].
*/
def multipartAttributesNel[A: DecodeEntity: ClassTag](name: String)(implicit F: Effect[F]): Endpoint[F, NonEmptyList[A]] =
def multipartAttributesNel[A: DecodeEntity: ClassTag](name: String)(implicit F: Sync[F]): Endpoint[F, NonEmptyList[A]] =
Endpoint.multipartAttributesNel[F, A](name)
}

Expand Down
18 changes: 9 additions & 9 deletions core/src/main/scala/io/finch/endpoint/body.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.finch.endpoint

import cats.effect.Effect
import cats.effect.Sync
import com.twitter.io.{Buf, Reader}
import io.finch._
import io.finch.internal._
Expand All @@ -10,7 +10,7 @@ import scala.reflect.ClassTag

private[finch] abstract class FullBody[F[_], A] extends Endpoint[F, A] {

protected def F: Effect[F]
protected def F: Sync[F]
protected def missing: F[Output[A]]
protected def present(contentType: String, content: Buf, cs: Charset): F[Output[A]]

Expand Down Expand Up @@ -53,7 +53,7 @@ private[finch] object FullBody {
private[finch] abstract class Body[F[_], A, B, CT](implicit
dd: Decode.Dispatchable[A, CT],
ct: ClassTag[A],
protected val F: Effect[F]
protected val F: Sync[F]
) extends FullBody[F, B] with FullBody.PreparedBody[F, A, B] {

protected def present(contentType: String, content: Buf, cs: Charset): F[Output[B]] =
Expand All @@ -65,7 +65,7 @@ private[finch] abstract class Body[F[_], A, B, CT](implicit
final override def toString: String = "body"
}

private[finch] abstract class BinaryBody[F[_], A](implicit protected val F: Effect[F])
private[finch] abstract class BinaryBody[F[_], A](implicit protected val F: Sync[F])
extends FullBody[F, A] with FullBody.PreparedBody[F, Array[Byte], A] {

protected def present(contentType: String, content: Buf, cs: Charset): F[Output[A]] =
Expand All @@ -74,7 +74,7 @@ private[finch] abstract class BinaryBody[F[_], A](implicit protected val F: Effe
final override def toString: String = "binaryBody"
}

private[finch] abstract class StringBody[F[_], A](implicit protected val F: Effect[F])
private[finch] abstract class StringBody[F[_], A](implicit protected val F: Sync[F])
extends FullBody[F, A]
with FullBody.PreparedBody[F, String, A] {

Expand All @@ -86,7 +86,7 @@ private[finch] abstract class StringBody[F[_], A](implicit protected val F: Effe

private[finch] abstract class ChunkedBody[F[_], S[_[_], _], A] extends Endpoint[F, S[F, A]] {

protected def F: Effect[F]
protected def F: Sync[F]
protected def prepare(r: Reader[Buf], cs: Charset): Output[S[F, A]]

final def apply(input: Input): EndpointResult[F, S[F, A]] =
Expand All @@ -102,7 +102,7 @@ private[finch] abstract class ChunkedBody[F[_], S[_[_], _], A] extends Endpoint[

private[finch] final class BinaryBodyStream[F[_], S[_[_], _]](implicit
LR: LiftReader[S, F],
protected val F: Effect[F]
protected val F: Sync[F]
) extends ChunkedBody[F, S, Array[Byte]] with (Buf => Array[Byte]) {

def apply(buf: Buf): Array[Byte] = buf.asByteArray
Expand All @@ -115,7 +115,7 @@ private[finch] final class BinaryBodyStream[F[_], S[_[_], _]](implicit

private[finch] final class StringBodyStream[F[_], S[_[_], _]](implicit
LR: LiftReader[S, F],
protected val F: Effect[F]
protected val F: Sync[F]
) extends ChunkedBody[F, S, String] with (Buf => String) {

def apply(buf: Buf): String = buf.asString(StandardCharsets.UTF_8)
Expand All @@ -129,7 +129,7 @@ private[finch] final class StringBodyStream[F[_], S[_[_], _]](implicit
}

private[finch] final class BodyStream[F[_], S[_[_], _], A, CT <: String](implicit
protected val F: Effect[F],
protected val F: Sync[F],
LR: LiftReader[S, F],
A: DecodeStream.Aux[S, F, A, CT]
) extends ChunkedBody[F, S, A] {
Expand Down
4 changes: 2 additions & 2 deletions core/src/main/scala/io/finch/endpoint/cookie.scala
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package io.finch.endpoint

import cats.effect.Effect
import cats.effect.Sync
import com.twitter.finagle.http.{Cookie => FinagleCookie}
import io.finch._

private[finch] abstract class Cookie[F[_], A](name: String)(implicit
protected val F: Effect[F]
protected val F: Sync[F]
) extends Endpoint[F, A] {

protected def missing(name: String): F[Output[A]]
Expand Down
Loading

0 comments on commit 21b143b

Please sign in to comment.