summaryrefslogtreecommitdiff
path: root/src/external/Base64.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/external/Base64.scala')
-rw-r--r--src/external/Base64.scala69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/external/Base64.scala b/src/external/Base64.scala
new file mode 100644
index 0000000..692abb8
--- /dev/null
+++ b/src/external/Base64.scala
@@ -0,0 +1,69 @@
+package io.github.marklister.base64
+
+/**
+ * Base64 encoder
+ * @author Mark Lister
+ * (c) Mark Lister 2014
+ *
+ * I, the copyright holder of this work, release this work into the public domain.
+ * This applies worldwide. In some countries this may not be legally possible;
+ * if so: I grant anyone the right to use this work for any purpose, without any
+ * conditions, unless such conditions are required by law.
+ *
+ * The repo for this Base64 encoder lives at https://github.com/marklister/base64
+ * Please send your issues, suggestions and pull requests there.
+ *
+ */
+
+object Base64 {
+
+ class B64Scheme(val encodeTable: IndexedSeq[Char]) {
+ lazy val decodeTable = collection.immutable.TreeMap(encodeTable.zipWithIndex: _*)
+ }
+
+ lazy val base64 = new B64Scheme(('A' to 'Z') ++ ('a' to 'z') ++ ('0' to '9') ++ Seq('+', '/'))
+ lazy val base64Url = new B64Scheme(base64.encodeTable.dropRight(2) ++ Seq('-', '_'))
+
+ implicit class Encoder(b: Array[Byte]) {
+ private[this] val zero = Array(0, 0).map(_.toByte)
+ lazy val pad = (3 - b.length % 3) % 3
+
+ def toBase64(implicit scheme: B64Scheme = base64): String = {
+ def sixBits(x: Array[Byte]): Seq[Int] = {
+ val a = (x(0) & 0xfc) >> 2
+ val b = ((x(0) & 0x3) << 4) + ((x(1) & 0xf0) >> 4)
+ val c = ((x(1) & 0xf) << 2) + ((x(2) & 0xc0) >> 6)
+ val d = (x(2)) & 0x3f
+ Seq(a, b, c, d)
+ }
+ ((b ++ zero.take(pad)).grouped(3)
+ .flatMap(sixBits(_))
+ .map(x => scheme.encodeTable(x))
+ .toSeq
+ .dropRight(pad) :+ "=" * pad)
+ .mkString
+ }
+ }
+
+ implicit class Decoder(s: String) {
+ lazy val cleanS = s.reverse.dropWhile(_ == '=').reverse
+ lazy val pad = s.length - cleanS.length
+
+ def toByteArray(implicit scheme: B64Scheme = base64): Array[Byte] = {
+ def threeBytes(s: Seq[Char]): Array[Byte] = {
+ val r = s.map(scheme.decodeTable(_)).foldLeft(0)((a,b)=>(a << 6) +b)
+ java.nio.ByteBuffer.allocate(8).putLong(r).array().takeRight(3)
+ }
+ if (pad > 2 || s.length % 4 != 0) throw new java.lang.IllegalArgumentException("Invalid Base64 String:" + s)
+ if (!cleanS.forall(scheme.encodeTable.contains(_))) throw new java.lang.IllegalArgumentException("Invalid Base64 String:" + s)
+
+ (cleanS + "A" * pad)
+ .grouped(4)
+ .map(threeBytes(_))
+ .flatten
+ .toArray
+ .dropRight(pad)
+ }
+ }
+
+}