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

io.altoo.serialization.kryo.scala.serializer.ScalaMapSerializers.scala Maven / Gradle / Ivy

/**
 * *****************************************************************************
 * Copyright 2012 Roman Levenstein
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ****************************************************************************
 */

package io.altoo.serialization.kryo.scala.serializer

import com.esotericsoftware.kryo.kryo5.io.{Input, Output}
import com.esotericsoftware.kryo.kryo5.{Kryo, Serializer}

import java.lang.reflect.Constructor
import scala.collection.immutable.{Map as IMap, SortedMap}
import scala.collection.mutable.Map as MMap

/**
 * Module with specialized serializers for Scala Maps.
 * They are split in 3 different serializers in order:
 * 1. To not need reflection at runtime (find if it is SortedMap)
 * 2. Use inplace updates with mutable Maps
 *
 * @author luben
 */

class ScalaMutableMapSerializer() extends Serializer[MMap[?, ?]] {

  override def read(kryo: Kryo, input: Input, typ: Class[? <: MMap[?, ?]]): MMap[?, ?] = {
    val len = input.readInt(true)
    val coll = kryo.newInstance(typ).empty.asInstanceOf[MMap[Any, Any]]
    if (len != 0) {
      var i = 0
      while (i < len) {
        coll(kryo.readClassAndObject(input)) = kryo.readClassAndObject(input)
        i += 1
      }
    }
    coll
  }

  override def write(kryo: Kryo, output: Output, collection: MMap[?, ?]): Unit = {
    val len = collection.size
    output.writeInt(len, true)
    if (len != 0) {
      val it = collection.iterator
      while (it.hasNext) {
        val t = it.next()
        kryo.writeClassAndObject(output, t._1)
        kryo.writeClassAndObject(output, t._2)
      }
    }
  }
}

class ScalaImmutableMapSerializer() extends Serializer[IMap[?, ?]] {

  setImmutable(true)

  override def read(kryo: Kryo, input: Input, typ: Class[? <: IMap[?, ?]]): IMap[?, ?] = {
    val len = input.readInt(true)
    var coll: IMap[Any, Any] = kryo.newInstance(typ).asInstanceOf[IMap[Any, Any]].empty

    if (len != 0) {
      var i = 0
      while (i < len) {
        coll += kryo.readClassAndObject(input) -> kryo.readClassAndObject(input)
        i += 1
      }
    }
    coll
  }

  override def write(kryo: Kryo, output: Output, collection: IMap[?, ?]): Unit = {
    val len = collection.size
    output.writeInt(len, true)
    if (len != 0) {
      val it = collection.iterator
      while (it.hasNext) {
        val t = it.next()
        kryo.writeClassAndObject(output, t._1)
        kryo.writeClassAndObject(output, t._2)
      }
    }
  }
}

class ScalaImmutableAbstractMapSerializer() extends Serializer[IMap[?, ?]] {

  setImmutable(true)

  override def read(kryo: Kryo, input: Input, typ: Class[? <: IMap[?, ?]]): IMap[?, ?] = {
    val len = input.readInt(true)
    var coll: IMap[Any, Any] = IMap.empty

    if (len != 0) {
      var i = 0
      while (i < len) {
        coll += kryo.readClassAndObject(input) -> kryo.readClassAndObject(input)
        i += 1
      }
    }
    coll
  }

  override def write(kryo: Kryo, output: Output, collection: IMap[?, ?]): Unit = {
    val len = collection.size
    output.writeInt(len, true)
    if (len != 0) {
      val it = collection.iterator
      while (it.hasNext) {
        val t = it.next()
        kryo.writeClassAndObject(output, t._1)
        kryo.writeClassAndObject(output, t._2)
      }
    }
  }
}

class ScalaSortedMapSerializer() extends Serializer[SortedMap[?, ?]] {
  private var class2constuctor = IMap[Class[?], Constructor[?]]()

  // All sorted maps are immutable
  setImmutable(true)

  override def read(kryo: Kryo, input: Input, typ: Class[? <: SortedMap[?, ?]]): SortedMap[?, ?] = {
    val len = input.readInt(true)
    implicit val mapOrdering: Ordering[Any] = kryo.readClassAndObject(input).asInstanceOf[scala.math.Ordering[Any]]
    var coll: SortedMap[Any, Any] =
      try {
        val constructor = class2constuctor.getOrElse(typ, {
            val constr = typ.getDeclaredConstructor(classOf[scala.math.Ordering[?]])
            class2constuctor += typ -> constr
            constr
          })
        constructor.newInstance(mapOrdering).asInstanceOf[SortedMap[Any, Any]].empty
      } catch {
        case _: Throwable => kryo.newInstance(typ).asInstanceOf[SortedMap[Any, Any]].empty
      }

    var i = 0
    while (i < len) {
      coll += kryo.readClassAndObject(input) -> kryo.readClassAndObject(input)
      i += 1
    }
    coll
  }

  override def write(kryo: Kryo, output: Output, collection: SortedMap[?, ?]): Unit = {
    val len = collection.size
    output.writeInt(len, true)

    kryo.writeClassAndObject(output, collection.ordering)

    val it = collection.iterator
    while (it.hasNext) {
      val t = it.next()
      kryo.writeClassAndObject(output, t._1)
      kryo.writeClassAndObject(output, t._2)
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy