scodec.bits.BitVector Scala Examples

The following examples show how to use scodec.bits.BitVector. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: BitVectorSocket.scala    From skunk   with MIT License 5 votes vote down vote up
// Copyright (c) 2018-2020 by Rob Norris
// This software is licensed under the MIT License (MIT).
// For more information see LICENSE or https://opensource.org/licenses/MIT

package skunk.net

import cats._
import cats.effect._
import cats.implicits._
import fs2.Chunk
import fs2.io.tcp.Socket
import scala.concurrent.duration.FiniteDuration
import scodec.bits.BitVector
import java.net.InetSocketAddress
import java.nio.channels._
import java.util.concurrent.Executors
import java.util.concurrent.ThreadFactory
import fs2.io.tcp.SocketGroup


  def apply[F[_]: Concurrent: ContextShift](
    host:         String,
    port:         Int,
    readTimeout:  FiniteDuration,
    writeTimeout: FiniteDuration,
    sg:           SocketGroup,
    sslOptions:   Option[SSLNegotiation.Options[F]],
  ): Resource[F, BitVectorSocket[F]] =
    for {
      sock  <- sg.client[F](new InetSocketAddress(host, port))
      sockʹ <- sslOptions.fold(sock.pure[Resource[F, ?]])(SSLNegotiation.negotiateSSL(sock, readTimeout, writeTimeout, _))
    } yield fromSocket(sockʹ, readTimeout, writeTimeout)

} 
Example 2
Source File: MyBijections.scala    From fotm-info   with MIT License 5 votes vote down vote up
package models

import com.twitter.bijection.{Base64String, Bijection, GZippedBytes}
import info.fotm.domain.{CharacterId, Team}
import scodec.Codec
import scodec.bits.BitVector
import scodec.codecs.implicits._
import info.fotm.MyCodecImplicits._

object MyBijections {
  def scodecBase64Bijection[T](implicit codec: Codec[T]): Bijection[T, String] = Bijection.build[T, String] { t =>
    val bytes = Codec.encode(t).require.toByteArray
    Bijection.bytes2Base64(bytes).str
  } { base64 =>
    val bytes = Bijection.bytes2Base64.inverse(Base64String(base64))
    Codec.decode[T](BitVector(bytes)).require.value
  }

  def scodecGzipBijection[T](implicit codec: Codec[T]): Bijection[T, Array[Byte]] = Bijection.build[T, Array[Byte]] { t =>
    val bytes = Codec.encode(t).require.toByteArray
    Bijection.bytes2GzippedBytes(bytes).bytes
  } { gzippedBytes =>
    val bytes = Bijection.bytes2GzippedBytes.inverse(GZippedBytes(gzippedBytes))
    Codec.decode[T](BitVector(bytes)).require.value
  }

  lazy val teamIdBijection: Bijection[Team, String] = scodecBase64Bijection[Team]
  lazy val charIdBijection: Bijection[CharacterId, String] = scodecBase64Bijection[CharacterId]
} 
Example 3
Source File: BoopickleCodec.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.macros.boopickle
import boopickle.Pickler
import scodec.bits.BitVector
import scodec.{ Attempt, Codec, DecodeResult, Decoder, Encoder, Err, SizeBound }
import _root_.boopickle.Default._

import scala.util.Try

object BoopickleCodec {
  def encoder[A](implicit pickler: Pickler[A]): Encoder[A] = new Encoder[A] {
    override def encode(value: A): Attempt[BitVector] =
      Attempt.successful(BitVector(Pickle.intoBytes(value)))
    override def sizeBound: SizeBound = SizeBound.unknown
  }
  def decoder[A](implicit pickler: Pickler[A]): Decoder[A] = new Decoder[A] {
    override def decode(bits: BitVector): Attempt[DecodeResult[A]] =
      Unpickle
        .apply[A]
        .tryFromBytes(bits.toByteBuffer)
        .fold(
          s => Attempt.failure(Err(s.getMessage)),
          a => Attempt.successful(DecodeResult(a, BitVector.empty))
        )
  }

  def codec[A](implicit pickler: Pickler[A]): Codec[A] = Codec(encoder[A], decoder[A])

  def attemptFromTry[A](ta: Try[A]): Attempt[DecodeResult[A]] = ta.fold(
    s => Attempt.failure(Err(s.getMessage)),
    a => Attempt.successful(DecodeResult(a, BitVector.empty))
  )
} 
Example 4
Source File: BoopickleWireProtocolTest.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.tests

import java.util.UUID

import aecor.encoding.WireProtocol
import aecor.macros.boopickle.BoopickleWireProtocol
import aecor.tests.BoopickleWireProtocolTest._
import cats.implicits._
import cats.tagless.syntax.functorK._
import cats.tagless.{ Derive, FunctorK }
import cats.{ Applicative, Functor, Id, ~> }
import org.scalatest.matchers.should.Matchers
import org.scalatest.funsuite.AnyFunSuite
import scodec.bits.BitVector
import scodec.{ Attempt, Decoder }

object BoopickleWireProtocolTest {
  final case class FooId(value: UUID) extends AnyVal
}

class BoopickleWireProtocolTest extends AnyFunSuite with Matchers {
  import boopickle.Default._

  trait Foo[K, F[_]] {
    def include(i: K): F[Unit]
    def scdsc(s: String): F[K]
    def id: F[FooId]
  }

  object Foo {
    implicit def functorK[K]: FunctorK[Foo[K, *[_]]] = Derive.functorK
    implicit def wireProtocol[K: Pickler]: WireProtocol[Foo[K, *[_]]] = BoopickleWireProtocol.derive
  }

  def server[M[_[_]], F[_]: Applicative](
    actions: M[F]
  )(implicit M: WireProtocol[M]): BitVector => F[Attempt[BitVector]] = { in =>
    M.decoder
      .decodeValue(in) match {
      case Attempt.Successful(p) =>
        val r: F[p.A] = p.first.run(actions)
        r.map(a => p.second.encode(a))
      case Attempt.Failure(cause) =>
        Attempt.failure[BitVector](cause).pure[F]
    }

  }

  type DecodingResultT[F[_], A] = F[Attempt[A]]

  def client[M[_[_]], F[_]: Functor](
    server: BitVector => F[Attempt[BitVector]]
  )(implicit M: WireProtocol[M], MI: FunctorK[M]): M[DecodingResultT[F, *]] =
    M.encoder
      .mapK[DecodingResultT[F, *]](new (WireProtocol.Encoded ~> DecodingResultT[F, *]) {
        override def apply[A](fa: (BitVector, Decoder[A])): F[Attempt[A]] =
          server(fa._1).map(_.flatMap(fa._2.decodeValue))
      })

  test("encdec") {
    val uuid = UUID.randomUUID
    val actions = new Foo[Int, Id] {
      override def include(i: Int): Id[Unit] = ()
      override def scdsc(s: String): Id[Int] = s.length
      override def id: Id[FooId] = FooId(uuid)
    }

    val fooServer = server(actions)

    val fooClient = client[Foo[Int, *[_]], Id](fooServer)

    fooClient.include(1).toEither shouldBe Right(())
    fooClient.scdsc("1234").toEither shouldBe Right(4)
    fooClient.id.toEither shouldBe Right(FooId(uuid))
  }
} 
Example 5
Source File: GenericAkkaRuntime.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.runtime.akkageneric

import aecor.encoding.WireProtocol.Encoded
import aecor.encoding.syntax._
import aecor.encoding.{ KeyDecoder, KeyEncoder, WireProtocol }
import aecor.runtime.akkageneric.GenericAkkaRuntime.KeyedCommand
import aecor.runtime.akkageneric.GenericAkkaRuntimeActor.CommandResult
import aecor.runtime.akkageneric.serialization.Message
import aecor.util.effect._
import akka.actor.ActorSystem
import akka.cluster.sharding.{ ClusterSharding, ShardRegion }
import akka.pattern._
import akka.util.Timeout
import cats.effect.Effect
import cats.implicits._
import cats.tagless.FunctorK
import cats.tagless.syntax.functorK._
import cats.~>
import scodec.bits.BitVector

object GenericAkkaRuntime {
  def apply(system: ActorSystem): GenericAkkaRuntime =
    new GenericAkkaRuntime(system)
  private[akkageneric] final case class KeyedCommand(key: String, bytes: BitVector) extends Message
}

final class GenericAkkaRuntime private (system: ActorSystem) {
  def runBehavior[K: KeyEncoder: KeyDecoder, M[_[_]]: FunctorK, F[_]](
    typeName: String,
    createBehavior: K => F[M[F]],
    settings: GenericAkkaRuntimeSettings = GenericAkkaRuntimeSettings.default(system)
  )(implicit M: WireProtocol[M], F: Effect[F]): F[K => M[F]] =
    F.delay {
      val props = GenericAkkaRuntimeActor.props[K, M, F](createBehavior, settings.idleTimeout)

      val extractEntityId: ShardRegion.ExtractEntityId = {
        case KeyedCommand(entityId, c) =>
          (entityId, GenericAkkaRuntimeActor.Command(c))
      }

      val numberOfShards = settings.numberOfShards

      val extractShardId: ShardRegion.ExtractShardId = {
        case KeyedCommand(key, _) =>
          String.valueOf(scala.math.abs(key.hashCode) % numberOfShards)
        case other => throw new IllegalArgumentException(s"Unexpected message [$other]")
      }

      val shardRegion = ClusterSharding(system).start(
        typeName = typeName,
        entityProps = props,
        settings = settings.clusterShardingSettings,
        extractEntityId = extractEntityId,
        extractShardId = extractShardId
      )

      val keyEncoder = KeyEncoder[K]

      key =>
        M.encoder.mapK(new (Encoded ~> F) {

          implicit val askTimeout: Timeout = Timeout(settings.askTimeout)

          override def apply[A](fa: Encoded[A]): F[A] = F.suspend {
            val (bytes, decoder) = fa
            F.fromFuture {
                shardRegion ? KeyedCommand(keyEncoder(key), bytes)
              }
              .flatMap {
                case result: CommandResult =>
                  decoder.decodeValue(result.bytes).lift[F]
                case other =>
                  F.raiseError(
                    new IllegalArgumentException(s"Unexpected response [$other] from shard region")
                  )
              }
          }
        })
    }
} 
Example 6
Source File: MessageSerializer.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.runtime.akkageneric.serialization

import aecor.runtime.akkageneric.GenericAkkaRuntime.KeyedCommand
import aecor.runtime.akkageneric.GenericAkkaRuntimeActor.{ Command, CommandResult }
import akka.actor.ExtendedActorSystem
import akka.serialization.{ BaseSerializer, SerializerWithStringManifest }
import com.google.protobuf.ByteString
import scodec.bits.BitVector

import scala.collection.immutable.HashMap

class MessageSerializer(val system: ExtendedActorSystem)
    extends SerializerWithStringManifest
    with BaseSerializer {

  val KeyedCommandManifest = "A"
  val CommandManifest = "B"
  val CommandResultManifest = "C"

  private val fromBinaryMap =
    HashMap[String, Array[Byte] => AnyRef](
      KeyedCommandManifest -> keyedCommandFromBinary,
      CommandManifest -> commandFromBinary,
      CommandResultManifest -> commandResultFromBinary
    )

  override def manifest(o: AnyRef): String = o match {
    case KeyedCommand(_, _) => KeyedCommandManifest
    case Command(_)         => CommandManifest
    case CommandResult(_)   => CommandResultManifest
    case x                  => throw new IllegalArgumentException(s"Serialization of [$x] is not supported")
  }

  override def toBinary(o: AnyRef): Array[Byte] = o match {
    case Command(bytes) =>
      bytes.toByteArray
    case CommandResult(bytes) =>
      bytes.toByteArray
    case x @ KeyedCommand(_, _) =>
      entityCommandToBinary(x)
    case x => throw new IllegalArgumentException(s"Serialization of [$x] is not supported")
  }

  override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef =
    fromBinaryMap.get(manifest) match {
      case Some(f) => f(bytes)
      case other   => throw new IllegalArgumentException(s"Unknown manifest [$other]")
    }

  private def entityCommandToBinary(a: KeyedCommand): Array[Byte] =
    msg.KeyedCommand(a.key, ByteString.copyFrom(a.bytes.toByteBuffer)).toByteArray

  private def keyedCommandFromBinary(bytes: Array[Byte]): KeyedCommand =
    msg.KeyedCommand.parseFrom(bytes) match {
      case msg.KeyedCommand(key, commandBytes) =>
        KeyedCommand(key, BitVector(commandBytes.asReadOnlyByteBuffer()))
    }

  private def commandFromBinary(bytes: Array[Byte]): Command =
    Command(BitVector(bytes))

  private def commandResultFromBinary(bytes: Array[Byte]): CommandResult =
    CommandResult(BitVector(bytes))
} 
Example 7
Source File: MessageSerializerTest.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.runtime.akkageneric

import aecor.runtime.akkageneric.GenericAkkaRuntime.KeyedCommand
import aecor.runtime.akkageneric.GenericAkkaRuntimeActor.{ Command, CommandResult }
import aecor.runtime.akkageneric.serialization.MessageSerializer
import akka.actor.ActorSystem
import akka.serialization.SerializationExtension
import org.scalacheck.Arbitrary
import org.scalacheck.Arbitrary._
import org.scalacheck.Prop.forAll
import org.scalatest.BeforeAndAfterAll
import org.scalatest.funsuite.AnyFunSuite
import scodec.bits.BitVector

import scala.concurrent.Await
import scala.concurrent.duration._

class MessageSerializerTest extends AnyFunSuite with BeforeAndAfterAll {

  implicit val system: ActorSystem = ActorSystem("test")
  val serialization = SerializationExtension(system)
  implicit val bitVector: Arbitrary[BitVector] = Arbitrary(arbitrary[Array[Byte]].map(BitVector(_)))

  def canSerialize[A <: AnyRef](a: A): Boolean = {
    val ser = serialization.serializerFor(a.getClass)
    assert(ser.isInstanceOf[MessageSerializer])
    val mser = ser.asInstanceOf[MessageSerializer]
    val (man, bytes) = (mser.manifest(a), mser.toBinary(a))
    val out = mser.fromBinary(bytes, man)
    out === a
  }

  test("serialization") {
    forAll { bb: BitVector =>
      canSerialize(Command(bb))
    }
    forAll { bb: BitVector =>
      canSerialize(CommandResult(bb))
    }
    forAll { (key: String, bb: BitVector) =>
      canSerialize(KeyedCommand(key, bb))
    }
  }

  override protected def afterAll(): Unit = {
    Await.result(system.terminate(), 5.seconds)
    ()
  }
} 
Example 8
Source File: MessageSerializer.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.runtime.akkapersistence.serialization

import aecor.runtime.akkapersistence.AkkaPersistenceRuntime.EntityCommand
import aecor.runtime.akkapersistence.AkkaPersistenceRuntimeActor.{ CommandResult, HandleCommand }
import akka.actor.ExtendedActorSystem
import akka.serialization.{ BaseSerializer, SerializerWithStringManifest }
import com.google.protobuf.ByteString
import scodec.bits.BitVector

import scala.collection.immutable._

class MessageSerializer(val system: ExtendedActorSystem)
    extends SerializerWithStringManifest
    with BaseSerializer {

  val HandleCommandManifest = "A"
  val EntityCommandManifest = "B"
  val CommandResultManifest = "C"

  private val fromBinaryMap =
    HashMap[String, Array[Byte] => AnyRef](
      HandleCommandManifest -> handleCommandFromBinary,
      EntityCommandManifest -> entityCommandFromBinary,
      CommandResultManifest -> commandResultFromBinary
    )

  override def manifest(o: AnyRef): String = o match {
    case HandleCommand(_)    => HandleCommandManifest
    case EntityCommand(_, _) => EntityCommandManifest
    case CommandResult(_)    => CommandResultManifest
    case x                   => throw new IllegalArgumentException(s"Serialization of [$x] is not supported")
  }

  override def toBinary(o: AnyRef): Array[Byte] = o match {
    case x @ HandleCommand(_) =>
      x.commandBytes.toByteArray
    case _ @CommandResult(resultBytes) =>
      resultBytes.toByteArray
    case x @ EntityCommand(_, _) =>
      entityCommandToBinary(x)
    case x => throw new IllegalArgumentException(s"Serialization of [$x] is not supported")
  }

  override def fromBinary(bytes: Array[Byte], manifest: String): AnyRef =
    fromBinaryMap.get(manifest) match {
      case Some(f) => f(bytes)
      case other   => throw new IllegalArgumentException(s"Unknown manifest [$other]")
    }

  private def entityCommandToBinary(a: EntityCommand): Array[Byte] =
    msg.EntityCommand(a.entityKey, ByteString.copyFrom(a.commandBytes.toByteBuffer)).toByteArray

  private def entityCommandFromBinary(bytes: Array[Byte]): EntityCommand =
    msg.EntityCommand.parseFrom(bytes) match {
      case msg.EntityCommand(entityId, commandBytes) =>
        EntityCommand(entityId, BitVector(commandBytes.asReadOnlyByteBuffer))
    }

  private def handleCommandFromBinary(bytes: Array[Byte]): HandleCommand =
    HandleCommand(BitVector(bytes))

  private def commandResultFromBinary(bytes: Array[Byte]): CommandResult =
    CommandResult(BitVector(bytes))

} 
Example 9
Source File: AkkaPersistenceRuntime.scala    From aecor   with MIT License 5 votes vote down vote up
package aecor.runtime.akkapersistence

import aecor.data.{ EventsourcedBehavior, Tagging }
import aecor.encoding.WireProtocol.Encoded
import aecor.encoding.syntax._
import aecor.encoding.{ KeyDecoder, KeyEncoder, WireProtocol }
import aecor.runtime.akkapersistence.AkkaPersistenceRuntime._
import aecor.runtime.akkapersistence.AkkaPersistenceRuntimeActor.CommandResult
import aecor.runtime.akkapersistence.readside.{ AkkaPersistenceEventJournalQuery, JournalQuery }
import aecor.runtime.akkapersistence.serialization.{ Message, PersistentDecoder, PersistentEncoder }
import aecor.util.effect._
import akka.actor.ActorSystem
import akka.cluster.sharding.{ ClusterSharding, ShardRegion }
import akka.pattern.ask
import akka.util.Timeout
import cats.effect.Effect
import cats.implicits._
import cats.tagless.FunctorK
import cats.tagless.syntax.functorK._
import cats.~>
import scodec.bits.BitVector

object AkkaPersistenceRuntime {
  def apply[O](system: ActorSystem, journalAdapter: JournalAdapter[O]): AkkaPersistenceRuntime[O] =
    new AkkaPersistenceRuntime(system, journalAdapter)

  private[akkapersistence] final case class EntityCommand(entityKey: String,
                                                          commandBytes: BitVector)
      extends Message
}

class AkkaPersistenceRuntime[O] private[akkapersistence] (system: ActorSystem,
                                                          journalAdapter: JournalAdapter[O]) {
  def deploy[M[_[_]]: FunctorK, F[_], State, Event: PersistentEncoder: PersistentDecoder, K: KeyEncoder: KeyDecoder](
    typeName: String,
    behavior: EventsourcedBehavior[M, F, State, Event],
    tagging: Tagging[K],
    snapshotPolicy: SnapshotPolicy[State] = SnapshotPolicy.never,
    settings: AkkaPersistenceRuntimeSettings = AkkaPersistenceRuntimeSettings.default(system)
  )(implicit M: WireProtocol[M], F: Effect[F]): F[K => M[F]] =
    F.delay {
      val props =
        AkkaPersistenceRuntimeActor.props(
          typeName,
          behavior,
          snapshotPolicy,
          tagging,
          settings.idleTimeout,
          journalAdapter.writeJournalId,
          snapshotPolicy.pluginId
        )

      val extractEntityId: ShardRegion.ExtractEntityId = {
        case EntityCommand(entityId, bytes) =>
          (entityId, AkkaPersistenceRuntimeActor.HandleCommand(bytes))
      }

      val numberOfShards = settings.numberOfShards

      val extractShardId: ShardRegion.ExtractShardId = {
        case EntityCommand(entityId, _) =>
          (scala.math.abs(entityId.hashCode) % numberOfShards).toString
        case other => throw new IllegalArgumentException(s"Unexpected message [$other]")
      }

      val shardRegion = ClusterSharding(system).start(
        typeName = typeName,
        entityProps = props,
        settings = settings.clusterShardingSettings,
        extractEntityId = extractEntityId,
        extractShardId = extractShardId
      )

      val keyEncoder = KeyEncoder[K]

      key =>
        M.encoder.mapK(new (Encoded ~> F) {

          implicit val askTimeout: Timeout = Timeout(settings.askTimeout)

          override def apply[A](fa: Encoded[A]): F[A] = F.suspend {
            val (bytes, decoder) = fa
            F.fromFuture {
                shardRegion ? EntityCommand(keyEncoder(key), bytes)
              }
              .flatMap {
                case CommandResult(resultBytes) =>
                  decoder.decodeValue(resultBytes).lift[F]
                case other =>
                  F.raiseError(
                    new IllegalArgumentException(s"Unexpected response [$other] from shard region")
                  )
              }
          }
        })
    }

  def journal[K: KeyDecoder, E: PersistentDecoder]: JournalQuery[O, K, E] =
    AkkaPersistenceEventJournalQuery[O, K, E](journalAdapter)
} 
Example 10
Source File: SqlitePeersDb.scala    From eclair   with Apache License 2.0 5 votes vote down vote up
package fr.acinq.eclair.db.sqlite

