All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scodec.codecs.PaddedFixedSizeCodec.scala Maven / Gradle / Ivy

package scodec
package codecs

import scalaz.{ \/, \/-, -\/ }

import scalaz.syntax.order._
import scalaz.Ordering
import scalaz.std.AllInstances._

import scodec.bits.BitVector
import scala.annotation.tailrec

private[codecs] final class PaddedFixedSizeCodec[A](size: Long, codec: Codec[A], padCodec: Codec[Unit]) extends Codec[A] {
  override def encode(a: A) = for {
    encoded <- codec.encode(a)
    result <- {
      if (encoded.size > size)
        \/.left(s"[$a] requires ${encoded.size} bits but field is fixed size of $size bits")
      else if (encoded.size == size)
        \/.right(encoded)
      else {
        padCodec.encode(()).fold(
          err => \/.left(s"Padding codec [$padCodec] failed : $err"),
          padding => {
            @tailrec def pad(bits: BitVector): String \/ BitVector = bits.size ?|? size match {
              case Ordering.EQ => \/.right(bits)
              case Ordering.LT => pad(bits ++ padding)
              case Ordering.GT => \/.left(s"[$a] padded by [$padCodec] overflows fixed size field of $size bits")
            }
            pad(encoded)
          })
      }
    }
  } yield result

  override def decode(buffer: BitVector) =
    buffer.acquire(size) match {
      case Left(e) => \/.left(e)
      case Right(b) =>
        codec.decode(b) match {
          case e @ -\/(_) => e
          case \/-((rest, res)) => {
            @tailrec def validate(bits: BitVector): String \/ (BitVector, A) =
              if (bits.isEmpty)
                \/-((buffer.drop(size), res))
              else
                padCodec.decode(bits) match {
                  case e @ -\/(_) => e
                  case \/-((remain, _)) => validate(remain)
                }
            validate(rest)
          }
        }
    }

  override def toString = s"paddedFixedSizeBits($size, $codec, $padCodec)"
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy