solved padding for decoding but not for encoding

This commit is contained in:
FateJH 2016-09-21 00:50:21 -04:00
parent ae579d1780
commit 6be873c4f6
3 changed files with 34 additions and 10 deletions

View file

@ -203,4 +203,27 @@ object PacketHelpers {
def encodedStringWithLimit(limit : Int) : Codec[String] = variableSizeBytes(encodedStringSizeWithLimit(limit), ascii)
*/
def listOfNAligned[A](countCodec: Codec[Int], alignment : Int, valueCodec: Codec[A]): Codec[List[A]] = {
countCodec.
flatZip { count => new AlignedListCodec(valueCodec, alignment, Some(count)) }.
narrow[List[A]]({ case (cnt, xs) =>
if (xs.size == cnt) Attempt.successful(xs)
else Attempt.failure(Err(s"Insufficient number of elements: decoded ${xs.size} but should have decoded $cnt"))
}, xs => (xs.size, xs)).
withToString(s"listOfN($countCodec, $valueCodec)")
}
}
private final class AlignedListCodec[A](codec: Codec[A], alignment : Int, limit: Option[Int] = None) extends Codec[List[A]] {
def sizeBound = limit match {
case None => SizeBound.unknown
case Some(lim) => codec.sizeBound * lim.toLong
}
def encode(list: List[A]) = Encoder.encodeSeq(codec)(list)
def decode(buffer: BitVector) = Decoder.decodeCollect[List, A](codec, limit)(buffer.drop(alignment))
override def toString = s"list($codec)"
}

View file

@ -1,7 +1,7 @@
// Copyright (c) 2016 PSForever.net to present
package net.psforever.packet.game
import net.psforever.packet.{GamePacketOpcode, Marshallable, PlanetSideGamePacket}
import net.psforever.packet.{GamePacketOpcode, Marshallable, PacketHelpers, PlanetSideGamePacket}
import scodec.Codec
import scodec.codecs._
@ -41,6 +41,7 @@ final case class HotSpotInfo(unk1 : Int,
* @param spots a List of HotSpotInfo, or `Nil` if empty
*/
// TODO need aligned/padded list support
// TODO test with sendRawResponse(hex"9F 0D00 5 02 0 00 D07 00 8CA 00020 00 BEA 00 4C4 40000")
final case class HotSpotUpdateMessage(continent_guid : PlanetSideGUID,
unk : Int,
spots : List[HotSpotInfo] = Nil)
@ -64,6 +65,6 @@ object HotSpotUpdateMessage extends Marshallable[HotSpotUpdateMessage] {
implicit val codec : Codec[HotSpotUpdateMessage] = (
("continent_guid" | PlanetSideGUID.codec) ::
("unk" | uint4L) ::
("spots" | listOfN(uint8L, HotSpotInfo.codec))
("spots" | PacketHelpers.listOfNAligned(uint8L, 4, HotSpotInfo.codec))
).as[HotSpotUpdateMessage]
}

View file

@ -937,8 +937,8 @@ class GamePacketTest extends Specification {
continent_guid mustEqual PlanetSideGUID(5)
unk mustEqual 1
spots.size mustEqual 1
spots.head.x mustEqual 3730
spots.head.y mustEqual 1105
spots.head.x mustEqual 2350
spots.head.y mustEqual 1300
spots.head.scale mustEqual 128
case _ =>
ko
@ -951,11 +951,11 @@ class GamePacketTest extends Specification {
continent_guid mustEqual PlanetSideGUID(5)
unk mustEqual 5
spots.size mustEqual 2
spots.head.x mustEqual 125
spots.head.y mustEqual 3240
spots.head.x mustEqual 2000
spots.head.y mustEqual 2700
spots.head.scale mustEqual 128
spots(1).x mustEqual 3755
spots(1).y mustEqual 3140
spots(1).x mustEqual 2750
spots(1).y mustEqual 1100
spots(1).scale mustEqual 128
case _ =>
ko
@ -969,13 +969,13 @@ class GamePacketTest extends Specification {
}
"encode (one)" in {
val msg = HotSpotUpdateMessage(PlanetSideGUID(5),1, HotSpotInfo(0,3730,0,1105,128)::Nil)
val msg = HotSpotUpdateMessage(PlanetSideGUID(5),1, HotSpotInfo(0,2350,0,1300,128)::Nil)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual stringOne
}
"encode (two)" in {
val msg = HotSpotUpdateMessage(PlanetSideGUID(5),1, HotSpotInfo(0,125,0,3240,128)::HotSpotInfo(0,3755,0,3140,128)::Nil)
val msg = HotSpotUpdateMessage(PlanetSideGUID(5),1, HotSpotInfo(0,2000,0,2700,128)::HotSpotInfo(0,2750,0,1100,128)::Nil)
val pkt = PacketCoding.EncodePacket(msg).require.toByteVector
pkt mustEqual stringOne
}