Skip to content

Instantly share code, notes, and snippets.

@mpilquist
Created February 11, 2020 13:58
Show Gist options
  • Save mpilquist/70e8eebac176f97e7e56d6e4225fe6b8 to your computer and use it in GitHub Desktop.
Save mpilquist/70e8eebac176f97e7e56d6e4225fe6b8 to your computer and use it in GitHub Desktop.
diff --git a/unitTests/src/test/scala/scodec/examples/TlvExample.scala b/unitTests/src/test/scala/scodec/examples/TlvExample.scala
index 873bf05..b31e727 100644
--- a/unitTests/src/test/scala/scodec/examples/TlvExample.scala
+++ b/unitTests/src/test/scala/scodec/examples/TlvExample.scala
@@ -5,7 +5,7 @@ import scodec.bits._
import codecs._
class TlvExample extends CodecSuite {
- // Example of implementing type-length-value encodings using coproducts.
+ // Example of implementing type-length-value encodings.
// See http://en.wikipedia.org/wiki/Type-length-value for more information on TLV.
//
// This example models a command set for 2 dimensional movement. Each command
@@ -23,18 +23,19 @@ class TlvExample extends CodecSuite {
//
// Unrecognized commands must be decoded.
- sealed trait Command
- case object Go extends Command
- case object Stop extends Command
- case class TurnLeft(degrees: Int) extends Command
- case class TurnRight(degrees: Int) extends Command
+ enum Command {
+ case Go
+ case Stop
+ case TurnLeft(degress: Int)
+ case TurnRight(degress: Int)
+ }
case class UnrecognizedCommand(commandType: Int, data: BitVector)
"type-length-value encodings" should {
- "be supported by coproduct codecs" in {
- // The type field acts as the discriminator for the coproduct
+ "be supported" in {
+ // The type field acts as the discriminator
// The length field is handled by coproduct framing
// Each component codec writes the value
@@ -46,33 +47,28 @@ class TlvExample extends CodecSuite {
uint16.decode(b).orElse(uint8.decode(b))
}
- implicit val goCodec: Codec[Go.type] = provide(Go)
- implicit val stopCodec: Codec[Stop.type] = provide(Stop)
- implicit val leftCodec: Codec[TurnLeft] = uint8or16.as[TurnLeft]
- implicit val rightCodec: Codec[TurnRight] = uint8or16.as[TurnRight]
- implicit val unrecognizedCodec: Codec[UnrecognizedCommand] =
- (uint8 :: variableSizeBytes(uint8, bits)).as[UnrecognizedCommand]
+ val commandCodec: Codec[Command] =
+ discriminated[Command].by(uint8)
+ .framing([x] => (c: Codec[x]) => variableSizeBytes(uint8, c))
+ .singleton(0, Command.Go)
+ .singleton(1, Command.Stop)
+ .typecase(2, uint8or16.as[Command.TurnLeft])
+ .typecase(3, uint8or16.as[Command.TurnRight])
- implicit val commandDiscriminated: Discriminated[Command, Int] =
- Discriminated[Command, Int](uint8, new CodecTransformation {
- def apply[X](c: Codec[X]) = variableSizeBytes(uint8, c)
- })
- implicit val goDiscriminator: Discriminator[Command, Go.type, Int] = Discriminator(0)
- implicit val stopDiscriminator: Discriminator[Command, Stop.type, Int] = Discriminator(1)
- implicit val leftDiscriminator: Discriminator[Command, TurnLeft, Int] = Discriminator(2)
- implicit val rightDiscriminator: Discriminator[Command, TurnRight, Int] = Discriminator(3)
+ val unrecognizedCodec: Codec[UnrecognizedCommand] =
+ (uint8 :: variableSizeBytes(uint8, bits)).as[UnrecognizedCommand]
val codec: Codec[Either[UnrecognizedCommand, Command]] =
- discriminatorFallback(unrecognizedCodec, Codec[Command])
+ discriminatorFallback(unrecognizedCodec, commandCodec)
- roundtrip(codec, Right(Go))
- roundtrip(codec, Right(Stop))
- roundtrip(codec, Right(TurnLeft(270)))
- roundtrip(codec, Right(TurnRight(180)))
+ roundtrip(codec, Right(Command.Go))
+ roundtrip(codec, Right(Command.Stop))
+ roundtrip(codec, Right(Command.TurnLeft(270)))
+ roundtrip(codec, Right(Command.TurnRight(180)))
codec.decode(hex"0400".bits).require.value shouldBe Left(
UnrecognizedCommand(4, BitVector.empty)
)
- roundtrip(list(codec), List(Right(TurnRight(180)), Right(Go), Right(Stop)))
+ roundtrip(list(codec), List(Right(Command.TurnRight(180)), Right(Command.Go), Right(Command.Stop)))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment