CycloneTechnology/ChaMP

View on GitHub
champ-ipmi/src/main/scala/com/cyclone/ipmi/codec/package.scala

Summary

Maintainability
A
0 mins
Test Coverage
package com.cyclone.ipmi

import java.io.InputStream

import akka.util.ByteString
import com.google.common.io.ByteStreams

import scala.annotation.tailrec

/**
  * Support methods and implicits
  */
package object codec extends CodecSupport with DefaultCodecs {

  implicit class RichByte(val byte: Byte) extends AnyVal {

    def as[A](implicit decoder: Decoder[A]): A = decoder.decode(ByteString(byte))

    def map[A](f: Byte => A): A = f(byte)

    def toUnsignedInt: Int = byte.toInt & 0xff

    def in(range: Range): Boolean = range.contains(byte.toUnsignedInt)

    def bits1To7: Byte = ((byte.toUnsignedInt & 0xff) >> 1).toByte

    def bits2To7: Byte = ((byte.toUnsignedInt & 0xff) >> 2).toByte

    def bits3To7: Byte = ((byte.toUnsignedInt & 0xff) >> 3).toByte

    def bits4To7: Byte = ((byte.toUnsignedInt & 0xff) >> 4).toByte

    def bits6To7: Byte = ((byte.toUnsignedInt & 0xff) >> 6).toByte

    def bits0To6: Byte = ((byte.toUnsignedInt & 0x7f) >> 0).toByte

    def bits5To6: Byte = ((byte.toUnsignedInt & 0x7f) >> 5).toByte

    def bits4To6: Byte = ((byte.toUnsignedInt & 0x7f) >> 4).toByte

    def bits0To5: Byte = ((byte.toUnsignedInt & 0x3f) >> 0).toByte

    def bits4To5: Byte = ((byte.toUnsignedInt & 0x3f) >> 4).toByte

    def bits3To5: Byte = ((byte.toUnsignedInt & 0x3f) >> 3).toByte

    def bits0To4: Byte = ((byte.toUnsignedInt & 0x1f) >> 0).toByte

    def bits3To4: Byte = ((byte.toUnsignedInt & 0x1f) >> 3).toByte

    def bits0To3: Byte = ((byte.toUnsignedInt & 0x0f) >> 0).toByte

    def bits2To3: Byte = ((byte.toUnsignedInt & 0x0f) >> 2).toByte

    def bits0To2: Byte = ((byte.toUnsignedInt & 0x07) >> 0).toByte

    def bits1To2: Byte = ((byte.toUnsignedInt & 0x07) >> 1).toByte

    def bits0To1: Byte = ((byte.toUnsignedInt & 0x03) >> 0).toByte

    def bit0: Boolean = (byte.toUnsignedInt & 0x01) != 0

    def bit1: Boolean = (byte.toUnsignedInt & 0x02) != 0

    def bit2: Boolean = (byte.toUnsignedInt & 0x04) != 0

    def bit3: Boolean = (byte.toUnsignedInt & 0x08) != 0

    def bit4: Boolean = (byte.toUnsignedInt & 0x10) != 0

    def bit5: Boolean = (byte.toUnsignedInt & 0x20) != 0

    def bit6: Boolean = (byte.toUnsignedInt & 0x40) != 0

    def bit7: Boolean = (byte.toUnsignedInt & 0x80) != 0

    def set0: Byte = (byte.toUnsignedInt | 0x01).toByte

    def set1: Byte = (byte.toUnsignedInt | 0x02).toByte

    def set2: Byte = (byte.toUnsignedInt | 0x04).toByte

    def set3: Byte = (byte.toUnsignedInt | 0x08).toByte

    def set4: Byte = (byte.toUnsignedInt | 0x10).toByte

    def set5: Byte = (byte.toUnsignedInt | 0x20).toByte

    def set6: Byte = (byte.toUnsignedInt | 0x40).toByte

    def set7: Byte = (byte.toUnsignedInt | 0x80).toByte
  }

  implicit class RichOptByte(val ob: Option[Byte]) extends AnyVal {

    def as[A](implicit decoder: Decoder[A]): Option[A] =
      ob.map(b => decoder.decode(ByteString(b)))
  }

  implicit class RichInt(val int: Int) extends AnyVal {
    def in(range: Range): Boolean = range.contains(int)
  }

  implicit class RichBool(val b: Boolean) extends AnyVal {
    def toBit7: Byte = (if (b) 0x80 else 0).toByte

    def toBit6: Byte = (if (b) 0x40 else 0).toByte

    def toBit5: Byte = (if (b) 0x20 else 0).toByte

    def toBit4: Byte = (if (b) 0x10 else 0).toByte

    def toBit3: Byte = (if (b) 0x08 else 0).toByte

    def toBit2: Byte = (if (b) 0x04 else 0).toByte

    def toBit1: Byte = (if (b) 0x02 else 0).toByte

    def toBit0: Byte = (if (b) 0x01 else 0).toByte
  }

  implicit class EncoderOps[A](val a: A) extends AnyVal {
    def toBin(implicit coder: Coder[A]): ByteString = coder.encode(a)

    def toByte(implicit coder: Coder[A]): Byte = toBin.apply(0)
  }

  implicit class RichInputStream(val inputStream: InputStream) extends AnyVal {

    def read(num: Int): ByteString = {
      val bs = Array.ofDim[Byte](num)

      ByteStreams.readFully(inputStream, bs)

      ByteString(bs)
    }

    def readByteOptional: Option[Byte] = {
      val b = inputStream.read()

      if (b == -1)
        None
      else
        Some(b.toByte)
    }

    def readByte: Byte = readByteOptional.get
  }

  implicit class RichByteString(val data: ByteString) extends AnyVal {

    def as[A](implicit decoder: Decoder[A]): A = decoder.decode(data)

    def toHexString(separator: String = ":"): String = data.map("%02X" format _).mkString(separator)

    def take(range: Range): ByteString = data.drop(range.start).take(range.length)

    def splitWhenever(p: Byte => Boolean): List[ByteString] = {
      // Tail recursive version of http://stackoverflow.com/a/7293881
      @tailrec
      def loop(acc: List[ByteString], xs: ByteString): List[ByteString] =
        xs match {
          case bs if bs.isEmpty => acc
          case bs =>
            val (ys, zs) = bs.tail.span(!p(_))
            loop((ByteString(bs.head) ++ ys) :: acc, zs)
        }

      loop(List.empty, data).reverse
    }
  }

}