Home

Awesome

proto

proto Scala version support
proto Scala version support
proto Scala version support
Production Ready

Lightweight and fast serialization library for Scala 2/3 based on Protocol Buffers with macros magic.

Motivation

Serialization library for Scala that can be used either for long term store models and short term models. With easy to migrate possibility.

Install

Add dependency:

libraryDependencies += "io.github.zero-deps" %% "proto" % "latest.integration"

Dependency as a git-submodule is also supported.

Benchmark #1

datalibraryscala-2scala-3
datadecodejava 44079.139 38979.697
datadecodejackson 176941.468 188555.562
datadecodejsoniter-scala 483788.001no support for Scala 3
datadecodeboopickle 2885610.648no support for Scala 3
datadecodeproto 3383845.4583776688.591
datadecodescalapb 3270691.5643893847.420
datalibraryscala-2scala-3
dataencodejava 220444.268 217484.396
dataencodejackson 431318.803 384863.249
dataencodejsoniter-scala 1054650.233no support for Scala 3
dataencodeboopickle 1520834.519no support for Scala 3
dataencodeproto 3186951.4412965427.382
dataencodescalapb 3628779.8643972905.402
datalibraryscala-2scala-3
msgdecodejsoniter-scala 3486552.303no support for Scala 3
msgdecodeproto 5825174.1706395557.251
msgdecodescalapb 4898257.6716902064.854
datalibraryscala-2scala-3
msgencodejsoniter-scala 6372602.760no support for Scala 3
msgencodeproto 6487748.9596745673.393
msgencodescalapb 9202135.4519056962.541

environment

Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
16 GB 2133 MHz LPDDR3
Java 15

run benchmark

sbt
project bench
++ 3.0.0
jmh:run -i 2 -wi 1 -f1 -t1

Benchmark #2

datalibraryscala-3
datadecodejava 92130,460
datadecodejackson 517036,354
datadecodeproto 6716619,956
datalibraryscala-3
dataencodejava 537462,511
dataencodejackson 882065,311
dataencodeproto 9380874,587
datalibraryscala-3
msgdecodeproto11733555,275
datalibraryscala-3
msgencodeproto18486833,582

environment

Apple M1
16 GB
Java 21

run benchmark

sbt
project bench
++ 3.0.0
jmh:run -i 2 -wi 1 -f1 -t1

Usage

You can pick one of the way how to define field number:

You can use annotation @proto.RestrictedN to restrict usage of specified field numbers. Can be used with classes or traits.

import scala.collection.immutable.TreeMap
import proto.{encode, decode, N}
import proto.{caseCodecIdx, caseCodecNums, caseCodecAuto}

final case class VectorClock(versions: TreeMap[String, Long])
@RestrictedN(3,4)
final case class Equipment(@N(1) id: String, @N(2) tpe: String)
final case class Car(id: String, color: Int, equipment: List[Equipment], vc: VectorClock)

implicit val tuple2Codec = caseCodecIdx[Tuple2[String, Long]] //codec for TreeMap[String, Long]

implicit val vectorClockCodec = caseCodecIdx[VectorClock]
implicit val equipmentCodec = caseCodecAuto[Equipment]
implicit val carCodec = caseCodecNums[Car]('id->1, 'color->4, 'equipment->2, 'vc->3)

val vc = VectorClock(versions=TreeMap.empty)
val equipment = List(Equipment(id="1", tpe="123"), Equipment(id="2", tpe="456"))
val car = Car(id="1", color=16416882, equipment=equipment, vc=vc)
//encode
val bytes: Array[Byte] = encode(car)
//decode
val car2: Car = decode[Car](bytes)

More examples in testing.scala