mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-19 18:14:44 +00:00
Packet: Improve sizeCodec for MultiPacketEx
Was completely unreadable before. Now it's not.
This commit is contained in:
parent
7b82491d0e
commit
372a88bb6e
|
|
@ -2,9 +2,10 @@
|
|||
package net.psforever.packet.control
|
||||
|
||||
import net.psforever.packet.{ControlPacketOpcode, Marshallable, PlanetSideControlPacket}
|
||||
import scodec.{Attempt, Codec, DecodeResult, SizeBound}
|
||||
import scodec.{Attempt, Codec, DecodeResult, Err, SizeBound}
|
||||
import scodec.bits._
|
||||
import scodec.codecs._
|
||||
import shapeless.HNil
|
||||
|
||||
final case class MultiPacketEx(packets : Vector[ByteVector])
|
||||
extends PlanetSideControlPacket {
|
||||
|
|
@ -14,53 +15,57 @@ final case class MultiPacketEx(packets : Vector[ByteVector])
|
|||
}
|
||||
|
||||
object MultiPacketEx extends Marshallable[MultiPacketEx] {
|
||||
val ffFound: Codec[Boolean] = new Codec[Boolean] {
|
||||
def sizeBound = SizeBound.exact(0)
|
||||
def encode(b: Boolean) =
|
||||
if(b)
|
||||
Attempt.successful(hex"ff".bits)
|
||||
else
|
||||
Attempt.successful(bin"")
|
||||
def decode(b: BitVector) = {
|
||||
if (b.length >= 8 && b.take(8) == hex"ff".bits)
|
||||
Attempt.successful(DecodeResult(true, b.drop(8)))
|
||||
else
|
||||
Attempt.successful(DecodeResult(false, b))
|
||||
val sizeCodec : Codec[Long] = new Codec[Long] {
|
||||
private def description = s"variable-bit unsigned integer"
|
||||
override def sizeBound = SizeBound.bounded(8, 32)
|
||||
|
||||
val MaxValue = (1L << 31) - 1
|
||||
val MinValue = 0
|
||||
|
||||
override def encode(i: Long) = {
|
||||
if (i > MaxValue) {
|
||||
Attempt.failure(Err(s"$i is greater than maximum value $MaxValue for $description"))
|
||||
} else if (i < MinValue) {
|
||||
Attempt.failure(Err(s"$i is less than minimum value $MinValue for $description"))
|
||||
} else {
|
||||
if(i < 0xff) {
|
||||
uint8L.encode(i.toInt)
|
||||
} else if(i < 0xffff) {
|
||||
(constant(hex"ff") :: uint16L).dropUnits.encode(i.toInt :: HNil)
|
||||
} else {
|
||||
(constant(hex"ffffff") :: uint32L).dropUnits.encode(i :: HNil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override def toString = "bitsRemaining"
|
||||
}
|
||||
override def decode(buffer: BitVector) : Attempt[DecodeResult[Long]] = {
|
||||
val sizeTypes = List(8, 16, 32)
|
||||
val guards = List(hex"ff".bits, hex"ffff".bits)
|
||||
|
||||
val twoffFound: Codec[Boolean] = new Codec[Boolean] {
|
||||
def sizeBound = SizeBound.exact(0)
|
||||
def encode(b: Boolean) =
|
||||
if(b)
|
||||
Attempt.successful(hex"ffff".bits)
|
||||
else
|
||||
Attempt.successful(bin"")
|
||||
def decode(b: BitVector) = {
|
||||
if (b.length >= 16 && b.take(16) == hex"ffff".bits)
|
||||
Attempt.successful(DecodeResult(true, b.drop(16)))
|
||||
else
|
||||
Attempt.successful(DecodeResult(false, b))
|
||||
var buf = buffer
|
||||
|
||||
for(i <- sizeTypes.indices) {
|
||||
val s = sizeTypes{i}
|
||||
|
||||
if(!buf.sizeGreaterThanOrEqual(s))
|
||||
return Attempt.failure(Err.insufficientBits(s, buf.size))
|
||||
|
||||
val value = buf.take(s)
|
||||
buf = buf.drop(s)
|
||||
|
||||
if(i == guards.length || value != guards{i})
|
||||
return Attempt.successful(
|
||||
DecodeResult(value.toLong(signed = false, ByteOrdering.LittleEndian),
|
||||
buf)
|
||||
)
|
||||
}
|
||||
|
||||
// will never reach here
|
||||
Attempt.failure(Err("unknown error"))
|
||||
}
|
||||
|
||||
override def toString = "bitsRemaining"
|
||||
override def toString = description
|
||||
}
|
||||
|
||||
val sizeCodec = either(ffFound, uint8L,
|
||||
either(twoffFound, uint16L, uint32L).xmap[Long](
|
||||
(a : Either[Int, Long]) => a.fold[Long](a => a, a => a),
|
||||
(a : Long) =>
|
||||
if(a < 0xffff) Left(a.toInt) else Right(a)
|
||||
)
|
||||
).xmap[Long](
|
||||
(a : Either[Int, Long]) => a.fold[Long](a => a, a => a),
|
||||
(a : Long) =>
|
||||
if(a < 0xff) Left(a.toInt) else Right(a)
|
||||
)
|
||||
|
||||
implicit val codec : Codec[MultiPacketEx] = (
|
||||
("packets" | vector(variableSizeBytesLong(sizeCodec, bytes)))
|
||||
).as[MultiPacketEx]
|
||||
implicit val codec : Codec[MultiPacketEx] = ("packets" | vector(variableSizeBytesLong(sizeCodec, bytes))).as[MultiPacketEx]
|
||||
}
|
||||
Loading…
Reference in a new issue