From 9827904a6aa6b649665cf78fa56716011fb37e6d Mon Sep 17 00:00:00 2001 From: iximeow Date: Mon, 2 Mar 2015 15:34:34 -0800 Subject: initial commit --- src/ConversionUtils.scala | 87 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 src/ConversionUtils.scala (limited to 'src/ConversionUtils.scala') diff --git a/src/ConversionUtils.scala b/src/ConversionUtils.scala new file mode 100644 index 0000000..32689fc --- /dev/null +++ b/src/ConversionUtils.scala @@ -0,0 +1,87 @@ +package ixee.cryptopals.utils + +import ByteUtils._ +import FunctionUtils._ + +object ConversionUtils { + def hexStr2Bytes(s: String): Seq[Byte] = + padToByte(s).grouped(2).map(byteStr2Byte).toStream.force + + def byteStr2Byte(str: String): Byte = + charSeq2Byte(str.toSeq) + + def charSeq2Byte(seq: Seq[Char]): Byte = + seq.map(octet2nibble).reduce(joinNibbles) + + def joinNibbles(a: Byte, b: Byte): Byte = + ((a @<< 4) @+ b) + + def padToByte(s: String): String = + if (s.length % 2 != 0) "0" + s else s + + def octet2nibble(c: Char): Byte = { + (c.toLower match { + case c if c >= 'a' && c <= 'f' => + (c - 'a') + 10.toByte + case c if c >= '0' && c <= '9' => + c - '0' + case _ => + throw new IllegalArgumentException(s"Invalid hexadecimal character: $c") + }).toByte + } + + def hexStr2Base64String(s: String): String = { + import io.github.marklister.base64.Base64._ + + hexStr2Bytes(s).toArray.toBase64 + } + + implicit class RichSeqByte(seq: Seq[Byte]) { + def to[T : SizedNumeric : BitOps]: T = { + val numeric = implicitly[SizedNumeric[T]] + if(seq.length < numeric.byteSize) { + throw new RuntimeException("Byte input is not long enough") + } + + var out: Long = seq(0) + for(i <- 1 until numeric.byteSize) { + out << 8 + out = seq(i) | out + } + numeric.fromLong(out) + } + + def hex: String = + seq.map(_.hex).reduceLeft(_ + _) + + def asAscii: String = + new String(seq.toArray) + } + + implicit class RichStringBytes(s: String) { + def asBytes = s.toSeq.map(_.toByte) + def asByteStream = s.asBytes.toStream + def asRepeatedBytes(count: Int) = + Stream.continually(s.asBytes).flatten.take(count) + } + + // TODO: tailrec this, get rid of for + def toByteSeq[T : SizedNumeric : BitOps](x: T): Seq[Byte] = { + val buf = new Array[Byte](x.byteSize) + for(i <- 0 until x.byteSize) { + val shiftAmount = (x.byteSize - i - 1) << 3 + buf(i) = (x @>>> shiftAmount).truncatedTo[Byte] + } + buf.toSeq + } + + def toBinaryString[T : SizedNumeric](x: T)(implicit a: BitOps[T]): String = { + val buf = new StringBuilder(x.bitSize) + for(i <- 0 until x.bitSize) { + val shiftAmount: Int = x.bitSize - i - 1 + buf.append((x @>>> shiftAmount) @& 0x01.liftedTo[T]) + } + buf.toString() + } +} + -- cgit v1.1