import java.sql.Connection

import fr.acinq.bitcoin.Crypto
import fr.acinq.bitcoin.Crypto.PublicKey
import fr.acinq.eclair.db.PeersDb
import fr.acinq.eclair.db.sqlite.SqliteUtils.{codecSequence, getVersion, using}
import fr.acinq.eclair.wire._
import scodec.bits.BitVector

class SqlitePeersDb(sqlite: Connection) extends PeersDb {

  import SqliteUtils.ExtendedResultSet._

  val DB_NAME = "peers"
  val CURRENT_VERSION = 1

  using(sqlite.createStatement(), inTransaction = true) { statement =>
    require(getVersion(statement, DB_NAME, CURRENT_VERSION) == CURRENT_VERSION, s"incompatible version of $DB_NAME DB found") // there is only one version currently deployed
    statement.executeUpdate("CREATE TABLE IF NOT EXISTS peers (node_id BLOB NOT NULL PRIMARY KEY, data BLOB NOT NULL)")
  }

  override def addOrUpdatePeer(nodeId: Crypto.PublicKey, nodeaddress: NodeAddress): Unit = {
    val data = CommonCodecs.nodeaddress.encode(nodeaddress).require.toByteArray
    using(sqlite.prepareStatement("UPDATE peers SET data=? WHERE node_id=?")) { update =>
      update.setBytes(1, data)
      update.setBytes(2, nodeId.value.toArray)
      if (update.executeUpdate() == 0) {
        using(sqlite.prepareStatement("INSERT INTO peers VALUES (?, ?)")) { statement =>
          statement.setBytes(1, nodeId.value.toArray)
          statement.setBytes(2, data)
          statement.executeUpdate()
        }
      }
    }
  }

  override def removePeer(nodeId: Crypto.PublicKey): Unit = {
    using(sqlite.prepareStatement("DELETE FROM peers WHERE node_id=?")) { statement =>
      statement.setBytes(1, nodeId.value.toArray)
      statement.executeUpdate()
    }
  }

  override def getPeer(nodeId: PublicKey): Option[NodeAddress] = {
    using(sqlite.prepareStatement("SELECT data FROM peers WHERE node_id=?")) { statement =>
      statement.setBytes(1, nodeId.value.toArray)
      val rs = statement.executeQuery()
      codecSequence(rs, CommonCodecs.nodeaddress).headOption
    }
  }

  override def listPeers(): Map[PublicKey, NodeAddress] = {
    using(sqlite.createStatement()) { statement =>
      val rs = statement.executeQuery("SELECT node_id, data FROM peers")
      var m: Map[PublicKey, NodeAddress] = Map()
      while (rs.next()) {
        val nodeid = PublicKey(rs.getByteVector("node_id"))
        val nodeaddress = CommonCodecs.nodeaddress.decode(BitVector(rs.getBytes("data"))).require.value
        m += (nodeid -> nodeaddress)
      }
      m
    }
  }

  // used by mobile apps
  override def close(): Unit = sqlite.close()
} 
Example 11
Source File: ReprFormat.scala    From polynote   with Apache License 2.0 5 votes vote down vote up
package polynote.data

import scodec.bits.{BitVector, ByteVector}
import shapeless.{Generic, HList, HNil, Lazy, ::}

import scala.collection.GenTraversable

trait ReprFormat[T] extends (T => ByteVector)

object ReprFormat extends ReprFormat0 {

  final case class instance[T](fn: T => ByteVector) extends ReprFormat[T] {
    def apply(t: T): ByteVector = fn(t)
  }

  private val one = ByteVector.fromByte(1)
  private val zero = ByteVector.fromByte(0)

  implicit val byteFormat: ReprFormat[Byte] = instance(ByteVector.fromByte)
  implicit val boolFormat: ReprFormat[Boolean] = instance(b => if (b) one else zero)
  implicit val shortFormat: ReprFormat[Short] = instance(ByteVector.fromShort(_))
  implicit val intFormat: ReprFormat[Int] = instance(ByteVector.fromInt(_))
  implicit val longFormat: ReprFormat[Long] = instance(ByteVector.fromLong(_))
  implicit val floatFormat: ReprFormat[Float] = instance(f => ByteVector.fromInt(java.lang.Float.floatToIntBits(f)))
  implicit val doubleFormat: ReprFormat[Double] = instance(d => ByteVector.fromLong(java.lang.Double.doubleToLongBits(d)))
  implicit val stringFormat: ReprFormat[String] = instance(str => ByteVector.encodeUtf8(str).fold(throw _, identity))
  implicit val byteArrayFormat: ReprFormat[Array[Byte]] = instance(ByteVector(_))
  implicit val byteVectorFormat: ReprFormat[ByteVector] = instance(identity)
  implicit val bitVectorFormat: ReprFormat[BitVector] = instance(_.toByteVector)

  implicit def arrayFormat[A](implicit elFormat: ReprFormat[A]): ReprFormat[Array[A]] = instance {
    arr => arr.foldLeft(ByteVector.fromInt(arr.length)) {
      (accum: ByteVector, next: A) => accum ++ elFormat(next)
    }
  }

  implicit def traversableFormat[F[X] <: GenTraversable[X], A](implicit elFormat: ReprFormat[A]): ReprFormat[F[A]] = instance {
    arr => arr.foldLeft(ByteVector.fromInt(arr.size)) {
      (accum, next) => accum ++ elFormat(next)
    }
  }

  implicit def optionalFormat[A](implicit elFormat: ReprFormat[A]): ReprFormat[Option[A]] = instance {
    case Some(el) => one ++ elFormat(el)
    case None => zero
  }

  implicit val hnilFormat: ReprFormat[HNil] = instance(_ => ByteVector.empty)

  implicit def hlistFormat[H, T <: HList](implicit formatH: ReprFormat[H], formatT: ReprFormat[T]): ReprFormat[H :: T] =
    instance {
      case h :: t => formatH(h) ++ formatT(t)
    }


}

private[data] trait ReprFormat0 { self: ReprFormat.type =>
  implicit def struct[A, L <: HList](implicit gen: Generic.Aux[A, L], formatL: Lazy[ReprFormat[L]]): ReprFormat[A] =
    instance(a => formatL.value(gen.to(a)))
} 
Example 12
Source File: WAL.scala    From polynote   with Apache License 2.0 5 votes vote down vote up
package polynote.server
package repository.fs

import java.nio.ByteBuffer
import java.nio.charset.StandardCharsets
import java.time.Instant

import polynote.messages.{Message, Notebook}
import scodec.bits.{BitVector, ByteVector}
import scodec.{Attempt, Codec, codecs}
import scodec.stream.decode
import scodec.stream.decode.StreamDecoder
import zio.{RIO, Task, ZIO}
import zio.blocking.Blocking
import zio.clock.{Clock, currentDateTime}

import scala.util.Try

object WAL {

  val WALMagicNumber: Array[Byte] = "PNWAL".getBytes(StandardCharsets.US_ASCII)
  val WALVersion: Short = 1

  // Timestamp for each update is stored in 32 bits unsigned, epoch UTC seconds.
  // So we'll have to change the format by February of 2106. Apologies to my great-great-great grandchildren.
  private val instantCodec = codecs.uint32.exmap[Instant](
    epochSeconds => Attempt.fromTry(Try(Instant.ofEpochSecond(epochSeconds))),
    instant      => Attempt.successful(instant.getEpochSecond)
  )

  def encodeTimestamp(instant: Instant): Task[BitVector] =
    ZIO.fromEither(instantCodec.encode(instant).toEither)
      .mapError(err => new RuntimeException(err.message))

  val messageCodec: Codec[(Instant, Message)] = codecs.variableSizeBytes(codecs.int32, instantCodec ~ Message.codec)

  val decoder: StreamDecoder[(Instant, Message)] = {
    val readMagic = decode.once(codecs.constant(ByteVector(WALMagicNumber)))
    val readVersion = decode.once(codecs.int16)
    def readMessages(version: Int): StreamDecoder[(Instant, Message)] = version match {
      case 1 => decode.many(messageCodec)
      case v => decode.raiseError(new Exception(s"Unknown WAL version $v"))
    }

    for {
      _       <- readMagic
      ver     <- readVersion
      message <- readMessages(ver)
    } yield message
  }

  trait WALWriter {
    protected def append(bytes: Array[Byte]): RIO[Blocking, Unit] = append(ByteBuffer.wrap(bytes))
    protected def append(bytes: BitVector): RIO[Blocking, Unit] = append(bytes.toByteBuffer)
    protected def append(bytes: ByteBuffer): RIO[Blocking, Unit]

    def writeHeader(notebook: Notebook): RIO[Blocking with Clock, Unit] =
      append(WALMagicNumber) *>
        append(BitVector.fromShort(WALVersion)) *>
        appendMessage(notebook.withoutResults)

    def appendMessage(message: Message): RIO[Blocking with Clock, Unit] = for {
      ts    <- currentDateTime.map(_.toInstant)
      bytes <- ZIO.fromEither(messageCodec.encode((ts, message)).toEither).mapError(err => new RuntimeException(err.message))
      _     <- append(bytes)
    } yield ()

    def sync(): RIO[Blocking, Unit]

    def close(): RIO[Blocking, Unit]
  }

  object WALWriter {
    object NoWAL extends WALWriter {
      override protected def append(bytes: ByteBuffer): RIO[Blocking, Unit] = ZIO.unit
      override def sync(): RIO[Blocking, Unit] = ZIO.unit
      override def close(): RIO[Blocking, Unit] = ZIO.unit
    }
  }
} 
Example 13
Source File: RESPBench.scala    From laserdisc   with MIT License 5 votes vote down vote up
package laserdisc
package protocol

import java.nio.charset.StandardCharsets.UTF_8

import org.openjdk.jmh.annotations.{Benchmark, Scope, State}
import scodec.bits.BitVector
import scodec.codecs.utf8
import scodec.{Attempt, Codec}

@State(Scope.Benchmark)
class RESPBench {

  private final val codec = Codec[RESP]

  private final val chars = 2000

  private final val ok              = "OK"
  private final val okRedis         = s"+$ok$CRLF"
  private final val rtProblem       = "runtime problem"
  private final val rtProblemRedis  = s"-$rtProblem$CRLF"
  private final val fortyTwo        = 42L
  private final val fortyTwoRedis   = s":$fortyTwo$CRLF"
  private final val longString      = new String(Array.fill(chars)('a'))
  private final val longStringRedis = s"$$$chars$CRLF$longString$CRLF"
  private final val longStringI =
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

  private final val str             = Str(ok)
  private final val strBits         = BitVector(okRedis.getBytes(UTF_8))
  private final val err             = Err(rtProblem)
  private final val errBits         = BitVector(rtProblemRedis.getBytes(UTF_8))
  private final val num             = Num(fortyTwo)
  private final val numBits         = BitVector(fortyTwoRedis.getBytes(UTF_8))
  private final val bulk            = Bulk(longString)
  private final val bulkBits        = BitVector(longStringRedis.getBytes(UTF_8))
  private final val longStringBits  = BitVector(longString.getBytes(UTF_8))
  private final val longStringIBits = BitVector(longStringI.getBytes(UTF_8))

  @Benchmark def baseline_utf8_encode: Attempt[BitVector]  = utf8.encode(longString)
  @Benchmark def baseline_utf8_decode: Attempt[String]     = utf8.decodeValue(longStringBits)
  @Benchmark def baseline_utf8_encodeI: Attempt[BitVector] = utf8.encode(longStringI)
  @Benchmark def baseline_utf8_decodeI: Attempt[String]    = utf8.decodeValue(longStringIBits)
  @Benchmark def str_encode: Attempt[BitVector]            = codec.encode(str)
  @Benchmark def str_decode: Attempt[RESP]                 = codec.decodeValue(strBits)
  @Benchmark def err_encode: Attempt[BitVector]            = codec.encode(err)
  @Benchmark def err_decode: Attempt[RESP]                 = codec.decodeValue(errBits)
  @Benchmark def num_encode: Attempt[BitVector]            = codec.encode(num)
  @Benchmark def num_decode: Attempt[RESP]                 = codec.decodeValue(numBits)
  @Benchmark def bulk_encode: Attempt[BitVector]           = codec.encode(bulk)
  @Benchmark def bulk_decode: Attempt[RESP]                = codec.decodeValue(bulkBits)
} 
Example 14
Source File: UTF8EncodingBench.scala    From laserdisc   with MIT License 5 votes vote down vote up
package laserdisc
package protocol

import java.nio.ByteBuffer
import java.nio.charset.StandardCharsets.UTF_8

import org.openjdk.jmh.annotations._
import scodec.Attempt
import scodec.bits.BitVector

@State(Scope.Benchmark)
@Warmup(time = 1)
@Measurement(time = 1)
class UTF8EncodingBench {

  private final val defaultUtf8 = scodec.codecs.utf8
  private final val lenientUtf8 = new LenientStringCodec(UTF_8)

  private final val ok          = "OK"
  private final val okBytes     = ok.getBytes(UTF_8)
  private final val okBitVector = BitVector.view(okBytes)

  private final val longString          = new String(Array.fill(2000)('a'))
  private final val longStringBytes     = longString.getBytes(UTF_8)
  private final val longStringBitVector = BitVector.view(longStringBytes)

  @Benchmark def decode_ok_baseline_charset: String      = UTF_8.decode(ByteBuffer.wrap(okBytes)).toString
  @Benchmark def decode_ok_baseline_string: String       = new String(okBytes, UTF_8)
  @Benchmark def decode_ok_default_utf8: Attempt[String] = defaultUtf8.decodeValue(okBitVector)
  @Benchmark def decode_ok_lenient_utf8: Attempt[String] = lenientUtf8.decodeValue(okBitVector)

  @Benchmark def decode_long_string_baseline_charset: String      = UTF_8.decode(ByteBuffer.wrap(longStringBytes)).toString
  @Benchmark def decode_long_string_baseline_string: String       = new String(longStringBytes, UTF_8)
  @Benchmark def decode_long_string_default_utf8: Attempt[String] = defaultUtf8.decodeValue(longStringBitVector)
  @Benchmark def decode_long_string_lenient_utf8: Attempt[String] = lenientUtf8.decodeValue(longStringBitVector)

  @Benchmark def encode_ok_baseline_charset: ByteBuffer       = UTF_8.encode(ok)
  @Benchmark def encode_ok_baseline_string: scala.Array[Byte] = ok.getBytes(UTF_8)
  @Benchmark def encode_ok_default_utf8: Attempt[BitVector]   = defaultUtf8.encode(ok)
  @Benchmark def encode_ok_lenient_utf8: Attempt[BitVector]   = lenientUtf8.encode(ok)

  @Benchmark def encode_long_string_baseline_charset: ByteBuffer       = UTF_8.encode(longString)
  @Benchmark def encode_long_string_baseline_string: scala.Array[Byte] = longString.getBytes(UTF_8)
  @Benchmark def encode_long_string_default_utf8: Attempt[BitVector]   = defaultUtf8.encode(longString)
  @Benchmark def encode_long_string_lenient_utf8: Attempt[BitVector]   = lenientUtf8.encode(longString)
} 
Example 15
Source File: RESPFrameBench.scala    From laserdisc   with MIT License 5 votes vote down vote up
package laserdisc
package protocol

import org.openjdk.jmh.annotations.{Benchmark, Scope, State}
import scodec.bits.BitVector
import eu.timepit.refined.types.string.NonEmptyString
import java.nio.ByteBuffer

import laserdisc.RESPFrameFixture
import org.openjdk.jmh.infra.Blackhole

@State(Scope.Benchmark)
class RESPFrameBench extends RESPFrameFixture {

  val mixedNoArr = bytesOf(mixedNoArrList)
  val arrOneLevel = bytesOf(arrOneLevelList)
  val arrFiveLevels = bytesOf(arrFiveLevelsList)

  val empty = BitVector.empty.toByteBuffer
  val mixedNoArrFull = BitVector(mixedNoArr).toByteBuffer
  val arrOneLevelFull = BitVector(arrOneLevel).toByteBuffer
  val arrFiveLevelsFull = BitVector(arrFiveLevels).toByteBuffer

  @Benchmark def frameOfFullBaseline(bh: Blackhole)= {
    val frame = EmptyFrame.append(empty)
    bh.consume(frame)
  }
  @Benchmark def frameOfMixedNoArrFull(bh: Blackhole) = {
    val frame = EmptyFrame.append(mixedNoArrFull)
    bh.consume(frame)
  }
  @Benchmark def frameOfMixedArrOneLevelFull(bh: Blackhole) = {
    val frame = EmptyFrame.append(arrOneLevelFull)
    bh.consume(frame)
  }
  @Benchmark def frameOfMixedArrFiveLevelsFull(bh: Blackhole) = {
    val frame = EmptyFrame.append(arrFiveLevelsFull)
    bh.consume(frame)
  }

  val mixedNoArrSmallChunkBuffers    = groupInChunks(mixedNoArr, 128)
  val arrOneLevelSmallChunkBuffers   = groupInChunks(arrOneLevel, 128)
  val arrFiveLevelsSmallChunkBuffers = groupInChunks(arrFiveLevels, 128)

  @Benchmark def frameOfChunkedBaseline(bh: Blackhole)= {
    val frames = appendChunks(Iterator.empty[BitVector])
    bh.consume(frames)
  }
  @Benchmark def frameOfChunkedShortMixedNoArr(bh: Blackhole)= {
    val frames = appendChunks(mixedNoArrSmallChunkBuffers)
    bh.consume(frames)
  }
  @Benchmark def frameOfChunkedShortArrOneLevel(bh: Blackhole)   = {
    val frames = appendChunks(arrOneLevelSmallChunkBuffers)
    bh.consume(frames)
  }
  @Benchmark def frameOfChunkedShortArrFiveLevels(bh: Blackhole) = {
    val frames = appendChunks(arrFiveLevelsSmallChunkBuffers)
    bh.consume(frames)
  }

  val mixedNoArrBigChunkBuffers    = groupInChunks(mixedNoArr, 1024)
  val arrOneLevelBigChunkBuffers   = groupInChunks(arrOneLevel, 1024)
  val arrFiveLevelsBigChunkBuffers = groupInChunks(arrFiveLevels, 1024)

  @Benchmark def frameOfChunkedLongMixedNoArr(bh: Blackhole)    = {
    val frames = appendChunks(mixedNoArrBigChunkBuffers)
    bh.consume(frames)
  }
  @Benchmark def frameOfChunkedLongArrOneLevel(bh: Blackhole)   = {
    val frames = appendChunks(arrOneLevelBigChunkBuffers)
    bh.consume(frames)
  }
  @Benchmark def frameOfChunkedLongArrFiveLevels(bh: Blackhole) = {
    val frames = appendChunks(arrFiveLevelsBigChunkBuffers)
    bh.consume(frames)
  }
} 
Example 16
Source File: RESPFrame.scala    From laserdisc   with MIT License 5 votes vote down vote up
package laserdisc
package protocol

import java.nio.ByteBuffer

import laserdisc.protocol.BitVectorDecoding._
import laserdisc.protocol.RESP.stateOf
import scodec.bits.BitVector

import scala.annotation.tailrec

private[laserdisc] sealed trait RESPFrame extends Product with Serializable with EitherSyntax with BitVectorSyntax {
  def append(bytes: ByteBuffer): Exception | NonEmptyRESPFrame = nextFrame(BitVector.view(bytes))
  protected final def nextFrame(bits: BitVector): Exception | NonEmptyRESPFrame =
    stateOf(bits)
      .flatMap {
        case MissingBits(n)              => Right(IncompleteFrame(bits, n))
        case Incomplete                  => Right(IncompleteFrame(bits, 0L))
        case Complete                    => Right(CompleteFrame(bits))
        case CompleteWithRemainder(c, r) => consumeRemainder(Right(MoreThanOneFrame(Vector(CompleteFrame(c)), r)))
      }
      .leftMap(e => UnknownBufferState(s"Err building the frame from buffer: $e. Content: ${bits.tailToUtf8}"))

  @tailrec private[this] final def consumeRemainder(current: String | MoreThanOneFrame): String | MoreThanOneFrame =
    current match {
      case Right(s) =>
        stateOf(s.remainder) match {
          case Left(ee)                           => Left(ee)
          case Right(CompleteWithRemainder(c, r)) => consumeRemainder(Right(MoreThanOneFrame(s.complete :+ CompleteFrame(c), r)))
          case Right(Complete)                    => Right(MoreThanOneFrame(s.complete :+ CompleteFrame(s.remainder), BitVector.empty))
          case _                                  => Right(s)
        }
      case left => left
    }
}

private[laserdisc] case object EmptyFrame        extends RESPFrame
private[protocol] sealed trait NonEmptyRESPFrame extends RESPFrame

private[laserdisc] final case class CompleteFrame(bits: BitVector) extends NonEmptyRESPFrame
private[laserdisc] final case class MoreThanOneFrame(private[laserdisc] val complete: Vector[CompleteFrame], remainder: BitVector)
    extends NonEmptyRESPFrame
private[laserdisc] final case class IncompleteFrame(partial: BitVector, bitsToComplete: Long) extends NonEmptyRESPFrame {
  override def append(bytes: ByteBuffer): Exception | NonEmptyRESPFrame = {
    val newBits = BitVector.view(bytes)
    //  Saves some size checks
    if (bitsToComplete > 0 && bitsToComplete == newBits.size) Right(CompleteFrame(partial ++ newBits))
    else nextFrame(partial ++ newBits)
  }
}

private[laserdisc] final case class UnknownBufferState(message: String) extends laserdisc.Platform.LaserDiscRespFrameError(message) 
Example 17
Source File: RESPFunctionsSpec.scala    From laserdisc   with MIT License 5 votes vote down vote up
package laserdisc
package protocol

import laserdisc.protocol.BitVectorDecoding.{Complete, CompleteWithRemainder, Incomplete, MissingBits}
import scodec.bits.BitVector

final class RESPFunctionsSpec extends BaseSpec {

  test("A RESP codec checking the state of a bit vector with the size prefix not complete gives IncompleteVector") {
    assertEquals(RESP.stateOf(BitVector("$2362".getBytes)), Incomplete)
  }

  test("A RESP codec checking the state of a bit vector with only the data type selector gives IncompleteVector") {
    assertEquals(RESP.stateOf(BitVector("$".getBytes)), Incomplete)
  }

  test("A RESP codec checking the state of a bit vector that's complete gives CompleteVector") {
    assertEquals(RESP.stateOf(BitVector("$16\r\nTest bulk string\r\n".getBytes)), Complete)
  }

  test(
    "A RESP codec checking the state of a bit vector with the size prefix complete and an incomplete payload gives MissingBits with the correct number of bits missing"
  ) {
    assertEquals(RESP.stateOf(BitVector("$40\r\nIncomplete test bulk string".getBytes)), MissingBits(120))
  }

  test("A RESP codec checking the state of a bit vector that represents an empty bulk gives CompleteVector") {
    assertEquals(RESP.stateOf(BitVector("$-1\r\n".getBytes)), Complete)
  }

  test("A RESP codec checking the state of an incomplete bit vector that represents an empty bulk gives MissingBits") {
    assertEquals(RESP.stateOf(BitVector("$-".getBytes)), Incomplete)
  }

  test(
    "A RESP codec checking the state of a bulk bit vector that contains one message complete and one not complete gives CompleteWithRemainder"
  ) {
    assertEquals(
      RESP.stateOf(BitVector("$16\r\nTest bulk string\r\n$16\r\nTest bulk".getBytes)),
      CompleteWithRemainder(
        BitVector("$16\r\nTest bulk string\r\n".toCharArray.map(_.toByte)),
        BitVector("$16\r\nTest bulk".toCharArray.map(_.toByte))
      )
    )
  }

  test("A RESP codec checking the state of a bulk bit vector that contains more than one complete messages gives CompleteWithRemainder") {
    assertEquals(
      RESP.stateOf(BitVector("$16\r\nTest bulk string\r\n$16\r\nTest bulk string\r\n$16\r\nTest bulk string\r\n".getBytes)),
      CompleteWithRemainder(
        BitVector("$16\r\nTest bulk string\r\n".toCharArray.map(_.toByte)),
        BitVector("$16\r\nTest bulk string\r\n$16\r\nTest bulk string\r\n".toCharArray.map(_.toByte))
      )
    )
  }

  test("A RESP codec checking the state of a bulk bit vector that contains more than one null message gives CompleteWithRemainder") {
    assertEquals(
      RESP.stateOf(BitVector("$-1\r\n$-1\r\n$-1\r\n".getBytes)),
      CompleteWithRemainder(
        BitVector("$-1\r\n".toCharArray.map(_.toByte)),
        BitVector("$-1\r\n$-1\r\n".toCharArray.map(_.toByte))
      )
    )
  }
} 
Example 18
Source File: RESPFrameMixedSpec.scala    From laserdisc   with MIT License 5 votes vote down vote up
package laserdisc
package protocol

import org.scalacheck.Prop.forAll
import scodec.bits.BitVector

final class RESPFrameMixedSpec extends RESPFrameFixture {

  test(
    "Appending to a non empty mixed frame a bit vector composed of a complete sequence of integers, simple strings, bulk strings and errors gives MoreThanOne with a list of all the complete items"
  ) {
    val nonEmptyFrame = IncompleteFrame(BitVector("$16\r\nTest bulk str".getBytes), 0)
    val inputVector = BitVector(
      "ing\r\n+OK\r\n$0\r\n\r\n+Another simple string\r\n*3\r\n$16\r\nTest bulk string\r\n:100\r\n+A simple string\r\n-Possible error message\r\n*0\r\n:1\r\n:2\r\n*2\r\n$8\r\nAnother1\r\n-An error\r\n:177\r\n+Another simple string\r\n$21\r\nTest bulk string 1 11\r\n*5\r\n$16\r\nTest bulk string\r\n:13\r\n-1234 An error with numbers\r\n:100\r\n+A simple string\r\n-And an error message\r\n".getBytes
    )
    nonEmptyFrame.append(inputVector.toByteBuffer) onRightAll {
      case r @ MoreThanOneFrame(_, _) =>
        assertEquals(
          r.complete,
          Vector(
            CompleteFrame(BitVector("$16\r\nTest bulk string\r\n".getBytes())),
            CompleteFrame(BitVector("+OK\r\n".getBytes())),
            CompleteFrame(BitVector("$0\r\n\r\n".getBytes())),
            CompleteFrame(BitVector("+Another simple string\r\n".getBytes())),
            CompleteFrame(BitVector("*3\r\n$16\r\nTest bulk string\r\n:100\r\n+A simple string\r\n".getBytes)),
            CompleteFrame(BitVector("-Possible error message\r\n".getBytes())),
            CompleteFrame(BitVector("*0\r\n".getBytes())),
            CompleteFrame(BitVector(":1\r\n".getBytes())),
            CompleteFrame(BitVector(":2\r\n".getBytes())),
            CompleteFrame(BitVector("*2\r\n$8\r\nAnother1\r\n-An error\r\n".getBytes)),
            CompleteFrame(BitVector(":177\r\n".getBytes())),
            CompleteFrame(BitVector("+Another simple string\r\n".getBytes())),
            CompleteFrame(BitVector("$21\r\nTest bulk string 1 11\r\n".getBytes())),
            CompleteFrame(
              BitVector(
                "*5\r\n$16\r\nTest bulk string\r\n:13\r\n-1234 An error with numbers\r\n:100\r\n+A simple string\r\n".getBytes
              )
            ),
            CompleteFrame(BitVector("-And an error message\r\n".getBytes()))
          )
        )
      case _ => fail(s"expected a MoreThanOne type")
    }
  }

  test(
    "Appending to a non empty mixed frame a bit vector composed of sequence of integers, simple strings, bulk strings and errors that are not complete gives MoreThanOne with a list of all the complete items plus the remainder"
  ) {
    val nonEmptyFrame = IncompleteFrame(BitVector("$16\r\nTest bulk str".getBytes), 0)
    val inputVector = BitVector(
      "ing\r\n+OK\r\n+Another simple string\r\n-Possible error message\r\n:1\r\n:2\r\n:177\r\n+Another simple string\r\n$21\r\nTest bulk string 1 11\r\n-And an error message\r\n".getBytes
    )
    nonEmptyFrame.append(inputVector.toByteBuffer) onRightAll {
      case r @ MoreThanOneFrame(_, _) =>
        assertEquals(
          r.complete,
          Vector(
            CompleteFrame(BitVector("$16\r\nTest bulk string\r\n".getBytes())),
            CompleteFrame(BitVector("+OK\r\n".getBytes())),
            CompleteFrame(BitVector("+Another simple string\r\n".getBytes())),
            CompleteFrame(BitVector("-Possible error message\r\n".getBytes())),
            CompleteFrame(BitVector(":1\r\n".getBytes())),
            CompleteFrame(BitVector(":2\r\n".getBytes())),
            CompleteFrame(BitVector(":177\r\n".getBytes())),
            CompleteFrame(BitVector("+Another simple string\r\n".getBytes())),
            CompleteFrame(BitVector("$21\r\nTest bulk string 1 11\r\n".getBytes())),
            CompleteFrame(BitVector("-And an error message\r\n".getBytes()))
          )
        )
      case _ => fail(s"expected a MoreThanOne type")
    }
  }

  property("Appending to an empty frame a random sequence of complete messages gives MoreThanOne with all the complete items") {
    forAll { testSet: OneOrMore[ProtocolEncoded] =>
      val vector = BitVector(testSet.value.map(_.encoded).mkString.getBytes)

      EmptyFrame.append(vector.toByteBuffer) onRightAll {
        case MoreThanOneFrame(complete, remainder) =>
          assertEquals(complete.size, testSet.value.size)
          assert(remainder.isEmpty)
        case CompleteFrame(_) => succeed
        case other            => fail(s"expected a MoreThanOne type. Was $other")
      }
    }
  }
} 
Example 19
Source File: StreamingSpec.scala    From seals   with Apache License 2.0 5 votes vote down vote up
package com.example.streaming

import java.io.{ ByteArrayInputStream, ByteArrayOutputStream }

import shapeless.record._

import cats.effect.IO

import org.scalatest.matchers.should.Matchers
import org.scalatest.flatspec.AnyFlatSpec

import fs2.Stream

import scodec.Codec
import scodec.bits.BitVector
import scodec.stream.CodecError

import dev.tauri.seals._
import dev.tauri.seals.scodec.Codecs._
import dev.tauri.seals.scodec.StreamCodecs._

class StreamingSpec extends AnyFlatSpec with Matchers {

  import Main.{ Animal, Elephant, Quokka, Quagga, Grey }

  val animals = Vector[Animal](
    Elephant("Dumbo", tuskLength = 35.0f),
    Quokka("Nellie"),
    Quagga("Ford", speed = 120.0)
  )

  val transformedAnimals = Vector[Animal](
    Elephant("Dumbo", tuskLength = 35.0f + 17.0f),
    Quokka("Nellie", Grey)
  )

  val animalStream = Stream.emits[IO, Animal](animals)

  val encoder = streamEncoderFromReified[Animal]
  val decoder = streamDecoderFromReified[Animal]

  "Encoding/decoding" should "work correctly" in {
    val tsk: IO[Unit] = for {
      bv <- encoder.encode[IO](animalStream).compile.fold(BitVector.empty)(_ ++ _)
      as <- decoder.decode[IO](Stream(bv)).compile.toVector
    } yield {
      as should === (animals)
    }
    tsk.unsafeRunSync()
  }

  it should "fail with incompatible models" in {
    val mod = Reified[Record.`'Elephant -> Elephant, 'Quokka -> Quokka`.T].model
    val bv: BitVector = Codec[Model].encode(mod).getOrElse(fail)
    val tsk: IO[Unit] = for {
      as <- decoder.decode[IO](Stream(bv)).compile.toVector
    } yield {
      as should === (Vector.empty)
    }

    val ex = intercept[CodecError] {
      tsk.unsafeRunSync()
    }
    ex.err.message should include ("incompatible models")
  }

  "Transformation" should "work correctly" in {
    val tsk: IO[Unit] = for {
      ibv <- encoder.encode[IO](animalStream).compile.fold(BitVector.empty)(_ ++ _)
      is = new ByteArrayInputStream(ibv.toByteArray)
      os = new ByteArrayOutputStream
      _ <- Main.transform(is, os)(Main.transformer)
      obv = BitVector(os.toByteArray())
      transformed <- decoder.decode[IO](Stream(obv)).compile.fold(Vector.empty[Animal])(_ :+ _)
    } yield {
      transformed should === (transformedAnimals)
    }
    tsk.unsafeRunSync()
  }
} 
Example 20
Source File: RlpEncoded.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.codec.rlp

import scodec.bits.{BitVector, ByteVector}

// normally we construct `RlpEncoded` via rlp encoding
// to avoid dumb problems
final class RlpEncoded private (val bits: BitVector) extends AnyVal {
  def bytes: ByteVector = bits.bytes

  def byteArray: Array[Byte] = bits.toByteArray

  def decoded[A](implicit codec: RlpCodec[A]): Either[Throwable, A] =
    codec.decode(bits).toEither match {
      case Left(err)     => Left(new Exception(err.messageWithContext))
      case Right(result) => Right(result.value)
    }

  def isItem: Boolean =
    bits.bytes.headOption match {
      case Some(byte) => (0xff & byte) < RlpCodecHelper.listOffset
      case None       => false
    }

  def isList: Boolean =
    !isItem

  def isEmptyItem: Boolean =
    this == RlpEncoded.emptyItem

  def isEmptyList: Boolean =
    this == RlpEncoded.emptyList

  override def toString: String = s"RlpEncoded(${bits.bytes})"
}

object RlpEncoded {
  def coerce(bits: BitVector): RlpEncoded = new RlpEncoded(bits)

  val emptyItem: RlpEncoded = RlpEncoded.coerce(BitVector(RlpCodecHelper.itemOffset.toByte))

  val emptyList: RlpEncoded = RlpEncoded.coerce(BitVector(RlpCodecHelper.listOffset.toByte))
} 
Example 21
Source File: LowerPriorityRlpCodec.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.codec.rlp

import magnolia._
import scodec._
import scodec.bits.BitVector

trait LowerPriorityRlpCodec {
  type Typeclass[A] = RlpCodec[A]

  def combine[A](ctx: CaseClass[RlpCodec, A]): RlpCodec[A] = {
    val codec = new Codec[A] {
      override def encode(value: A): Attempt[BitVector] =
        Attempt.successful {
          ctx.parameters.foldLeft(BitVector.empty)((acc, cur) => acc ++ cur.typeclass.encode(cur.dereference(value)).require)
        }

      override def decode(bits: BitVector): Attempt[DecodeResult[A]] = {
        val (fields, remainder) = ctx.parameters.foldLeft((List.empty[Any], bits)) {
          case ((acc, bits), cur) =>
            val v = cur.typeclass.decode(bits).require
            (v.value :: acc, v.remainder)
        }
        Attempt.successful(DecodeResult(ctx.rawConstruct(fields.reverse), remainder))
      }

      override def sizeBound: SizeBound =
        ctx.parameters match {
          case head :: _ =>
            ctx.parameters.foldLeft(head.typeclass.sizeBound)((acc, cur) => acc + cur.typeclass.sizeBound)
          case Nil =>
            SizeBound.unknown
        }

      override def toString: String =
        s"${ctx.typeName.short}(${ctx.parameters.map(p => s"${p.label}").mkString(",")})"
    }

    if (ctx.isValueClass) {
      RlpCodecHelper.fromCodec(PrefixType.NoPrefix, codec)
    } else {
      RlpCodecHelper.fromCodec(PrefixType.ListLenPrefix, codec)
    }
  }

  def dispatch[A](ctx: SealedTrait[RlpCodec, A]): RlpCodec[A] = {
    val m1 = ctx.subtypes.zipWithIndex.map(_.swap).toMap
    val m2 = ctx.subtypes.zipWithIndex.toMap
    val codec = new Codec[A] {
      override def encode(value: A): Attempt[BitVector] =
        ctx.dispatch(value)(sub => {
          val bits = codecs.uint8.encode(m2(sub)).require
          sub.typeclass.encode(sub.cast(value)).map(v => bits ++ v)
        })

      override def decode(bits: BitVector): Attempt[DecodeResult[A]] =
        codecs.uint8.decode(bits).flatMap { result =>
          m1.get(result.value) match {
            case Some(sub) => sub.typeclass.decode(result.remainder)
            case None      => Attempt.failure(Err(s"decode ADT failure, can not find its subtype instance of ${result.value}"))
          }
        }

      override def sizeBound: SizeBound = SizeBound.unknown
    }

    RlpCodecHelper.fromCodec(PrefixType.ItemLenPrefix, codec)
  }

  implicit def gen[A]: RlpCodec[A] = macro Magnolia.gen[A]
} 
Example 22
Source File: RlpCodec.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.codec.rlp

import scodec._
import scodec.bits.BitVector

// we are cheating here...
// do not use methods other than encode & decode
trait RlpCodec[A] extends Codec[A] {
  override def sizeBound: SizeBound = SizeBound.unknown
}

object RlpCodec extends RlpCodecInstances {
  def apply[A](implicit ev: RlpCodec[A]): RlpCodec[A] = ev

  def isItemPrefix(bits: BitVector): Boolean =
    bits.bytes.headOption match {
      case Some(byte) => (0xff & byte) < RlpCodecHelper.listOffset
      case None       => false
    }

  def isEmptyPrefix(bits: BitVector): Boolean =
    bits.bytes.headOption match {
      case Some(byte) => byte == RlpCodecHelper.itemOffset.toByte
      case None       => false
    }
} 
Example 23
Source File: BinaryCodec.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.sdk

import jbok.codec.rlp.RlpEncoded
import jbok.codec.rlp.implicits._
import jbok.core.models.{BlockHeader, SignedTransaction}
import scodec.bits.BitVector

import scala.scalajs.js
import scala.scalajs.js.JSConverters._
import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
import scala.scalajs.js.typedarray.Int8Array

@JSExportTopLevel("BinaryCodec")
@JSExportAll
object BinaryCodec {
  def encodeBlockHeader(header: BlockHeader): Int8Array =
    new Int8Array(header.encoded.byteArray.toJSArray)

  def decodeBlockHeader(bytes: Int8Array): js.UndefOr[BlockHeader] =
    RlpEncoded.coerce(BitVector(bytes.toArray)).decoded[BlockHeader].toOption.orUndefined

  def encodeTx(tx: SignedTransaction): Int8Array =
    new Int8Array(tx.encoded.byteArray.toJSArray)

  def decodeTx(bytes: Int8Array): js.UndefOr[SignedTransaction] =
    RlpEncoded.coerce(BitVector(bytes.toArray)).decoded[SignedTransaction].toOption.orUndefined
} 
Example 24
Source File: Implicits.scala    From xenomorph   with GNU Lesser General Public License v3.0 5 votes vote down vote up
package xenomorph.scodec

import scodec.bits.BitVector
import scodec.codecs.implicits._
import scodec.{Attempt, Codec, Decoder, Encoder, _}
import xenomorph.Schema.Schema
import xenomorph.json.JType.JSchema
import xenomorph.json._

import scalaz.~>

object Implicits {

  implicit val toEncoder: ToEncoder[JSchema] = new ToEncoder[JSchema] { self =>
    override val toEncoder = new (JSchema ~> Encoder) {
      def apply[A](s: JSchema[A]): Encoder[A] = s.unmutu match {
        case JNullT()    => Encoder(_ => Attempt.successful(BitVector.empty))
        case JBoolT()    => implicitly[Encoder[Boolean]]
        case JByteT()    => implicitly[Encoder[Byte]]
        case JShortT()   => implicitly[Encoder[Short]]
        case JIntT()     => implicitly[Encoder[Int]]
        case JLongT()    => implicitly[Encoder[Long]]
        case JFloatT()   => implicitly[Encoder[Float]]
        case JDoubleT()  => implicitly[Encoder[Double]]
        case JCharT()    => implicitly[Encoder[Byte]].xmap((_: Byte).toChar, (_: Char).toByte)
        case JStrT()     => implicitly[Encoder[String]]
        case arr: JArrayT[Schema[JSchema, ?], i] =>
          val baseEncoder: Encoder[i] = ToEncoder.schemaToEncoder[JSchema](self).toEncoder(arr.elem)
          implicit val codec = Codec[i](baseEncoder, null)
          implicitly[Encoder[Vector[i]]]
      }
    }
  }

  implicit val toDecoder: ToDecoder[JSchema] = new ToDecoder[JSchema] { self =>
    override val toDecoder = new (JSchema ~> Decoder) {
      def apply[A](s: JSchema[A]): Decoder[A] = s.unmutu match {
        case JNullT()    => Decoder.point(())
        case JBoolT()    => implicitly[Decoder[Boolean]]
        case JByteT()    => implicitly[Decoder[Byte]]
        case JShortT()   => implicitly[Decoder[Short]]
        case JIntT()     => implicitly[Decoder[Int]]
        case JLongT()    => implicitly[Decoder[Long]]
        case JFloatT()   => implicitly[Decoder[Float]]
        case JDoubleT()  => implicitly[Decoder[Double]]
        case JCharT()    => implicitly[Decoder[Byte]].xmap((_: Byte).toChar, (_: Char).toByte)
        case JStrT()     => implicitly[Decoder[String]]
        case arr: JArrayT[Schema[JSchema, ?], i] =>
          val baseDecoder: Decoder[i] = ToDecoder.schemaToDecoder[JSchema](self).toDecoder(arr.elem)
          implicit val codec = Codec[i](null, baseDecoder)
          implicitly[Codec[Vector[i]]].asDecoder
      }
    }
  }

} 
Example 25
Source File: Server.scala    From seals   with Apache License 2.0 5 votes vote down vote up
package com.example.server

import java.net.{ InetSocketAddress, InetAddress }
import java.nio.channels.AsynchronousChannelGroup
import java.util.concurrent.Executors

import scala.concurrent.duration._

import cats.implicits._
import cats.effect.{ IO, IOApp, ExitCode, Resource, Blocker }

import fs2.{ Stream, Chunk }
import fs2.io.tcp

import scodec.bits.BitVector
import scodec.Codec

import dev.tauri.seals.scodec.Codecs._

import com.example.proto._

object Server extends IOApp {

  final val bufferSize = 32 * 1024
  final val timeout = Some(2.seconds)
  final val maxClients = 200
  final val port = 8080

  val rnd = new scala.util.Random

  def addr(port: Int): InetSocketAddress =
    new InetSocketAddress(InetAddress.getLoopbackAddress, port)

  override def run(args: List[String]): IO[ExitCode] = {
    Blocker[IO].use { bl =>
      tcp.SocketGroup[IO](bl).use { sg =>
        serve(port, sg).compile.drain.as(ExitCode.Success)
      }
    }
  }

  def serve(port: Int, sg: tcp.SocketGroup): Stream[IO, Unit] = {
    Stream.resource(sg.serverResource[IO](addr(port))).flatMap {
      case (localAddr, sockets) =>
        val s = sockets.map { socket =>
          Stream.resource(socket).flatMap { socket =>
            val bvs: Stream[IO, BitVector] = socket.reads(bufferSize, timeout).chunks.map(ch => BitVector.view(ch.toArray))
            val tsk: IO[BitVector] = bvs.compile.toVector.map(_.foldLeft(BitVector.empty)(_ ++ _))
            val request: IO[Request] = tsk.flatMap { bv =>
              Codec[Request].decode(bv).fold(
                err => IO.raiseError(new Exception(err.toString)),
                result => IO.pure(result.value)
              )
            }
            val response: IO[Response] = request.flatMap(logic)
            val encoded: Stream[IO, Byte] = Stream.eval(response)
              .map(r => Codec[Response].encode(r).require)
              .flatMap { bv => Stream.chunk(Chunk.bytes(bv.bytes.toArray)) }
            encoded.through(socket.writes(timeout)).onFinalize(socket.endOfOutput)
          }
        }
        s.parJoin[IO, Unit](maxClients)
    }
  }

  def logic(req: Request): IO[Response] = req match {
    case RandomNumber(min, max) =>
      if (min < max) {
        IO {
          val v = rnd.nextInt(max - min + 1) + min
          Number(v)
        }
      } else if (min === max) {
        IO.pure(Number(min))
      } else {
        IO.raiseError(new IllegalArgumentException("min must not be greater than max"))
      }
    case ReSeed(s) =>
      IO {
        rnd.setSeed(s)
        Ok
      }
  }
} 
Example 26
Source File: Client.scala    From seals   with Apache License 2.0 5 votes vote down vote up
package com.example.lib

import java.net.{ InetAddress, InetSocketAddress }

import scala.concurrent.Future
import scala.concurrent.Await
import scala.concurrent.duration._

import cats.effect.{ IO, ContextShift }

import akka.NotUsed
import akka.actor.ActorSystem
import akka.stream._
import akka.stream.scaladsl._
import akka.util.{ ByteString }

import scodec.bits.BitVector
import scodec.stream.{ StreamEncoder, StreamDecoder }

import fs2.interop.reactivestreams._

import dev.tauri.seals.scodec.StreamCodecs._
import dev.tauri.seals.scodec.StreamCodecs.{ pipe => decPipe }

import Protocol.v1.{ Request, Response, Seed, Random }

object Client {

  val reqCodec: StreamEncoder[Request] = streamEncoderFromReified[Request]
  val resCodec: StreamDecoder[Response] = streamDecoderFromReified[Response]

  def main(args: Array[String]): Unit = {
    implicit val sys: ActorSystem = ActorSystem("ClientSystem")
    implicit val mat: Materializer = ActorMaterializer()
    try {
      val resp = Await.result(client(1234), 10.seconds)
      println(resp)
    } finally {
      sys.terminate()
    }
  }

  def client(port: Int)(implicit sys: ActorSystem, mat: Materializer): Future[Vector[Response]] = {
    val addr = new InetSocketAddress(InetAddress.getLoopbackAddress, port)
    Tcp().outgoingConnection(addr).joinMat(logic)(Keep.right).run()
  }

  def logic(implicit sys: ActorSystem): Flow[ByteString, ByteString, Future[Vector[Response]]] = {

    implicit val cs: ContextShift[IO] = IO.contextShift(sys.dispatcher)

    val requests = fs2.Stream(Seed(0xabcdL), Random(1, 100)).covary[IO]
    val source = Source
      .fromPublisher(reqCodec.encode(requests).toUnicastPublisher())
      .map(bv => ByteString.fromArrayUnsafe(bv.toByteArray))

    // TODO: this would be much less ugly, if we had a decoder `Flow`
    val buffer = fs2.concurrent.Queue.unbounded[IO, Option[BitVector]].unsafeRunSync()
    val decode: Flow[ByteString, Response, NotUsed] = Flow.fromSinkAndSource(
      Sink.onComplete { _ =>
        buffer.enqueue1(None).unsafeRunSync()
      }.contramap[ByteString] { x =>
        buffer.enqueue1(Some(BitVector.view(x.toArray))).unsafeRunSync()
      },
      Source.fromPublisher(buffer
        .dequeue
        .unNoneTerminate
        .through(decPipe[IO, Response])
        .toUnicastPublisher()
      )
    )
    val sink: Sink[ByteString, Future[Vector[Response]]] = decode.toMat(
      Sink.fold(Vector.empty[Response])(_ :+ _)
    )(Keep.right)

    Flow.fromSinkAndSourceMat(sink, source)(Keep.left)
  }
} 
Example 27
Source File: Server.scala    From seals   with Apache License 2.0 5 votes vote down vote up
package com.example.lib

import java.net.{ InetSocketAddress, InetAddress }

import scala.concurrent.duration._

import cats.implicits._
import cats.effect.{ IO, IOApp, ExitCode, Blocker }

import fs2.{ Stream, Chunk }
import fs2.io.tcp

import scodec.bits.BitVector
import scodec.stream.{ StreamEncoder, StreamDecoder }

import dev.tauri.seals.scodec.StreamCodecs._
import dev.tauri.seals.scodec.StreamCodecs.{ pipe => decPipe }

import Protocol.v1.{ Request, Response, Random, Seed, RandInt, Seeded }

object Server extends IOApp {

  final val bufferSize = 32 * 1024
  final val timeout = Some(2.seconds)
  final val maxClients = 200

  val rnd = new scala.util.Random

  def addr(port: Int): InetSocketAddress =
    new InetSocketAddress(InetAddress.getLoopbackAddress, port)

  val reqCodec: StreamDecoder[Request] = streamDecoderFromReified[Request]
  val resCodec: StreamEncoder[Response] = streamEncoderFromReified[Response]

  override def run(args: List[String]): IO[ExitCode] = {
    Blocker[IO].use { bl =>
      tcp.SocketGroup[IO](bl).use { sg =>
        serve(1234, sg).compile.drain.as(ExitCode.Success)
      }
    }
  }

  def serve(port: Int, sg: tcp.SocketGroup): Stream[IO, Unit] =
    serveAddr(port, sg).as(())

  def serveAddr(port: Int, sg: tcp.SocketGroup): Stream[IO, InetSocketAddress] = {
    Stream.resource(sg.serverResource[IO](addr(port))).flatMap {
      case (localAddr, sockets) =>
        val x = sockets.flatMap { socket =>
          Stream.resource(socket).map { socket =>
            val bvs: Stream[IO, BitVector] = socket.reads(bufferSize, timeout).chunks.map(ch => BitVector.view(ch.toArray))
            val requests: Stream[IO, Request] = bvs.through(decPipe[IO, Request])
            val responses: Stream[IO, Response] = requests.flatMap(req => Stream.eval(logic(req)))
            val encoded: Stream[IO, Byte] = resCodec.encode(responses).flatMap { bv =>
              Stream.chunk(Chunk.bytes(bv.bytes.toArray))
            }

            encoded.through(socket.writes(timeout)).onFinalize(socket.endOfOutput)
          }
        }

        Stream.emit(localAddr) ++ x.parJoin(maxClients).drain
    }
  }

  def logic(req: Request): IO[Response] = req match {
    case Random(min, max) =>
      if (min < max) {
        IO {
          val v = rnd.nextInt(max - min + 1) + min
          RandInt(v)
        }
      } else if (min === max) {
        IO.pure(RandInt(min))
      } else {
        IO.raiseError(new IllegalArgumentException("min must not be greater than max"))
      }
    case Seed(s) =>
      IO {
        rnd.setSeed(s)
        Seeded
      }
  }
} 
Example 28
Source File: testkit.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.codec

import jbok.codec.rlp.RlpCodec
import jbok.codec.rlp.implicits._
import org.scalatest.{Assertion, Matchers}
import scodec.bits.{BitVector, ByteVector}
import scodec.{Attempt, DecodeResult, Err}

object testkit extends testkit
trait testkit extends Matchers {
  def roundtripAndMatch[A](a: A, expected: ByteVector)(implicit c: RlpCodec[A]): Assertion = {
    roundtrip[A](a)
    a.encoded.bits.bytes shouldBe expected
  }

  def roundtripLen[A](a: A, expectedNumBytes: Int)(implicit c: RlpCodec[A]): Assertion = {
    roundtrip[A](a)
    a.encoded.bits.bytes.length shouldBe expectedNumBytes
  }

  def roundtrip[A](a: A)(implicit c: RlpCodec[A]): Assertion =
    roundtrip(c, a)

  def roundtrip[A](codec: RlpCodec[A], value: A): Assertion = {
    val encoded = codec.encode(value)
    encoded.isSuccessful shouldBe true
    val Attempt.Successful(DecodeResult(decoded, remainder)) = codec.decode(encoded.require)
    remainder shouldBe BitVector.empty
    decoded shouldBe value
  }

  def roundtripAll[A](codec: RlpCodec[A], as: collection.Iterable[A]): Unit =
    as foreach { a =>
      roundtrip(codec, a)
    }

  def encodeError[A](codec: RlpCodec[A], a: A, err: Err): Assertion = {
    val encoded = codec.encode(a)
    encoded shouldBe Attempt.Failure(err)
  }

  def shouldDecodeFullyTo[A](codec: RlpCodec[A], buf: BitVector, expected: A): Assertion = {
    val Attempt.Successful(DecodeResult(actual, rest)) = codec decode buf
    rest shouldBe BitVector.empty
    actual shouldBe expected
  }
} 
Example 29
Source File: Mnemonic.scala    From EncryCore   with GNU General Public License v3.0 5 votes vote down vote up
package encry.utils

import org.encryfoundation.common.utils.Algos
import scodec.bits.BitVector
import scala.io.Source

object Mnemonic {

  def getWords: Array[String] =
    Source.fromInputStream(getClass.getResourceAsStream("/languages/english/words.txt")).getLines.toArray

  def seedFromMnemonic(mnemonicCode: String, passPhrase: String = ""): Array[Byte] =
    Algos.hash(mnemonicCode + "mnemonic=" + passPhrase)

  def entropyToMnemonicCode(entropy: Array[Byte]): String = {
    val words: Array[String] = getWords
    val checkSum: BitVector = BitVector(Algos.hash(entropy))
    val entropyWithCheckSum: BitVector = BitVector(entropy) ++ checkSum.take(4)

    entropyWithCheckSum.grouped(11).map { i =>
      words(i.toInt(signed = false))
    }.mkString(" ")
  }
} 
Example 30
Source File: BitcoinSUtilTest.scala    From bitcoin-s   with MIT License 5 votes vote down vote up
package org.bitcoins.core.util

import org.bitcoins.testkit.util.BitcoinSUnitTest
import scodec.bits.BitVector


class BitcoinSUtilTest extends BitcoinSUnitTest {

  "BitcoinSUtil" must "determine if a string is a hex string" in {
    BytesUtil.isHex("abcdef0123456789") must be(true)

    BytesUtil.isHex("") must be(false)

    //don't allow upper case hex chars
    BytesUtil.isHex("ABCDEF0123456789") must be(false)

    BytesUtil.isHex("g") must be(false)

    //fail to parse a hex string that is uneven
    BytesUtil.isHex("123") must be(false)
  }

  it must "convert a byte to a bit vector" in {
    val byte = 0.toByte
    BytesUtil.byteToBitVector(byte).toIndexedSeq must be(
      Seq(false, false, false, false, false, false, false, false))

    val byte1 = 1.toByte
    BytesUtil.byteToBitVector(byte1).toIndexedSeq must be(
      Seq(false, false, false, false, false, false, false, true))

    val byte2 = 2.toByte
    BytesUtil.byteToBitVector(byte2).toIndexedSeq must be(
      Seq(false, false, false, false, false, false, true, false))

    val byte3 = 3.toByte
    BytesUtil.byteToBitVector(byte3).toIndexedSeq must be(
      Seq(false, false, false, false, false, false, true, true))

    val maxByte = 0xff.toByte
    BytesUtil.byteToBitVector(maxByte).toIndexedSeq must be(
      Seq(true, true, true, true, true, true, true, true))
  }

  it must "convert a bit vector to a byte" in {
    val bitVector0 = BitVector.bits(
      Seq(false, false, false, false, false, false, false, false))
    BytesUtil.bitVectorToBytes(bitVector0).toByte() must be(0.toByte)

    val bitVector1 =
      BitVector.bits(Seq(false, false, false, false, false, false, false, true))
    BytesUtil.bitVectorToBytes(bitVector1).toByte() must be(1.toByte)

    val bitVector2 =
      BitVector.bits(Seq(false, false, false, false, false, false, true, false))
    BytesUtil.bitVectorToBytes(bitVector2).toByte() must be(2.toByte)

    val bitVectorMax =
      BitVector.bits(Seq(true, true, true, true, true, true, true, true))
    BytesUtil.bitVectorToBytes(bitVectorMax).toByte() must be(0xff.toByte)

  }
} 
Example 31
Source File: RawMerkleBlockMessageSerializerTest.scala    From bitcoin-s   with MIT License 5 votes vote down vote up
package org.bitcoins.core.serializers.p2p.messages

import org.bitcoins.core.number.{UInt32, UInt64}
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.util.BytesUtil
import org.bitcoins.crypto.DoubleSha256Digest
import org.bitcoins.testkit.util.BitcoinSUnitTest
import scodec.bits.BitVector

class RawMerkleBlockMessageSerializerTest extends BitcoinSUnitTest {

  //from bitcoin developer reference
  //https://bitcoin.org/en/developer-reference#merkleblock
  val hex =
    "0100000082bb869cf3a793432a66e826e05a6fc37469f8efb7421dc88067010000000000" +
      "7f16c5962e8bd963659c793ce370d95f093bc7e367117b3c30c1f8fdd0d97287" +
      "76381b4d4c86041b554b85290700000004" +
      "3612262624047ee87660be1a707519a443b1c1ce3d248cbfc6c15870f6c5daa2" +
      "019f5b01d4195ecbc9398fbf3c3b1fa9bb3183301d7a1fb3bd174fcfa40a2b65" +
      "41ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d068" +
      "20d2a7bc994987302e5b1ac80fc425fe25f8b63169ea78e68fbaaefa59379bbf" +
      "011d"

  "RawMerkleBlockMessage" must "read a raw hex string into a merkle block message" in {
    val merkleBlockMessage = RawMerkleBlockMessageSerializer.read(hex)

    merkleBlockMessage.merkleBlock.transactionCount must be(UInt32(7))
    merkleBlockMessage.merkleBlock.hashCount must be(CompactSizeUInt(UInt64(4)))

    merkleBlockMessage.merkleBlock.hashes must be(
      Seq(
        DoubleSha256Digest(BytesUtil.decodeHex(
          "3612262624047ee87660be1a707519a443b1c1ce3d248cbfc6c15870f6c5daa2")),
        DoubleSha256Digest(BytesUtil.decodeHex(
          "019f5b01d4195ecbc9398fbf3c3b1fa9bb3183301d7a1fb3bd174fcfa40a2b65")),
        DoubleSha256Digest(BytesUtil.decodeHex(
          "41ed70551dd7e841883ab8f0b16bf04176b7d1480e4f0af9f3d4c3595768d068")),
        DoubleSha256Digest(BytesUtil.decodeHex(
          "20d2a7bc994987302e5b1ac80fc425fe25f8b63169ea78e68fbaaefa59379bbf"))
      ))

    merkleBlockMessage.merkleBlock.partialMerkleTree.bits must be(
      BitVector.fromValidBin("10111000"))
  }

  it must "write a merkle block header message" in {
    val merkleBlockMessage = RawMerkleBlockMessageSerializer.read(hex)

    RawMerkleBlockMessageSerializer.write(merkleBlockMessage).toHex must be(hex)
  }
} 
Example 32
Source File: KeyManagerCreateApi.scala    From bitcoin-s   with MIT License 5 votes vote down vote up
package org.bitcoins.keymanager

import org.bitcoins.core.crypto.MnemonicCode
import org.bitcoins.keymanager.bip39.BIP39KeyManager
import scodec.bits.BitVector


  final def initializeWithMnemonic(
      mnemonicCode: MnemonicCode,
      bip39PasswordOpt: Option[String],
      kmParams: KeyManagerParams): Either[
    KeyManagerInitializeError,
    BIP39KeyManager] = {
    val entropy = mnemonicCode.toEntropy
    initializeWithEntropy(entropy = entropy,
                          bip39PasswordOpt = bip39PasswordOpt,
                          kmParams = kmParams)
  }
} 
Example 33
Source File: GolombFilter.scala    From bitcoin-s   with MIT License 5 votes vote down vote up
package org.bitcoins.core.gcs

import org.bitcoins.core.number.{UInt64, UInt8}
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.crypto.{
  CryptoUtil,
  DoubleSha256Digest,
  DoubleSha256DigestBE,
  NetworkElement
}
import scodec.bits.{BitVector, ByteVector}


  def getHeader(prevHeaderHash: DoubleSha256Digest): FilterHeader = {
    FilterHeader(filterHash = this.hash, prevHeaderHash = prevHeaderHash)
  }

  override def bytes: ByteVector = {
    n.bytes ++ encodedData.bytes
  }

  def hashToRange(item: ByteVector): UInt64 = GCS.hashToRange(item, f, key)

} 
Example 34
Source File: RawMerkleBlockSerializer.scala    From bitcoin-s   with MIT License 5 votes vote down vote up
package org.bitcoins.core.serializers.blockchain

import org.bitcoins.core.number.{UInt32, UInt64}
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.protocol.blockchain.MerkleBlock
import org.bitcoins.core.serializers.RawBitcoinSerializer
import org.bitcoins.core.util.BytesUtil
import org.bitcoins.crypto.DoubleSha256Digest
import scodec.bits.{BitVector, ByteVector}

import scala.annotation.tailrec


  private def parseTransactionHashes(
      bytes: ByteVector,
      hashCount: CompactSizeUInt): (Seq[DoubleSha256Digest], ByteVector) = {
    @tailrec
    def loop(
        remainingHashes: Long,
        remainingBytes: ByteVector,
        accum: List[DoubleSha256Digest]): (
        Seq[DoubleSha256Digest],
        ByteVector) = {
      if (remainingHashes <= 0) (accum.reverse, remainingBytes)
      else {
        val (hashBytes, newRemainingBytes) = remainingBytes.splitAt(32)
        loop(remainingHashes - 1,
             newRemainingBytes,
             DoubleSha256Digest(hashBytes) :: accum)
      }
    }
    loop(hashCount.num.toInt, bytes, Nil)
  }
}

object RawMerkleBlockSerializer extends RawMerkleBlockSerializer 
Example 35
Source File: KeyManagerUnitTest.scala    From bitcoin-s   with MIT License 5 votes vote down vote up
package org.bitcoins.testkit.keymanager

import org.bitcoins.core.crypto.MnemonicCode
import org.bitcoins.keymanager.KeyManagerParams
import org.bitcoins.keymanager.bip39.BIP39KeyManager
import org.bitcoins.testkit.util.BitcoinSUnitTest
import scodec.bits.BitVector

trait KeyManagerUnitTest extends BitcoinSUnitTest {

  def withInitializedKeyManager(
      kmParams: KeyManagerParams = KeyManagerTestUtil.createKeyManagerParams(),
      entropy: BitVector = MnemonicCode.getEntropy256Bits,
      bip39PasswordOpt: Option[String] =
        KeyManagerTestUtil.bip39PasswordOpt): BIP39KeyManager = {
    val kmResult = BIP39KeyManager.initializeWithEntropy(
      entropy = entropy,
      bip39PasswordOpt = bip39PasswordOpt,
      kmParams = kmParams
    )

    val km = kmResult match {
      case Right(km) => km
      case Left(err) =>
        fail(s"Failed to initialize key manager with err=${err}")
    }

    km
  }
} 
Example 36
Source File: PersistenceTckSerializer.scala    From kafka-journal   with MIT License 5 votes vote down vote up
package akka.persistence.journal

import java.io.NotSerializableException

import akka.persistence.journal.JournalPerfSpec.Cmd
import akka.serialization.SerializerWithStringManifest
import scodec.bits.BitVector
import scodec.{Codec, codecs}

class PersistenceTckSerializer extends SerializerWithStringManifest {
  import PersistenceTckSerializer._

  def identifier = 585506118

  def manifest(a: AnyRef): String = a match {
    case _: Cmd => cmdManifest
    case _      => illegalArgument(s"Cannot serialize message of ${ a.getClass } in ${ getClass.getName }")
  }

  def toBinary(a: AnyRef): Array[Byte] = {
    a match {
      case a: Cmd => cmdCodec.encode(a).require.toByteArray
      case _      => illegalArgument(s"Cannot serialize message of ${ a.getClass } in ${ getClass.getName }")
    }
  }

  def fromBinary(bytes: Array[Byte], manifest: String): AnyRef = {
    manifest match {
      case `cmdManifest` => cmdCodec.decode(BitVector.view(bytes)).require.value
      case _             => notSerializable(s"Cannot deserialize message for manifest $manifest in ${ getClass.getName }")
    }
  }

  private def notSerializable(msg: String) = throw new NotSerializableException(msg)

  private def illegalArgument(msg: String) = throw new IllegalArgumentException(msg)
}

object PersistenceTckSerializer {

  val cmdManifest = "A"

  implicit val cmdCodec: Codec[Cmd] = {
    val codec = codecs.utf8_32 :: codecs.int32
    codec.as[Cmd]
  }
}