Skip to content

Commit d03e693

Browse files
committed
serialisation compatability before we change the red black trees
1 parent be4b31b commit d03e693

File tree

4 files changed

+100
-6
lines changed

4 files changed

+100
-6
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Scala (https://www.scala-lang.org)
3+
*
4+
* Copyright EPFL and Lightbend, Inc.
5+
*
6+
* Licensed under Apache License 2.0
7+
* (http://www.apache.org/licenses/LICENSE-2.0).
8+
*
9+
* See the NOTICE file distributed with this work for
10+
* additional information regarding copyright ownership.
11+
*/
12+
13+
package scala.collection.immutable
14+
15+
import java.io.IOException
16+
import scala.annotation.meta.getter
17+
18+
private[immutable] object RedBlackTree {
19+
20+
// Trees for serialisation compat with 2.12 legacy format
21+
// allow the format to be written in that manner for 2.12.11 and before
22+
//on write this is the same format as before
23+
//on read the `readResolve` will convert to the NewRedBlackTree format
24+
25+
// the Tree children must be AnyRef as during construction then are RedBlackTree.Tree
26+
// due to the readResolve the tree is migrated to new format and the children will be converted to
27+
// NewRedBlackTree as they are read
28+
29+
@SerialVersionUID(7757490705548110898L)
30+
sealed abstract class Tree[A, +B](
31+
@(inline@getter) final val key: A,
32+
@(inline@getter) final val value: B,
33+
@(inline@getter) final val left: AnyRef,
34+
@(inline@getter) final val right: AnyRef)
35+
extends Serializable {
36+
private def _count(tree: AnyRef) = if (tree eq null) 0 else tree.asInstanceOf[Tree[A, B]].count
37+
@(inline @getter) final val count: Int = 1 + _count(left) + _count(right)
38+
}
39+
40+
@SerialVersionUID(6516527240275040268L)
41+
final class RedTree[A, +B](key: A,
42+
value: B,
43+
left: AnyRef,
44+
right: AnyRef) extends Tree[A, B](key, value, left, right) {
45+
@throws[IOException]
46+
private[this] def readResolve(): AnyRef =
47+
NewRedBlackTree.RedTree(key, value,
48+
this.left.asInstanceOf[NewRedBlackTree.Tree[A, B]],
49+
this.right.asInstanceOf[NewRedBlackTree.Tree[A, B]])
50+
51+
override def toString: String = "RedTree(" + key + ", " + value + ", " + left + ", " + right + ")"
52+
}
53+
54+
@SerialVersionUID(-3666942709716265983L)
55+
final class BlackTree[A, +B](key: A,
56+
value: B,
57+
left: AnyRef,
58+
right: AnyRef) extends Tree[A, B](key, value, left, right) {
59+
@throws[IOException]
60+
private[this] def readResolve(): AnyRef =
61+
NewRedBlackTree.BlackTree(key, value,
62+
this.left.asInstanceOf[NewRedBlackTree.Tree[A, B]],
63+
this.right.asInstanceOf[NewRedBlackTree.Tree[A, B]])
64+
65+
override def toString: String = "BlackTree(" + key + ", " + value + ", " + left + ", " + right + ")"
66+
}
67+
68+
def from[A, B](tree: NewRedBlackTree.Tree[A, B]): Tree[A, B] = {
69+
if (tree eq null) null
70+
else {
71+
val left = from(tree.left)
72+
val right = from(tree.right)
73+
if (NewRedBlackTree.isBlack(tree))
74+
new BlackTree(tree.key, tree.value, left, right)
75+
else
76+
new RedTree(tree.key, tree.value, left, right)
77+
}
78+
}
79+
80+
}

library/src/scala/collection/immutable/RedBlackTree.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import java.lang.{Integer, String}
2828
* easily be used. The API represented by the RedBlackTree object tries to hide these
2929
* optimizations behind a reasonably clean API.
3030
*/
31-
private[collection] object RedBlackTree {
31+
private[collection] object NewRedBlackTree {
3232

3333
def isEmpty(tree: Tree[_, _]): Boolean = tree eq null
3434

@@ -378,7 +378,7 @@ private[collection] object RedBlackTree {
378378
@(`inline` @getter) final val left: Tree[A, B],
379379
@(`inline` @getter) final val right: Tree[A, B]) extends Serializable
380380
{
381-
@(`inline` @getter) final val count: Int = 1 + RedBlackTree.count(left) + RedBlackTree.count(right)
381+
@(`inline` @getter) final val count: Int = 1 + NewRedBlackTree.count(left) + NewRedBlackTree.count(right)
382382
def black: Tree[A, B]
383383
def red: Tree[A, B]
384384
}

library/src/scala/collection/immutable/TreeMap.scala

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ package immutable
1717
import java.io.IOException
1818

1919
import generic._
20-
import immutable.{RedBlackTree => RB}
20+
import immutable.{NewRedBlackTree => RB}
2121
import mutable.Builder
2222
import scala.util.hashing.MurmurHash3
2323

@@ -93,7 +93,7 @@ object TreeMap extends ImmutableSortedMapFactory[TreeMap] {
9393
private val legacySerialisation = System.getProperty("scala.collection.immutable.TreeMap.newSerialisation", "false") != "false"
9494

9595
private class TreeMapProxy[A, B](
96-
@transient private[this] var tree: RedBlackTree.Tree[A, B],
96+
@transient private[this] var tree: RB.Tree[A, B],
9797
@transient private[this] var ordering: Ordering[A]) extends Serializable {
9898

9999
@throws[IOException]
@@ -387,4 +387,12 @@ final class TreeMap[A, +B] private (tree: RB.Tree[A, B])(implicit val ordering:
387387
@throws[IOException]
388388
private[this] def writeReplace(out: java.io.ObjectOutputStream): AnyRef =
389389
if (TreeMap.legacySerialisation) this else new TreeMap.TreeMapProxy(tree, ordering)
390+
391+
@throws[IOException]
392+
private[this] def writeObject(out: java.io.ObjectOutputStream) = {
393+
out.writeObject(ordering)
394+
out.writeObject(RedBlackTree.from(tree))
395+
}
396+
397+
390398
}

library/src/scala/collection/immutable/TreeSet.scala

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ package immutable
1717
import java.io.IOException
1818

1919
import generic._
20-
import immutable.{RedBlackTree => RB}
20+
import immutable.{NewRedBlackTree => RB}
2121
import mutable.Builder
2222

2323
/** $factoryInfo
@@ -59,7 +59,7 @@ object TreeSet extends ImmutableSortedSetFactory[TreeSet] {
5959
private val legacySerialisation = System.getProperty("scala.collection.immutable.TreeSet.newSerialisation", "false") != "false"
6060

6161
private class TreeSetProxy[A](
62-
@transient private[this] var tree: RedBlackTree.Tree[A, Any],
62+
@transient private[this] var tree: RB.Tree[A, Any],
6363
@transient private[this] var ordering: Ordering[A]) extends Serializable {
6464

6565
@throws[IOException]
@@ -283,4 +283,10 @@ final class TreeSet[A] private[immutable] (private[immutable] val tree: RB.Tree[
283283
@throws[IOException]
284284
private[this] def writeReplace(out: java.io.ObjectOutputStream): AnyRef =
285285
if (TreeSet.legacySerialisation) this else new TreeSet.TreeSetProxy(tree, ordering)
286+
287+
@throws[IOException]
288+
private[this] def writeObject(out: java.io.ObjectOutputStream) = {
289+
out.writeObject(ordering)
290+
out.writeObject(RedBlackTree.from(tree))
291+
}
286292
}

0 commit comments

Comments
 (0)