Codec
Codec
module contains the encoding and decoding support for json & binary.
All codecs support JVM and ScalaJS.
json
circe
is used for all json codec, codec/shared/src/main/scala/jbok/codec/json
contains some
custom instances.
For some primary types such as BigInt
, we always delegate it to String
, rather than circe
’s default behavior.
Some instances for core models(e.g. Address
, Uint256
) are defined in their companion objects.
We prefer @ConfiguredJsonCodec
annotation, so import jbok.codec.json.implicits._
is a must.
import jbok.codec.json.implicits._
import io.circe.syntax._
import io.circe.parser._
binary
Typeclass RlpCodec
is used for core models binary codec.
Some instances and ops are defined in jbok/codec/rlp
.
import jbok.codec.rlp.RlpEncoded
import jbok.codec.rlp.implicits._
// encode A to RlpEncoded
"".encoded
// res0: RlpEncoded = RlpEncoded(ByteVector(1 bytes, 0x80))
0.encoded
// res1: RlpEncoded = RlpEncoded(ByteVector(1 bytes, 0x80))
case class Foo(name: String, age: Int)
Foo("oho", 18).encoded
// res2: RlpEncoded = RlpEncoded(ByteVector(6 bytes, 0xc5836f686f12))
List(Foo("cafe", 1), Foo("babe", 2)).encoded
// res3: RlpEncoded = RlpEncoded(ByteVector(15 bytes, 0xcec6846361666501c6846261626502))
// decode RlpEncoded to Either[Throwable, A]
val fooEncoded = Foo("bar", 42).encoded
// fooEncoded: RlpEncoded = RlpEncoded(ByteVector(6 bytes, 0xc5836261722a))
fooEncoded.decoded[Foo]
// res4: Either[Throwable, Foo] = Right(Foo("bar", 42))
// create `RlpEncoded` manually
RlpEncoded.coerce(fooEncoded.bits.drop(8)).decoded[Foo]
// res5: Either[Throwable, Foo] = Left(
// java.lang.Exception: invalid rlp list length 131
// )
rlp
is a low level, unoptimized binary codec protocol, but it’s behavior is concise and predictable.
It’s used to encode models like Block
or Transaction
, for computing stable message hashes.
RlpCodec
is implemented based on scodec
and magnolia
(macros for generating instances for case classes)