From 8bdfa1a4f6dbc594760ff7c848e5c278588ace58 Mon Sep 17 00:00:00 2001 From: Anubhab2003 Date: Tue, 21 Jan 2025 11:59:31 +0530 Subject: [PATCH] Added copy support for Scala serializers --- .../scala/CollectionSerializer.scala | 53 +++++++++++++++++++ .../fury/serializer/scala/MapSerializer.scala | 41 ++++++++++++++ .../serializer/scala/SerializerTest.scala | 24 +++++++++ 3 files changed, 118 insertions(+) create mode 100644 scala/src/test/scala/org/apache/fury/serializer/scala/SerializerTest.scala diff --git a/scala/src/main/scala/org/apache/fury/serializer/scala/CollectionSerializer.scala b/scala/src/main/scala/org/apache/fury/serializer/scala/CollectionSerializer.scala index 0c116e864f..b43c51a6c8 100644 --- a/scala/src/main/scala/org/apache/fury/serializer/scala/CollectionSerializer.scala +++ b/scala/src/main/scala/org/apache/fury/serializer/scala/CollectionSerializer.scala @@ -185,3 +185,56 @@ class ScalaSeqSerializer[A, T <: scala.collection.Seq[A]](fury: Fury, cls: Class new ListAdapter[Any](value) } } +abstract class AbstractScalaCollectionSerializer[A, T <: Iterable[A]](fury: Fury, cls: Class[T]) + extends AbstractCollectionSerializer[T](fury, cls) { + + // Existing methods + + // Add copy method + def copy(value: T): T = { + val builder = value.iterableFactory.newBuilder[A] + builder ++= value + builder.result() + } +} + +class ScalaCollectionSerializer[A, T <: Iterable[A]] (fury: Fury, cls: Class[T]) + extends AbstractScalaCollectionSerializer[A, T](fury, cls) { + override def onCollectionWrite(buffer: MemoryBuffer, value: T): util.Collection[_] = { + val factory: Factory[A, Any] = value.iterableFactory.iterableFactory + val adapter = new CollectionAdapter[A, T](value) + buffer.writeVarUint32Small7(adapter.size) + fury.writeRef(buffer, factory) + adapter + } + + // Implement copy method + override def copy(value: T): T = super.copy(value) +} + +class ScalaSortedSetSerializer[A, T <: scala.collection.SortedSet[A]](fury: Fury, cls: Class[T]) + extends AbstractScalaCollectionSerializer[A, T](fury, cls) { + override def onCollectionWrite(buffer: MemoryBuffer, value: T): util.Collection[_] = { + buffer.writeVarUint32Small7(value.size) + val factory = value.sortedIterableFactory.evidenceIterableFactory[Any]( + value.ordering.asInstanceOf[Ordering[Any]]) + fury.writeRef(buffer, factory) + new CollectionAdapter[A, T](value) + } + + // Implement copy method + override def copy(value: T): T = super.copy(value) +} + +class ScalaSeqSerializer[A, T <: scala.collection.Seq[A]](fury: Fury, cls: Class[T]) + extends AbstractScalaCollectionSerializer[A, T](fury, cls) { + override def onCollectionWrite(buffer: MemoryBuffer, value: T): util.Collection[_] = { + buffer.writeVarUint32Small7(value.size) + val factory: Factory[A, Any] = value.iterableFactory.iterableFactory + fury.writeRef(buffer, factory) + new ListAdapter[Any](value) + } + + // Implement copy method + override def copy(value: T): T = super.copy(value) +} diff --git a/scala/src/main/scala/org/apache/fury/serializer/scala/MapSerializer.scala b/scala/src/main/scala/org/apache/fury/serializer/scala/MapSerializer.scala index 4f68119381..3d373a6c64 100644 --- a/scala/src/main/scala/org/apache/fury/serializer/scala/MapSerializer.scala +++ b/scala/src/main/scala/org/apache/fury/serializer/scala/MapSerializer.scala @@ -142,3 +142,44 @@ class ScalaSortedMapSerializer[K, V, T <: scala.collection.SortedMap[K, V]](fury new MapAdapter[K, V](value) } } + +abstract class AbstractScalaMapSerializer[K, V, T](fury: Fury, cls: Class[T]) + extends AbstractMapSerializer[T](fury, cls) { + + // Existing methods + + // Add copy method + def copy(value: T): T = { + val builder = value.mapFactory.newBuilder[K, V] + builder ++= value + builder.result() + } +} + +class ScalaMapSerializer[K, V, T <: scala.collection.Map[K, V]](fury: Fury, cls: Class[T]) + extends AbstractScalaMapSerializer[K, V, T](fury, cls) { + + override def onMapWrite(buffer: MemoryBuffer, value: T): util.Map[_, _] = { + buffer.writeVarUint32Small7(value.size) + val factory = value.mapFactory.mapFactory[Any, Any].asInstanceOf[Factory[Any, Any]] + fury.writeRef(buffer, factory) + new MapAdapter[K, V](value) + } + + // Implement copy method + override def copy(value: T): T = super.copy(value) +} + +class ScalaSortedMapSerializer[K, V, T <: scala.collection.SortedMap[K, V]](fury: Fury, cls: Class[T]) + extends AbstractScalaMapSerializer[K, V, T](fury, cls) { + override def onMapWrite(buffer: MemoryBuffer, value: T): util.Map[_, _] = { + buffer.writeVarUint32Small7(value.size) + val factory = value.sortedMapFactory.sortedMapFactory[Any, Any]( + value.ordering.asInstanceOf[Ordering[Any]]).asInstanceOf[Factory[Any, Any]] + fury.writeRef(buffer, factory) + new MapAdapter[K, V](value) + } + + // Implement copy method + override def copy(value: T): T = super.copy(value) +} diff --git a/scala/src/test/scala/org/apache/fury/serializer/scala/SerializerTest.scala b/scala/src/test/scala/org/apache/fury/serializer/scala/SerializerTest.scala new file mode 100644 index 0000000000..565dcae1aa --- /dev/null +++ b/scala/src/test/scala/org/apache/fury/serializer/scala/SerializerTest.scala @@ -0,0 +1,24 @@ +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers + +class SerializerTest extends AnyFlatSpec with Matchers { + "ScalaCollectionSerializer" should "copy collections correctly" in { + val fury = new Fury() + val original = Seq(1, 2, 3) + val serializer = new ScalaCollectionSerializer[Int, Seq[Int]](fury, classOf[Seq[Int]]) + + val copy = serializer.copy(original) + copy shouldEqual original + copy should not be theSameInstanceAs (original) + } + + "ScalaMapSerializer" should "copy maps correctly" in { + val fury = new Fury() + val original = Map("a" -> 1, "b" -> 2) + val serializer = new ScalaMapSerializer[String, Int, Map[String, Int]](fury, classOf[Map[String, Int]]) + + val copy = serializer.copy(original) + copy shouldEqual original + copy should not be theSameInstanceAs (original) + } +}