Functor and Contravariant typeclasses for CryptoHasher (#80)

This commit is contained in:
Dmitry Kurinskiy 2018-03-10 15:50:45 +01:00 committed by Constantine Solovev
parent 37fa5ac62c
commit a7576f548b
2 changed files with 48 additions and 17 deletions

View File

@ -24,26 +24,17 @@ import scala.scalajs.js.JSConverters._
object JsCryptoHasher {
lazy val Sha256: CryptoHasher.Bytes = new CryptoHasher[Array[Byte], Array[Byte]] {
override def hash(msg1: Array[Byte]): Array[Byte] = {
lazy val Sha256: CryptoHasher.Bytes =
CryptoHasher.buildM[Array[Byte], Array[Byte]]{ msg
val sha256 = new SHA256()
sha256.update(msg1.toJSArray)
sha256.update(msg.toJSArray)
ByteVector.fromValidHex(sha256.digest("hex")).toArray
}
override def hash(msg1: Array[Byte], msg2: Array[Byte]*): Array[Byte] = {
hash(msg1 ++ msg2.flatten)
}
}
}(_ ++ _)
lazy val Sha1: CryptoHasher.Bytes = new CryptoHasher[Array[Byte], Array[Byte]] {
override def hash(msg1: Array[Byte]): Array[Byte] = {
lazy val Sha1: CryptoHasher.Bytes =
CryptoHasher.buildM[Array[Byte], Array[Byte]]{ msg
val sha1 = new SHA1()
sha1.update(msg1.toJSArray)
sha1.update(msg.toJSArray)
ByteVector.fromValidHex(sha1.digest("hex")).toArray
}
override def hash(msg1: Array[Byte], msg2: Array[Byte]*): Array[Byte] = {
hash(msg1 ++ msg2.flatten)
}
}
}(_ ++ _)
}

View File

@ -17,20 +17,60 @@
package fluence.crypto.hash
import cats.kernel.Semigroup
import cats.{ Contravariant, Functor, Monoid, Traverse }
import scala.language.{ higherKinds, reflectiveCalls }
/**
* TODO add F[_] effect
* Base interface for hashing.
*
* @tparam M type of message for hashing
* @tparam H type of hashed message
*/
trait CryptoHasher[M, H] {
self
def hash(msg: M): H
def hash(msg1: M, msgN: M*): H
def hashM[F[_] : Traverse](ms: F[M])(implicit M: Monoid[M]): H =
hash(Traverse[F].fold(ms))
final def map[B](f: H B): CryptoHasher[M, B] = new CryptoHasher[M, B] {
override def hash(msg: M): B = f(self.hash(msg))
override def hash(msg1: M, msgN: M*): B = f(self.hash(msg1, msgN: _*))
}
final def contramap[N](f: N M): CryptoHasher[N, H] = new CryptoHasher[N, H] {
override def hash(msg: N): H = self.hash(f(msg))
override def hash(msg1: N, msgN: N*): H = self.hash(f(msg1), msgN.map(f): _*)
}
}
object CryptoHasher {
type Bytes = CryptoHasher[Array[Byte], Array[Byte]]
def buildM[M : Semigroup, H](h: M H): CryptoHasher[M, H] = new CryptoHasher[M, H] {
override def hash(msg: M): H = h(msg)
override def hash(msg1: M, msgN: M*): H = h(msgN.foldLeft(msg1)(Semigroup[M].combine))
}
implicit def cryptoHasherFunctor[M]: Functor[({ type λ[α] = CryptoHasher[M, α] })#λ] =
new Functor[({ type λ[α] = CryptoHasher[M, α] })#λ] {
override def map[A, B](fa: CryptoHasher[M, A])(f: A B): CryptoHasher[M, B] =
fa.map(f)
}
implicit def cryptoHasherContravariant[H]: Contravariant[({ type λ[α] = CryptoHasher[α, H] })#λ] =
new Contravariant[({ type λ[α] = CryptoHasher[α, H] })#λ] {
override def contramap[A, B](fa: CryptoHasher[A, H])(f: B A): CryptoHasher[B, H] =
fa.contramap(f)
}
}