Skip to content
This repository has been archived by the owner on Feb 20, 2019. It is now read-only.

Commit

Permalink
genListPickler supports lists of non-primitive elements
Browse files Browse the repository at this point in the history
  • Loading branch information
phaller committed Jul 12, 2013
1 parent 85bcf3d commit 01cb5cf
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 22 deletions.
48 changes: 26 additions & 22 deletions core/src/main/scala/pickling/Custom.scala
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ trait CorePicklersUnpicklers extends GenPicklers with GenUnpicklers with LowPrio
implicit val doublePicklerUnpickler: SPickler[Double] with Unpickler[Double] = new PrimitivePicklerUnpickler[Double]
implicit val nullPicklerUnpickler: SPickler[Null] with Unpickler[Null] = new PrimitivePicklerUnpickler[Null]

implicit def genListPickler[T](implicit format: PickleFormat): SPickler[::[T]] with Unpickler[::[T]] = macro Compat.ListPicklerUnpicklerMacro_impl[T]
implicit def genListPickler[T](implicit format: PickleFormat): SPickler[::[T]] with Unpickler[::[T]] =
macro Compat.ListPicklerUnpicklerMacro_impl[T]
// TODO: figure out why this is slower than traversablePickler
// implicit def genVectorPickler[T](implicit format: PickleFormat): Pickler[Vector[T]] with Unpickler[Vector[T]] = macro VectorPicklerUnpicklerMacro.impl[T]
}
Expand Down Expand Up @@ -142,7 +143,9 @@ trait CollectionPicklerUnpicklerMacro extends Macro {
import scala.reflect.runtime.universe._
import scala.pickling._
import scala.pickling.`package`.PickleOps

val format = new ${format.tpe}()

implicit val elpickler: SPickler[$eltpe] = {
val elpickler = "bam!"
implicitly[SPickler[$eltpe]]
Expand All @@ -155,47 +158,48 @@ trait CollectionPicklerUnpicklerMacro extends Macro {
val eltag = "bam!"
implicitly[scala.pickling.FastTypeTag[$eltpe]]
}

def pickle(picklee: $tpe, builder: PBuilder): Unit = {
if (!$isPrimitive) throw new PicklingException(s"implementation restriction: non-primitive collections aren't supported")
builder.beginEntry()
// TODO: this needs to be adjusted to work with non-primitive types
// 1) elisions might need to be set on per-element basis
// 2) val elpicker needs to be turned into def elpickler(el: $$eltpe) which would do dispatch
// 3) hint pinning would need to work with potentially nested picklings of elements
// ============
builder.hintStaticallyElidedType()
builder.hintTag(eltag)
builder.pinHints()
// ============
if ($isPrimitive) {
builder.hintStaticallyElidedType()
builder.hintTag(eltag)
builder.pinHints()
}
val arr = ${mkArray(q"picklee")}
val length = arr.length
builder.beginCollection(arr.length)
var i = 0
while (i < arr.length) {
builder.putElement(b => elpickler.pickle(arr(i), b))
builder putElement { b =>
if (!$isPrimitive) b.hintTag(eltag)
elpickler.pickle(arr(i), b)
}
i += 1
}
builder.unpinHints()
if ($isPrimitive) builder.unpinHints()
builder.endCollection(i)
builder.endEntry()
}
def unpickle(tag: => scala.pickling.FastTypeTag[_], reader: PReader): Any = {
if (!$isPrimitive) throw new PicklingException(s"implementation restriction: non-primitive collections aren't supported")
var buffer = ${mkBuffer(eltpe)}
val arrReader = reader.beginCollection()
// TODO: this needs to be adjusted to work with non-primitive types
arrReader.hintStaticallyElidedType()
arrReader.hintTag(eltag)
arrReader.pinHints()
if ($isPrimitive) {
arrReader.hintStaticallyElidedType()
arrReader.hintTag(eltag)
arrReader.pinHints()
}
val length = arrReader.readLength()
var i = 0
while (i < length) {
arrReader.beginEntry()
buffer += arrReader.readPrimitive().asInstanceOf[$eltpe]
arrReader.endEntry()
val r = arrReader.readElement()
r.beginEntryNoTag()
val elem = elunpickler.unpickle(eltag, r)
r.endEntry()
buffer += elem.asInstanceOf[$eltpe]
i += 1
}
arrReader.unpinHints()
if ($isPrimitive) arrReader.unpinHints()
arrReader.endCollection()
${mkResult(q"buffer")}
}
Expand Down
16 changes: 16 additions & 0 deletions core/src/test/scala/pickling/binary-list-object.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package scala.pickling.binary.list.obj

import org.scalatest.FunSuite

import scala.pickling._
import binary._

case class Person(name: String)

class BinaryListObjectTest extends FunSuite {
test("main") {
val lst = List(Person("A"), Person("B"), Person("C"))
val pickle = lst.pickle
assert(pickle.unpickle[List[Person]] == List(Person("A"), Person("B"), Person("C")))
}
}

0 comments on commit 01cb5cf

Please sign in to comment.