pogoprotos.scala
Scala fork of AeonLucid/POGOProtos using ScalaPB.
Installation
Add to build.sbt
(sbt version >=0.13.6):
resolvers += Resolver.bintrayRepo("walfie", "maven")
libraryDependencies ++= Seq(
"com.github.walfie" %% "pogoprotos" % "1.0.0"
)
Differences
- Packages are lowercase, e.g.,
pogoprotos.networking.requests.messages.GetPlayerMessage
instead ofPOGOProtos.Networking.Requests.Messages.GetPlayerMessage
- Response messages extend
pogoprotos.networking.ResponseMessage
- Request messages extend
pogoprotos.networking.RequestMessage[ResponseT]
(whereResponseT
is the correspondingResponseMessage
)
Usage
Classes are generated by ScalaPB, so everything in the ScalaPB docs applies here as well.
Serializing
Below is an example of constructing a RequestEnvelope
with several requests.
You can call .toByteArray
on any object to convert it to an Array[Byte]
that
can be sent over the wire.
import pogoprotos.networking.envelopes.RequestEnvelope
import pogoprotos.networking.requests.{Request, RequestType}
import pogoprotos.networking.requests.messages._
// ScalaPB-generated objects have a `.toByteArray` method, but the `requests`
// field in `RequestEnvelope` expects a protobuf `ByteString`.
import com.google.protobuf.ByteString
implicit def byteArrayToByteString(byteArray: Array[Byte]): ByteString =
ByteString.copyFrom(byteArray)
val request = RequestEnvelope().update(
_.statusCode := 2,
_.requestId := 25252,
_.latitude := 38.7330,
_.longitude := -121.8073,
_.altitude := 42.069,
_.unknown12 := 123,
_.requests :++= Seq(
Request().update(_.requestType := RequestType.GET_HATCHED_EGGS),
Request().update(
_.requestType := RequestType.GET_INVENTORY,
_.requestMessage := GetInventoryMessage().update(
_.lastTimestampMs := 123456789
).toByteArray
),
Request().update(_.requestType := RequestType.CHECK_AWARDED_BADGES),
Request().update(
_.requestType := RequestType.DOWNLOAD_SETTINGS,
_.requestMessage := DownloadSettingsMessage().update(
_.hash := "abcdef01234567890abcdef0123456789abcdef0"
).toByteArray
)
)
)
val requestAsBytes: Array[Byte] = request.toByteArray
As with ScalaPB, unspecified fields will be set to some default value.
Deserializing
The generated companion objects of each message have .parseFrom
(returns T
)
and .validate
(returns Try[T]
) methods.
import pogoprotos.networking.envelopes.ResponseEnvelope
// Pretend this is a response we received after posting the `RequestEnvelope`
val bytes: Array[Byte] = ResponseEnvelope().update(
_.statusCode := 53,
_.requestId := 315,
_.apiUrl := "http://example.com/"
).toByteArray
// `parseFrom` can throw an exception if the bytes could not be deserialized
val response = ResponseEnvelope.parseFrom(bytes)
// If we're concerned with possible failure, `validate` returns a `Try[ResponseEnvelope]`
val tryResponse = ResponseEnvelope.validate(bytes)
Assuming parsing succeeded, we can check the result's fields:
response.statusCode
// res11: Int = 53
response.requestId
// res12: Long = 315
response.apiUrl
// res13: String = http://example.com/
response.authTicket // This is unspecified in the message, so we expect `None`
// res14: Option[pogoprotos.networking.envelopes.AuthTicket] = None
On the other hand, if we try to parse an invalid message, we get:
ResponseEnvelope.validate(Array[Byte](1, 2, 3, 4, 5))
// res15: scala.util.Try[pogoprotos.networking.envelopes.ResponseEnvelope] = Failure(com.google.protobuf.InvalidProtocolBufferException: Protocol message contained an invalid tag (zero).)