Scala Pickling: Writing a custom pickler / unpickler for nested structures -
i'm trying write custom spickler / unpickler pair work around current limitations of scala-pickling. data type i'm trying pickle case class, of fields have own spickler , unpickler instances. i'd use these instances in custom pickler, don't know how.
here's example of mean:
// here's class want custom spickler / unpickler. // 1 of fields can pickled, i'd reuse logic. case class myclass[a: spickler: unpickler: fasttypetag](mystring: string, a: a) // here's custom pickler. class myclasspickler[a: spickler: unpickler: fasttypetag]( implicit val format: pickleformat) extends spickler[myclass[a]] unpickler[myclass[a]] { override def pickle( picklee: myclass[a], builder: pbuilder) { builder.beginentry(picklee) // here save `mystring` in custom way. builder.putfield( "myspecialpickler", b => b.hinttag(fasttypetag.scalastring).beginentry( picklee.mystring).endentry()) // need save `a`, has implicit spickler. // how use it? builder.endentry() } override def unpickle( tag: => fasttypetag[_], reader: preader): myclass[a] = { reader.beginentry() // first read string. val mystring = reader.readfield("myspecialpickler").unpickle[string] // need read `a`, has implicit unpickler. // how use it? val a: = ??? reader.endentry() myclass(mystring, a) } }
i appreciate working example. thanks!
here working example:
case class myclass[a](mystring: string, a: a)
note type parameter of myclass
not need context bounds. custom pickler class needs corresponding implicits:
class myclasspickler[a](implicit val format: pickleformat, atypetag: fasttypetag[a], apickler: spickler[a], aunpickler: unpickler[a]) extends spickler[myclass[a]] unpickler[myclass[a]] { private val stringunpickler = implicitly[unpickler[string]] override def pickle(picklee: myclass[a], builder: pbuilder) = { builder.beginentry(picklee) builder.putfield("mystring", b => b.hinttag(fasttypetag.scalastring).beginentry(picklee.mystring).endentry() ) builder.putfield("a", b => { b.hinttag(atypetag) apickler.pickle(picklee.a, b) } ) builder.endentry() } override def unpickle(tag: => fasttypetag[_], reader: preader): myclass[a] = { reader.hinttag(fasttypetag.scalastring) val tag = reader.beginentry() val mystringunpickled = stringunpickler.unpickle(tag, reader).asinstanceof[string] reader.endentry() reader.hinttag(atypetag) val atag = reader.beginentry() val aunpickled = aunpickler.unpickle(atag, reader).asinstanceof[a] reader.endentry() myclass(mystringunpickled, aunpickled) } }
in addition custom pickler class, need implicit def returns pickler instance specialized concrete type arguments:
implicit def myclasspickler[a: spickler: unpickler: fasttypetag](implicit pf: pickleformat) = new myclasspickler
Comments
Post a Comment