diff --git a/protobuf/js/src/main/scala/fluence/codec/Uint8ArrayCodecs.scala b/bits/js/src/main/scala/fluence/codec/bits/BitsUint8Codecs.scala
similarity index 79%
rename from protobuf/js/src/main/scala/fluence/codec/Uint8ArrayCodecs.scala
rename to bits/js/src/main/scala/fluence/codec/bits/BitsUint8Codecs.scala
index ed20768..e6873b4 100644
--- a/protobuf/js/src/main/scala/fluence/codec/Uint8ArrayCodecs.scala
+++ b/bits/js/src/main/scala/fluence/codec/bits/BitsUint8Codecs.scala
@@ -15,26 +15,18 @@
* along with this program. If not, see .
*/
-package fluence.codec
+package fluence.codec.bits
+import fluence.codec.PureCodec
import scodec.bits.ByteVector
-import scala.language.higherKinds
-
import scala.scalajs.js.typedarray.Uint8Array
import scala.scalajs.js.JSConverters._
-object Uint8ArrayCodecs {
-
+object BitsUint8Codecs {
implicit val byteVectorUint8Array: PureCodec[Uint8Array, ByteVector] =
PureCodec.liftB(
uint8 ⇒ ByteVector(uint8.toArray.map(_.toByte)),
vec ⇒ new Uint8Array(vec.toArray.map(_.toShort).toJSArray)
)
-
- implicit val byteArrayUint8Array: PureCodec[Uint8Array, Array[Byte]] =
- PureCodec.liftB(
- uint8 ⇒ uint8.toArray.map(_.toByte),
- arr ⇒ new Uint8Array(arr.toJSArray)
- )
}
diff --git a/bits/src/main/scala/fluence/codec/bits/BitsCodecs.scala b/bits/src/main/scala/fluence/codec/bits/BitsCodecs.scala
new file mode 100644
index 0000000..ffb6dbb
--- /dev/null
+++ b/bits/src/main/scala/fluence/codec/bits/BitsCodecs.scala
@@ -0,0 +1,46 @@
+/*
+ * 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 .
+ */
+
+package fluence.codec.bits
+
+import fluence.codec.{CodecError, PureCodec}
+import scodec.bits.{Bases, ByteVector}
+
+/**
+ * Implicit codecs for scodec data structures.
+ */
+object BitsCodecs {
+ import PureCodec.{liftB, liftEitherB}
+
+ implicit val byteArrayToVector: PureCodec[Array[Byte], ByteVector] =
+ liftB(ByteVector.apply, _.toArray)
+
+ // Notice the use of default Base64 alphabet
+ implicit val base64ToVector: PureCodec[String, ByteVector] =
+ base64AlphabetToVector(Bases.Alphabets.Base64)
+
+ def base64AlphabetToVector(alphabet: Bases.Base64Alphabet): PureCodec[String, ByteVector] =
+ liftEitherB(
+ str ⇒
+ ByteVector
+ .fromBase64Descriptive(str, alphabet)
+ .left
+ .map(CodecError(_)),
+ vec ⇒ Right(vec.toBase64(alphabet))
+ )
+
+}
diff --git a/bits/src/test/scala/fluence/codec/bits/BitsCodecsSpec.scala b/bits/src/test/scala/fluence/codec/bits/BitsCodecsSpec.scala
new file mode 100644
index 0000000..131b369
--- /dev/null
+++ b/bits/src/test/scala/fluence/codec/bits/BitsCodecsSpec.scala
@@ -0,0 +1,47 @@
+/*
+ * 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 .
+ */
+
+package fluence.codec.bits
+
+import cats.Id
+import cats.syntax.compose._
+import org.scalatest.prop.Checkers
+import org.scalatest.{Matchers, WordSpec}
+import scodec.bits.ByteVector
+import BitsCodecs._
+import fluence.codec.PureCodec
+
+class BitsCodecsSpec extends WordSpec with Matchers with Checkers {
+ "BitsCodecs" should {
+ "convert base64 strings to byte vectors and vice versa" in {
+
+ val arrCodec = implicitly[PureCodec[Array[Byte], ByteVector]]
+ val b64Codec = implicitly[PureCodec[ByteVector, String]]
+
+ check { (bytes: List[Byte]) ⇒
+ (arrCodec andThen arrCodec.swap).direct.apply[Id](bytes.toArray).value.map(_.toList).contains(bytes) &&
+ (arrCodec andThen b64Codec andThen b64Codec.swap andThen arrCodec.swap).direct
+ .apply[Id](bytes.toArray)
+ .value
+ .map(_.toList)
+ .contains(bytes)
+ }
+
+ b64Codec.inverse[Id]("wrong input!").value.isLeft shouldBe true
+ }
+ }
+}
diff --git a/circe/src/main/scala/fluence/codec/circe/CirceCodecs.scala b/circe/src/main/scala/fluence/codec/circe/CirceCodecs.scala
new file mode 100644
index 0000000..580d8dd
--- /dev/null
+++ b/circe/src/main/scala/fluence/codec/circe/CirceCodecs.scala
@@ -0,0 +1,37 @@
+/*
+ * 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 .
+ */
+
+package fluence.codec.circe
+
+import fluence.codec.{CodecError, PureCodec}
+import io.circe._
+
+object CirceCodecs {
+
+ implicit def circeJsonCodec[T](encoder: Encoder[T], decoder: Decoder[T]): PureCodec[T, Json] =
+ PureCodec.liftEitherB[T, Json](
+ t ⇒ Right(encoder.apply(t)),
+ json ⇒ decoder.decodeJson(json).left.map(f ⇒ CodecError("Cannot decode json value", causedBy = Some(f)))
+ )
+
+ implicit val circeJsonParseCodec: PureCodec[Json, String] =
+ PureCodec.liftEitherB(
+ json ⇒ Right(json.noSpaces),
+ str ⇒ parser.parse(str).left.map(f ⇒ CodecError("Cannot parse json string", causedBy = Some(f)))
+ )
+
+}
diff --git a/core/js/src/main/scala/fluence/codec/Uint8Codecs.scala b/core/js/src/main/scala/fluence/codec/Uint8Codecs.scala
new file mode 100644
index 0000000..0325eac
--- /dev/null
+++ b/core/js/src/main/scala/fluence/codec/Uint8Codecs.scala
@@ -0,0 +1,30 @@
+/*
+ * 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 .
+ */
+
+package fluence.codec
+
+import scala.scalajs.js.JSConverters._
+import scala.scalajs.js.typedarray.Uint8Array
+
+object Uint8Codecs {
+
+ implicit val byteArrayUint8Array: PureCodec[Uint8Array, Array[Byte]] =
+ PureCodec.liftB(
+ uint8 ⇒ uint8.toArray.map(_.toByte),
+ arr ⇒ new Uint8Array(arr.toJSArray)
+ )
+}
diff --git a/core/src/main/scala/fluence/codec/Codec.scala b/core/src/main/scala/fluence/codec/Codec.scala
index 377892c..04146e5 100644
--- a/core/src/main/scala/fluence/codec/Codec.scala
+++ b/core/src/main/scala/fluence/codec/Codec.scala
@@ -18,9 +18,8 @@
package fluence.codec
import cats.data.Kleisli
-import cats.{Applicative, ApplicativeError, FlatMap, Traverse}
+import cats.{Applicative, FlatMap, Traverse}
import cats.syntax.applicative._
-import scodec.bits.ByteVector
import scala.language.{higherKinds, implicitConversions}
@@ -31,6 +30,10 @@ import scala.language.{higherKinds, implicitConversions}
* @tparam B The type of binary representation
* @tparam F Encoding/decoding effect
*/
+@deprecated(
+ "Codec is planned for removing soon, as it's impure and not properly tested. Use PureCodec instead.",
+ "6.4.2018"
+)
final case class Codec[F[_], A, B](encode: A ⇒ F[B], decode: B ⇒ F[A]) {
self ⇒
@@ -47,6 +50,10 @@ final case class Codec[F[_], A, B](encode: A ⇒ F[B], decode: B ⇒ F[A]) {
def swap: Codec[F, B, A] = Codec(decode, encode)
}
+@deprecated(
+ "Codec is planned for removing soon, as it's impure and not properly tested. Use PureCodec instead.",
+ "6.4.2018"
+)
object Codec {
implicit def identityCodec[F[_]: Applicative, T]: Codec[F, T, T] =
Codec(_.pure[F], _.pure[F])
@@ -65,21 +72,10 @@ object Codec {
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]
- )
-
+ @deprecated(
+ "Codec is planned for removing soon, as it's impure and not properly tested. Use PureCodec instead.",
+ "6.4.2018"
+ )
def codec[F[_], O, B](implicit codec: Codec[F, O, B]): Codec[F, O, B] = codec
/**
@@ -92,6 +88,10 @@ object Codec {
* @tparam B Encoded type
* @return New codec for O and B
*/
+ @deprecated(
+ "Codec is planned for removing soon, as it's impure and not properly tested. Use PureCodec instead.",
+ "6.4.2018"
+ )
def pure[F[_]: Applicative, O, B](encodeFn: O ⇒ B, decodeFn: B ⇒ O): Codec[F, O, B] =
Codec(encodeFn(_).pure[F], decodeFn(_).pure[F])
}
diff --git a/core/src/main/scala/fluence/codec/CodecError.scala b/core/src/main/scala/fluence/codec/CodecError.scala
index e7a72ce..d26c4c0 100644
--- a/core/src/main/scala/fluence/codec/CodecError.scala
+++ b/core/src/main/scala/fluence/codec/CodecError.scala
@@ -26,6 +26,7 @@ import scala.util.control.NoStackTrace
* it's returned in the left side of Either(T) by PureCodec transformations.
*
* @param message Error message
+ * @param causedBy Error cause for wrapped exceptions
*/
case class CodecError(message: String, causedBy: Option[Throwable] = None) extends NoStackTrace {
override def getMessage: String = message
diff --git a/core/src/main/scala/fluence/codec/MonadicalEitherArrow.scala b/core/src/main/scala/fluence/codec/MonadicalEitherArrow.scala
index e786b6f..d3049bc 100644
--- a/core/src/main/scala/fluence/codec/MonadicalEitherArrow.scala
+++ b/core/src/main/scala/fluence/codec/MonadicalEitherArrow.scala
@@ -27,7 +27,7 @@ import scala.language.higherKinds
import scala.util.Try
/**
- * MonadicalEitherFunc wraps Func and Bijection with a fixed E error type.
+ * MonadicalEitherArrow wraps Func and Bijection with a fixed E error type.
*
* @tparam E Error type
*/
@@ -108,6 +108,10 @@ abstract class MonadicalEitherArrow[E <: Throwable] {
*/
lazy val swap: Bijection[B, A] = Bijection(inverse, direct)
+ @deprecated(
+ "You should keep codec Pure until running direct or inverse on it: there's no reason to bind effect into Codec",
+ "6.4.2018"
+ )
def toCodec[F[_]](implicit F: MonadError[F, Throwable]): Codec[F, A, B] =
Codec(direct.runF[F], inverse.runF[F])
}
@@ -144,6 +148,11 @@ abstract class MonadicalEitherArrow[E <: Throwable] {
Traverse[G].traverse[EitherT[F, E, ?], A, B](input)(f.apply[F](_))
}
+ /**
+ * Bijection Summoner -- useful for making a composition of bijections.
+ */
+ def apply[A, B](implicit bijection: Bijection[A, B]): Bijection[A, B] = bijection
+
/**
* Lifts a pure function into Func context.
*
diff --git a/core/src/main/scala/fluence/codec/PureCodec.scala b/core/src/main/scala/fluence/codec/PureCodec.scala
index 3fd8506..7af6939 100644
--- a/core/src/main/scala/fluence/codec/PureCodec.scala
+++ b/core/src/main/scala/fluence/codec/PureCodec.scala
@@ -17,26 +17,11 @@
package fluence.codec
-import scodec.bits.{Bases, ByteVector}
-
/**
* PureCodec default values.
*/
object PureCodec extends MonadicalEitherArrow[CodecError] {
- implicit val byteArrayToVector: PureCodec[Array[Byte], ByteVector] =
- liftB(ByteVector.apply, _.toArray)
-
- implicit val base64ToVector: PureCodec[String, ByteVector] =
- liftEitherB(
- str ⇒
- ByteVector
- .fromBase64Descriptive(str, Bases.Alphabets.Base64)
- .left
- .map(CodecError(_)),
- vec ⇒ Right(vec.toBase64(Bases.Alphabets.Base64))
- )
-
/**
* Summons an implicit codec.
*/
@@ -45,12 +30,12 @@ object PureCodec extends MonadicalEitherArrow[CodecError] {
/**
* Shortcut to build a PureCodec.Bijection with two Func's
*/
- def apply[A, B](direct: Func[A, B], inverse: Func[B, A]): Bijection[A, B] =
+ def build[A, B](direct: Func[A, B], inverse: Func[B, A]): Bijection[A, B] =
Bijection(direct, inverse)
/**
* Shortcut to build a PureCodec.Bijection with two pure functions
*/
- def apply[A, B](direct: A ⇒ B, inverse: B ⇒ A): Bijection[A, B] =
+ def build[A, B](direct: A ⇒ B, inverse: B ⇒ A): Bijection[A, B] =
liftB(direct, inverse)
}
diff --git a/core/src/test/scala/fluence/codec/PureCodecSpec.scala b/core/src/test/scala/fluence/codec/PureCodecSpec.scala
index 47c45a8..f776bef 100644
--- a/core/src/test/scala/fluence/codec/PureCodecSpec.scala
+++ b/core/src/test/scala/fluence/codec/PureCodecSpec.scala
@@ -17,12 +17,9 @@
package fluence.codec
-import cats.Id
import cats.instances.try_._
-import cats.syntax.compose._
import org.scalatest.prop.Checkers
import org.scalatest.{Matchers, WordSpec}
-import scodec.bits.ByteVector
import scala.util.Try
@@ -37,23 +34,5 @@ class PureCodecSpec extends WordSpec with Matchers with Checkers {
}
}
-
- "convert base64 strings to byte vectors and vice versa" in {
-
- val arrCodec = implicitly[PureCodec[Array[Byte], ByteVector]]
- val b64Codec = implicitly[PureCodec[ByteVector, String]]
-
- check { (bytes: List[Byte]) ⇒
- (arrCodec andThen arrCodec.swap).direct.apply[Id](bytes.toArray).value.map(_.toList).contains(bytes) &&
- (arrCodec andThen b64Codec andThen b64Codec.swap andThen arrCodec.swap).direct
- .apply[Id](bytes.toArray)
- .value
- .map(_.toList)
- .contains(bytes)
- }
-
- b64Codec.inverse[Id]("wrong input!").value.isLeft shouldBe true
-
- }
}
}
diff --git a/protobuf/src/main/scala/fluence/codec/pb/ProtobufCodecs.scala b/protobuf/src/main/scala/fluence/codec/pb/ProtobufCodecs.scala
index e3ccd2e..865c9e3 100644
--- a/protobuf/src/main/scala/fluence/codec/pb/ProtobufCodecs.scala
+++ b/protobuf/src/main/scala/fluence/codec/pb/ProtobufCodecs.scala
@@ -19,18 +19,11 @@ package fluence.codec.pb
import com.google.protobuf.ByteString
import fluence.codec.PureCodec
-import scodec.bits.ByteVector
import scala.language.higherKinds
object ProtobufCodecs {
- implicit val byteVectorByteString: PureCodec[ByteString, ByteVector] =
- PureCodec.liftB(
- str ⇒ ByteVector(str.toByteArray),
- vec ⇒ ByteString.copyFrom(vec.toArray)
- )
-
implicit val byteArrayByteString: PureCodec[ByteString, Array[Byte]] =
PureCodec.liftB(
str ⇒ str.toByteArray,