All Downloads are FREE. Search and download functionalities are using the official Maven repository.

boopickle.XCompat.scala Maven / Gradle / Ivy

The newest version!
package boopickle

import boopickle.Constants.NullRef

import collection.generic.CanBuildFrom
import scala.collection.generic.CanBuildFrom
import scala.language.higherKinds

trait XCompatImplicitPicklers {
  this: PicklerHelper =>

  implicit def mapPickler[T: P, S: P, V[_, _] <: scala.collection.Map[_, _]](implicit
      cbf: CanBuildFrom[Nothing, (T, S), V[T, S]]
  ): P[V[T, S]] =
    BasicPicklers.MapPickler[T, S, V]
  implicit def iterablePickler[T: P, V[_] <: Iterable[_]](implicit cbf: CanBuildFrom[Nothing, T, V[T]]): P[V[T]] =
    BasicPicklers.IterablePickler[T, V]
}

trait XCompatPicklers {
  this: PicklerHelper =>

  /**
    * This pickler works on all collections that derive from Iterable[T] (Vector, Set, List, etc)
    *
    * @tparam T
    *   type of the values
    * @tparam V
    *   type of the collection
    * @return
    */
  def IterablePickler[T: P, V[_] <: Iterable[_]](implicit cbf: CanBuildFrom[Nothing, T, V[T]]): P[V[T]] = new P[V[T]] {
    override def pickle(iterable: V[T])(implicit state: PickleState): Unit = {
      if (iterable == null) {
        state.enc.writeInt(NullRef)
      } else {
        // encode length
        state.enc.writeInt(iterable.size)
        // encode contents
        iterable.iterator.asInstanceOf[Iterator[T]].foreach(a => write[T](a))
      }
    }

    override def unpickle(implicit state: UnpickleState): V[T] = {
      state.dec.readInt match {
        case NullRef =>
          null.asInstanceOf[V[T]]
        case 0 =>
          // empty sequence
          val res = cbf().result()
          res
        case len =>
          val b = cbf()
          b.sizeHint(len)
          var i = 0
          while (i < len) {
            b += read[T]
            i += 1
          }
          val res = b.result()
          res
      }
    }
  }

  /**
    * Maps require a specific pickler as they have two type parameters.
    *
    * @tparam T
    *   Type of keys
    * @tparam S
    *   Type of values
    * @return
    */
  def MapPickler[T: P, S: P, V[_, _] <: scala.collection.Map[_, _]](implicit
      cbf: CanBuildFrom[Nothing, (T, S), V[T, S]]
  ): P[V[T, S]] =
    new P[V[T, S]] {
      override def pickle(map: V[T, S])(implicit state: PickleState): Unit = {
        if (map == null) {
          state.enc.writeInt(NullRef)
        } else {
          // encode length
          state.enc.writeInt(map.size)
          // encode contents as a sequence
          val kPickler = implicitly[P[T]]
          val vPickler = implicitly[P[S]]
          map.asInstanceOf[scala.collection.Map[T, S]].foreach { kv =>
            kPickler.pickle(kv._1)(state)
            vPickler.pickle(kv._2)(state)
          }
        }
      }

      override def unpickle(implicit state: UnpickleState): V[T, S] = {
        state.dec.readInt match {
          case NullRef =>
            null.asInstanceOf[V[T, S]]
          case 0 =>
            // empty map
            val res = cbf().result()
            res
          case idx if idx < 0 =>
            state.identityFor[V[T, S]](-idx)
          case len =>
            val b = cbf()
            b.sizeHint(len)
            val kPickler = implicitly[P[T]]
            val vPickler = implicitly[P[S]]
            var i        = 0
            while (i < len) {
              b += kPickler.unpickle(state) -> vPickler.unpickle(state)
              i += 1
            }
            val res = b.result()
            res
        }
      }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy