summaryrefslogtreecommitdiff
path: root/src/ConversionUtils.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/ConversionUtils.scala')
-rw-r--r--src/ConversionUtils.scala87
1 files changed, 87 insertions, 0 deletions
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()
+ }
+}
+