[Scala] Native mode rebuilds IntMap, LongMap, BitSet, mutable.LongMap and StringBuilder as a different collection class

Aperta
#4,102 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
68/100
Tipo di issue
Bug
Chiarezza
Abbastanza chiara
Stato di attività
Attiva
Stack tecnologico
scala
Ambito
backend

Direzione di ricerca

Start with ScalaCollectionSerializer, ScalaSeqSerializer and ScalaSortedSetSerializer in CollectionSerializer.scala, plus ScalaMapSerializer in MapSerializer.scala. Review the tests being added for #4100 and reproduce the listed collection cases across the affected modes. Done means round trips preserve each concrete collection type and ArraySeq representation without ClassCastException in typed fields.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug scala
Search before asking
  • I had searched in the issues and found no similar issues.
Version

main (1.8.0-SNAPSHOT), Scala 2.13.18 and 3.3.8

Component(s)

Scala

Minimal reproduce step
import org.apache.fory.scala.ForyScala
import scala.collection.immutable

case class Holder(m: immutable.IntMap[String])

val fory = ForyScala.builder()
  .withXlang(false)
  .withRefTracking(true)
  .requireClassRegistration(false)
  .build()

fory.deserialize(fory.serialize(Holder(immutable.IntMap(1 -> "a"))))
// DeserializationException caused by
// ClassCastException: scala.collection.immutable.Map$Map1 cannot be cast to scala.collection.immutable.IntMap
What did you expect to see?

A native-mode round trip should rebuild the same collection class, as it already does for List, Vector, HashMap, TreeMap, LinkedHashMap and others.

What did you see instead?

The native Scala collection serializers write the value's generic factory, iterableFactory, mapFactory or sortedIterableFactory. For these specialised kinds that factory builds a different class. The same happens in compatible and schema-consistent modes:

Written Read back as As a declared case class field
immutable.IntMap immutable.Map$Map1 / Map ClassCastException
immutable.LongMap immutable.Map$Map1 / Map ClassCastException
mutable.BitSet mutable.TreeSet ClassCastException
mutable.LongMap mutable.HashMap ClassCastException
mutable.StringBuilder mutable.ArrayBuffer[Char] ClassCastException
immutable.ArraySeq[Int] (ArraySeq$ofInt) ArraySeq$ofRef (boxed) works, but loses the unboxed representation

As a root value, the decoded collection compares equal to the original, so the change goes unnoticed until a typed field or a pattern match depends on the concrete class.

Anything Else?

The factories are chosen in ScalaCollectionSerializer, ScalaSeqSerializer, ScalaSortedSetSerializer and ScalaMapSerializer (CollectionSerializer.scala and MapSerializer.scala). These kinds probably need their specific factory or a dedicated serializer, for example IntMap/LongMap factories, BitSet from its bitmask, StringBuilder as a string, and ArraySeq keeping its element ClassTag.

Related: #4101 covers the registration gap for several of the same types. Found while adding tests in #4100.

Are you willing to submit a PR?
  • I'm willing to submit a PR!
Lingua principale
Java
Stelle
4.6k
Fork
470
Merge medio
9h 28m
PR unite (30g)
33

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di apache/fory

Tutte le issue di apache/fory

Issue simili

Altre issue su Java

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.