mirror of
https://github.com/fluencelabs/codec
synced 2025-04-25 14:52:14 +00:00
Sbt js modules refactoring (#70)
* replace codec/core and rename jvm-js modules * add files to git * add info into test
This commit is contained in:
parent
00b8a4af23
commit
2db276ce63
94
core/src/main/scala/fluence/codec/Codec.scala
Normal file
94
core/src/main/scala/fluence/codec/Codec.scala
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Fluence Labs Limited
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package fluence.codec
|
||||||
|
|
||||||
|
import cats.data.Kleisli
|
||||||
|
import cats.{ Applicative, ApplicativeError, FlatMap, Traverse }
|
||||||
|
import cats.syntax.applicative._
|
||||||
|
import scodec.bits.ByteVector
|
||||||
|
|
||||||
|
import scala.language.{ higherKinds, implicitConversions }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base trait for serialize/deserialize objects.
|
||||||
|
*
|
||||||
|
* @tparam A The type of plain object representation
|
||||||
|
* @tparam B The type of binary representation
|
||||||
|
* @tparam F Encoding/decoding effect
|
||||||
|
*/
|
||||||
|
final case class Codec[F[_], A, B](encode: A ⇒ F[B], decode: B ⇒ F[A]) {
|
||||||
|
self ⇒
|
||||||
|
|
||||||
|
implicit val direct: Kleisli[F, A, B] = Kleisli(encode)
|
||||||
|
|
||||||
|
implicit val inverse: Kleisli[F, B, A] = Kleisli(decode)
|
||||||
|
|
||||||
|
def andThen[C](other: Codec[F, B, C])(implicit F: FlatMap[F]): Codec[F, A, C] =
|
||||||
|
Codec((self.direct andThen other.direct).run, (other.inverse andThen self.inverse).run)
|
||||||
|
|
||||||
|
def compose[C](other: Codec[F, C, A])(implicit F: FlatMap[F]): Codec[F, C, B] =
|
||||||
|
Codec((other.direct andThen self.direct).run, (self.inverse andThen other.inverse).run)
|
||||||
|
|
||||||
|
def swap: Codec[F, B, A] = Codec(decode, encode)
|
||||||
|
}
|
||||||
|
|
||||||
|
object Codec {
|
||||||
|
implicit def identityCodec[F[_] : Applicative, T]: Codec[F, T, T] =
|
||||||
|
Codec(_.pure[F], _.pure[F])
|
||||||
|
|
||||||
|
implicit def traverseCodec[F[_] : Applicative, G[_] : Traverse, O, B](implicit codec: Codec[F, O, B]): Codec[F, G[O], G[B]] =
|
||||||
|
Codec[F, G[O], G[B]](Traverse[G].traverse[F, O, B](_)(codec.encode), Traverse[G].traverse[F, B, O](_)(codec.decode))
|
||||||
|
|
||||||
|
implicit def toDirect[F[_], A, B](implicit cod: Codec[F, A, B]): Kleisli[F, A, B] =
|
||||||
|
cod.direct
|
||||||
|
|
||||||
|
implicit def toInverse[F[_], A, B](implicit cod: Codec[F, A, B]): Kleisli[F, B, A] =
|
||||||
|
cod.inverse
|
||||||
|
|
||||||
|
implicit def swap[F[_], A, B](implicit cod: Codec[F, A, B]): Codec[F, B, A] =
|
||||||
|
Codec[F, B, A](cod.decode, cod.encode)
|
||||||
|
|
||||||
|
implicit def byteVectorArray[F[_] : Applicative]: Codec[F, Array[Byte], ByteVector] =
|
||||||
|
pure(ByteVector.apply, _.toArray)
|
||||||
|
|
||||||
|
// TODO: descriptive error
|
||||||
|
implicit def byteVectorB64[F[_]](implicit F: ApplicativeError[F, Throwable]): Codec[F, String, ByteVector] =
|
||||||
|
Codec(
|
||||||
|
str ⇒
|
||||||
|
ByteVector.fromBase64(str).fold[F[ByteVector]](
|
||||||
|
F.raiseError(new IllegalArgumentException(s"Given string is not valid b64: $str"))
|
||||||
|
)(_.pure[F]),
|
||||||
|
|
||||||
|
_.toBase64.pure[F]
|
||||||
|
)
|
||||||
|
|
||||||
|
def codec[F[_], O, B](implicit codec: Codec[F, O, B]): Codec[F, O, B] = codec
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Codec from pure encode/decode functions and an Applicative
|
||||||
|
*
|
||||||
|
* @param encodeFn Encode function that never fail
|
||||||
|
* @param decodeFn Decode function that never fail
|
||||||
|
* @tparam F Applicative effect
|
||||||
|
* @tparam O Raw type
|
||||||
|
* @tparam B Encoded type
|
||||||
|
* @return New codec for O and B
|
||||||
|
*/
|
||||||
|
def pure[F[_] : Applicative, O, B](encodeFn: O ⇒ B, decodeFn: B ⇒ O): Codec[F, O, B] =
|
||||||
|
Codec(encodeFn(_).pure[F], decodeFn(_).pure[F])
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user