-
-
Save martintrojer/5823970 to your computer and use it in GitHub Desktop.
edn pickling
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import scala.pickling._ | |
import scala.reflect.runtime.universe._ | |
import scala.util.parsing.json._ | |
import scala.collection.mutable.{StringBuilder, Stack} | |
package object edn { | |
implicit val pickleFormat: EdnPickleFormat = new EdnPickleFormat | |
} | |
package edn { | |
case class EdnPickle(value: String) extends Pickle { | |
type ValueType = String | |
type PickleFormatType = EdnPickleFormat | |
} | |
class EdnPickleFormat extends PickleFormat { | |
type PickleType = EdnPickle | |
def createBuilder() = new EdnPickleBuilder(this) | |
def createReader(pickle: EdnPickle, mirror: Mirror) = ??? | |
} | |
class EdnPickleBuilder(format: EdnPickleFormat) extends PBuilder with PickleTools { | |
private val buf = new StringBuilder() | |
private val tags = new Stack[FastTypeTag[_]]() | |
private def append(s: String) = buf ++= s | |
private def pickleArray(arr: Array[_], tag: FastTypeTag[_]) = { | |
append("[") | |
hintStaticallyElidedType() | |
hintTag(tag) | |
pinHints() | |
var i = 0 | |
while (i < arr.length) { | |
putElement(b => b.beginEntry(arr(i)).endEntry()) | |
i += 1 | |
} | |
unpinHints() | |
append("]") | |
} | |
private val primitives = Map[String, Any => Unit]( | |
FastTypeTag.Null.key -> ((picklee: Any) => append("null")), | |
FastTypeTag.Int.key -> ((picklee: Any) => append(picklee.toString)), | |
FastTypeTag.Long.key -> ((picklee: Any) => append("\"" + JSONFormat.quoteString(picklee.toString) + "\"")), | |
FastTypeTag.Short.key -> ((picklee: Any) => append(picklee.toString)), | |
FastTypeTag.Double.key -> ((picklee: Any) => append(picklee.toString)), | |
FastTypeTag.Float.key -> ((picklee: Any) => append(picklee.toString)), | |
FastTypeTag.Boolean.key -> ((picklee: Any) => append(picklee.toString)), | |
FastTypeTag.Byte.key -> ((picklee: Any) => append(picklee.toString)), | |
FastTypeTag.Char.key -> ((picklee: Any) => append("\"" + JSONFormat.quoteString(picklee.toString) + "\"")), | |
FastTypeTag.ScalaString.key -> ((picklee: Any) => append("\"" + JSONFormat.quoteString(picklee.toString) + "\"")), | |
FastTypeTag.JavaString.key -> ((picklee: Any) => append("\"" + JSONFormat.quoteString(picklee.toString) + "\"")), | |
FastTypeTag.ArrayInt.key -> ((picklee: Any) => pickleArray(picklee.asInstanceOf[Array[Int]], FastTypeTag.Int)) | |
) | |
def beginEntry(picklee: Any): this.type = withHints { hints => | |
tags.push(hints.tag) | |
if (primitives.contains(hints.tag.key)) { | |
if (hints.isElidedType) primitives(hints.tag.key)(picklee) | |
else ??? | |
} else append("#pickling/" + typeToString(hints.tag.tpe) + " {") | |
this | |
} | |
def putField(name: String, pickler: this.type => Unit): this.type = { | |
append(" :" + name + " ") | |
pickler(this) | |
this | |
} | |
def endEntry(): Unit = { | |
if (primitives.contains(tags.pop().key)) {} // do nothing | |
else append(" }") | |
} | |
def beginCollection(length: Int): this.type = { | |
putField("elems", b => ()) | |
append("[") | |
this | |
} | |
def putElement(pickler: this.type => Unit): this.type = { | |
if (buf.toString.trim.last != '[') append(", ") | |
pickler(this) | |
this | |
} | |
def endCollection(l: Int): Unit = append("]") | |
def result(): EdnPickle = EdnPickle(buf.toString) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment