Merge pull request #27 from Christewart/master

Adding utility function to convert a byte to a bit vector and vice versa
This commit is contained in:
Thomas McCabe 2016-08-15 13:51:18 -05:00 committed by GitHub
commit 7cee065214
3 changed files with 69 additions and 1 deletions

View File

@ -89,6 +89,31 @@ trait BitcoinSUtil {
val paddedHex = padding.mkString + hex
paddedHex
}
/** Converts a sequence of bytes to a sequence of bit vectors - assumes the sequence of bytes are big endian */
def bytesToBitVectors(bytes: Seq[Byte]): Seq[Seq[Boolean]] = bytes.map(byteToBitVector)
/** Converts a byte to a bit vector representing that byte - the bit vector is big endian */
def byteToBitVector(byte: Byte): Seq[Boolean] = {
(0 to 7).map(index => isBitSet(byte,7 - index))
}
/** Checks if the bit at the given index is set */
def isBitSet(byte: Byte, index: Int): Boolean = ((byte >> index) & 1) == 1
/** Converts a bit vector to a single byte -- assumes the bits are big endian */
def bitVectorToByte(bits: Seq[Boolean]): Byte = {
require(bits.size <= 8, "Cannot convert a bit vector to a byte when the size of the bit vector is larger than 8, got: " + bits)
val b = bits.reverse
val result: Seq[Int] = b.zipWithIndex.map { case (b, index) =>
if (b) NumberUtil.pow2(index).toInt else 0
}
result.sum.toByte
}
/** Converts a sequence of bit vectors to a sequence of bytes */
def bitVectorsToBytes(bits: Seq[Seq[Boolean]]): Seq[Byte] = bits.map(bitVectorToByte)
}
object BitcoinSUtil extends BitcoinSUtil

View File

@ -1,6 +1,6 @@
package org.bitcoins.core.util
import org.bitcoins.core.gen.StringGenerators
import org.bitcoins.core.gen.{CryptoGenerators, NumberGenerator, StringGenerators}
import org.scalacheck.{Gen, Prop, Properties}
/**
* Created by chris on 6/20/16.
@ -16,4 +16,15 @@ class BitcoinSUtilSpec extends Properties("BitcoinSUtilSpec") with BitcoinSLogge
Prop.forAll(StringGenerators.hexString) { hex : String =>
BitcoinSUtil.flipEndianess(BitcoinSUtil.flipEndianess(hex)) == hex
}
property("Convert a byte to a bit vector, convert it back to the original byte") =
Prop.forAll { byte: Byte =>
BitcoinSUtil.bitVectorToByte(BitcoinSUtil.byteToBitVector(byte)) == byte
}
property("Convert a sequence of bit vectors to a sequence of bytes") =
Prop.forAll(NumberGenerator.bitVectors) { bitVectors: Seq[Seq[Boolean]] =>
BitcoinSUtil.bytesToBitVectors(BitcoinSUtil.bitVectorsToBytes(bitVectors)) == bitVectors
}
}

View File

@ -21,4 +21,36 @@ class BitcoinSUtilTest extends FlatSpec with MustMatchers {
//fail to parse a hex string that is uneven
BitcoinSUtil.isHex("123") must be (false)
}
it must "convert a byte to a bit vector" in {
val byte = 0.toByte
BitcoinSUtil.byteToBitVector(byte) must be (Seq(false,false,false,false,false,false,false,false))
val byte1 = 1.toByte
BitcoinSUtil.byteToBitVector(byte1) must be (Seq(false,false,false,false,false,false,false,true))
val byte2 = 2.toByte
BitcoinSUtil.byteToBitVector(byte2) must be (Seq(false,false,false,false,false,false,true,false))
val byte3 = 3.toByte
BitcoinSUtil.byteToBitVector(byte3) must be (Seq(false,false,false,false,false,false,true,true))
val maxByte = 0xff.toByte
BitcoinSUtil.byteToBitVector(maxByte) must be (Seq(true,true,true,true,true,true,true,true))
}
it must "convert a bit vector to a byte" in {
val bitVector0 = Seq(false,false,false,false,false,false,false,false)
BitcoinSUtil.bitVectorToByte(bitVector0) must be (0.toByte)
val bitVector1 = Seq(false,false,false,false,false,false,false,true)
BitcoinSUtil.bitVectorToByte(bitVector1) must be (1.toByte)
val bitVector2 = Seq(false,false,false,false,false,false,true,false)
BitcoinSUtil.bitVectorToByte(bitVector2) must be (2.toByte)
val bitVectorMax = Seq(true,true,true,true,true,true,true,true)
BitcoinSUtil.bitVectorToByte(bitVectorMax) must be (0xff.toByte)
}
}