Skip to content

Commit

Permalink
Merge pull request #64 from http4s/topic/reach-for-async
Browse files Browse the repository at this point in the history
Deprecate `Priority`
  • Loading branch information
armanbilge authored Apr 1, 2022
2 parents b8e66c3 + 826ae87 commit c2a728c
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ import cats.effect.kernel.Async
import cats.effect.kernel.Sync

private[crypto] trait CryptoCompanionPlatform {
implicit def forAsyncOrSync[F[_]](implicit F: Priority[Async[F], Sync[F]]): Crypto[F] =

@deprecated("Preserved for bincompat", "0.2.3")
def forAsyncOrSync[F[_]](implicit F: Priority[Async[F], Sync[F]]): Crypto[F] =
forSync(F.join)

implicit def forSync[F[_]](implicit F: Sync[F]): Crypto[F] =
new UnsealedCrypto[F] {
override def hash: Hash[F] = Hash[F]
override def hmac: Hmac[F] = Hmac[F]
Expand Down
19 changes: 12 additions & 7 deletions crypto/js/src/main/scala/org/http4s/crypto/HashPlatform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,33 @@

package org.http4s.crypto

import cats.ApplicativeThrow
import cats.MonadThrow
import cats.effect.kernel.Async
import cats.syntax.all._
import scodec.bits.ByteVector

private[crypto] trait HashCompanionPlatform {
implicit def forAsyncOrMonadThrow[F[_]](
implicit F: Priority[Async[F], MonadThrow[F]]): Hash[F] =
@deprecated("Preserved for bincompat", "0.2.3")
def forAsyncOrMonadThrow[F[_]](implicit F: Priority[Async[F], MonadThrow[F]]): Hash[F] =
forApplicativeThrow(F.join)

implicit def forApplicativeThrow[F[_]](implicit F: ApplicativeThrow[F]): Hash[F] =
if (facade.isNodeJSRuntime)
new UnsealedHash[F] {
override def digest(algorithm: HashAlgorithm, data: ByteVector): F[ByteVector] =
F.join[MonadThrow[F]].catchNonFatal {
F.catchNonFatal {
val hash = facade.node.crypto.createHash(algorithm.toStringNodeJS)
hash.update(data.toUint8Array)
ByteVector.view(hash.digest())
}
}
else
F.getPreferred
.map { implicit F: Async[F] =>
Some(F)
.collect { case f: Async[F] => f }
.fold(
throw new UnsupportedOperationException("Hash[F] on browsers requires Async[F]")
) { implicit F: Async[F] =>
new UnsealedHash[F] {
import facade.browser._
override def digest(algorithm: HashAlgorithm, data: ByteVector): F[ByteVector] =
Expand All @@ -44,7 +51,5 @@ private[crypto] trait HashCompanionPlatform {
.map(ByteVector.view)
}
}
.getOrElse(throw new UnsupportedOperationException(
"Hash[F] on browsers requires Async[F]"))

}
53 changes: 30 additions & 23 deletions crypto/js/src/main/scala/org/http4s/crypto/HmacKeyGenPlatform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,36 +24,45 @@ import scodec.bits.ByteVector
import scala.scalajs.js

private[crypto] trait HmacKeyGenCompanionPlatform {
implicit def forAsyncOrSync[F[_]](implicit F0: Priority[Async[F], Sync[F]]): HmacKeyGen[F] =
@deprecated("Preserved for bincompat", "0.2.3")
def forAsyncOrSync[F[_]](implicit F0: Priority[Async[F], Sync[F]]): HmacKeyGen[F] =
forSync(F0.join)

implicit def forSync[F[_]](implicit F: Sync[F]): HmacKeyGen[F] =
if (facade.isNodeJSRuntime)
new UnsealedHmacKeyGen[F] {
import facade.node._

override def generateKey[A <: HmacAlgorithm](algorithm: A): F[SecretKey[A]] =
F0.fold { F =>
F.async_[SecretKey[A]] { cb =>
crypto.generateKey(
"hmac",
GenerateKeyOptions(algorithm.minimumKeyLength),
(err, key) =>
cb(
Option(err)
.map(js.JavaScriptException)
.toLeft(SecretKeySpec(ByteVector.view(key.`export`()), algorithm)))
)
}
} { F =>
F.delay {
val key =
crypto.generateKeySync("hmac", GenerateKeyOptions(algorithm.minimumKeyLength))
SecretKeySpec(ByteVector.view(key.`export`()), algorithm)
Some(F)
.collect { case f: Async[F] => f }
.fold {
F.delay[SecretKey[A]] {
val key =
crypto.generateKeySync("hmac", GenerateKeyOptions(algorithm.minimumKeyLength))
SecretKeySpec(ByteVector.view(key.`export`()), algorithm)
}
} { F =>
F.async_[SecretKey[A]] { cb =>
crypto.generateKey(
"hmac",
GenerateKeyOptions(algorithm.minimumKeyLength),
(err, key) =>
cb(
Option(err)
.map(js.JavaScriptException)
.toLeft(SecretKeySpec(ByteVector.view(key.`export`()), algorithm)))
)
}
}
}

}
else
F0.getPreferred
.map { implicit F: Async[F] =>
Some(F)
.collect { case f: Async[F] => f }
.fold(
throw new UnsupportedOperationException("HmacKeyGen[F] on browsers requires Async[F]")
) { implicit F =>
new UnsealedHmacKeyGen[F] {
import facade.browser._
override def generateKey[A <: HmacAlgorithm](algorithm: A): F[SecretKey[A]] =
Expand All @@ -70,7 +79,5 @@ private[crypto] trait HmacKeyGenCompanionPlatform {
} yield SecretKeySpec(ByteVector.view(exported), algorithm)
}
}
.getOrElse(throw new UnsupportedOperationException(
"HmacKeyGen[F] on browsers requires Async[F]"))

}
18 changes: 11 additions & 7 deletions crypto/js/src/main/scala/org/http4s/crypto/HmacPlatform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@ import scala.scalajs.js
private[crypto] trait HmacPlatform[F[_]]

private[crypto] trait HmacCompanionPlatform {
implicit def forAsyncOrApplicativeThrow[F[_]](

@deprecated("Preserved for bincompat", "0.2.3")
def forAsyncOrApplicativeThrow[F[_]](
implicit F0: Priority[Async[F], ApplicativeThrow[F]]): Hmac[F] =
forApplicativeThrow(F0.join)

implicit def forApplicativeThrow[F[_]](implicit F: ApplicativeThrow[F]): Hmac[F] =
if (facade.isNodeJSRuntime)
new UnsealedHmac[F] {
import facade.node._
implicit val F: ApplicativeThrow[F] = F0.join[ApplicativeThrow[F]]

override def digest(key: SecretKey[HmacAlgorithm], data: ByteVector): F[ByteVector] =
key match {
Expand All @@ -51,8 +55,11 @@ private[crypto] trait HmacCompanionPlatform {

}
else
F0.getPreferred
.map { implicit F: Async[F] =>
Some(F)
.collect { case f: Async[F] => f }
.fold(
throw new UnsupportedOperationException("Hmac[F] on browsers requires Async[F]")
) { implicit F: Async[F] =>
new UnsealedHmac[F] {
import facade.browser._
override def digest(
Expand Down Expand Up @@ -82,7 +89,4 @@ private[crypto] trait HmacCompanionPlatform {
F.pure(SecretKeySpec(key, algorithm))
}
}
.getOrElse(throw new UnsupportedOperationException(
"Hmac[F] on browsers requires Async[F]"))

}
7 changes: 5 additions & 2 deletions crypto/js/src/main/scala/org/http4s/crypto/Priority.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ package org.http4s.crypto
* This type can be useful for problems where multiple algorithms can be used, depending on the
* type classes available.
*/
@deprecated("Unneeded when P and F belong to the same hiearchy", "0.2.3")
private[http4s] sealed trait Priority[+P, +F] {

import Priority.{Fallback, Preferred}
Expand Down Expand Up @@ -70,11 +71,13 @@ private[http4s] object Priority extends FindPreferred {
}

private[crypto] trait FindPreferred extends FindFallback {
implicit def preferred[P](implicit ev: P): Priority[P, Nothing] =
@deprecated("Priority is deprecated", "0.2.3")
def preferred[P](implicit ev: P): Priority[P, Nothing] =
Priority.Preferred(ev)
}

private[crypto] trait FindFallback {
implicit def fallback[F](implicit ev: F): Priority[Nothing, F] =
@deprecated("Priority is deprecated", "0.2.3")
def fallback[F](implicit ev: F): Priority[Nothing, F] =
Priority.Fallback(ev)
}

0 comments on commit c2a728c

Please sign in to comment.