diff --git a/.scalafmt.conf b/.scalafmt.conf new file mode 100644 index 0000000..3c89bd1 --- /dev/null +++ b/.scalafmt.conf @@ -0,0 +1,7 @@ +version = "2.7.5" +align.preset = more +docstrings = JavaDoc +assumeStandardLibraryStripMargin = true +project.git = true +maxColumn = 100 +trailingCommas = multiple diff --git a/build.sbt b/build.sbt index 6d6a88a..09d8717 100644 --- a/build.sbt +++ b/build.sbt @@ -1,18 +1,19 @@ -lazy val root = project.in(file(".")) +lazy val root = project + .in(file(".")) .aggregate(scalaLibraryNextJVM, scalaLibraryNextJS) .settings( publish / skip := true, // With CrossType.Pure, the root project also picks up the sources in `src` Compile / unmanagedSourceDirectories := Nil, - Test / unmanagedSourceDirectories := Nil, + Test / unmanagedSourceDirectories := Nil, ) lazy val scalaLibraryNext = crossProject(JVMPlatform, JSPlatform) .crossType(CrossType.Pure) .in(file(".")) .jvmSettings( - libraryDependencies += "junit" % "junit" % "4.13.1" % Test, - libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % Test, + libraryDependencies += "junit" % "junit" % "4.13.1" % Test, + libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % Test, testOptions += Tests.Argument(TestFrameworks.JUnit, "-a", "-v"), ) .jsConfigure(_.enablePlugins(ScalaJSJUnitPlugin)) @@ -21,11 +22,11 @@ lazy val scalaLibraryNext = crossProject(JVMPlatform, JSPlatform) scalaModuleMimaPreviousVersion := None, scalacOptions ++= Seq("-deprecation", "-feature", "-Werror"), libraryDependencies ++= Seq( - "org.scalacheck" %%% "scalacheck" % "1.15.0" % Test, + "org.scalacheck" %%% "scalacheck" % "1.15.0" % Test ), ) .jsSettings( - Test / fork := false, + Test / fork := false ) lazy val scalaLibraryNextJVM = scalaLibraryNext.jvm diff --git a/project/plugins.sbt b/project/plugins.sbt index 5ccad05..f9a6a26 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,3 +1,4 @@ -addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.3") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.3.0") -addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.0.0") +addSbtPlugin("org.scala-lang.modules" % "sbt-scala-module" % "2.2.3") +addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.2") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.3.0") +addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.0.0") diff --git a/src/main/scala/scala/collection/SeqSet.scala b/src/main/scala/scala/collection/SeqSet.scala new file mode 100644 index 0000000..6f27019 --- /dev/null +++ b/src/main/scala/scala/collection/SeqSet.scala @@ -0,0 +1,37 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala.collection + +/** + * A generic trait for ordered sets. Concrete classes have to provide + * functionality for the abstract methods in `SeqSet`. + * + * Note that when checking for equality [[SeqSet]] does not take into account + * ordering. + * + * @tparam A the type of the values contained in this linked set. + * @define coll seq set + * @define Coll `collection.SeqSet` + */ +trait SeqSet[A] + extends Set[A] + with SetOps[A, SeqSet, SeqSet[A]] + with IterableFactoryDefaults[A, SeqSet] { + override def iterableFactory: IterableFactory[SeqSet] = SeqSet +} + +object SeqSet extends IterableFactory.Delegate[SeqSet](immutable.SeqSet) { + def fromMap(factory: MapFactory[SeqMap]): IterableFactory[SeqSet] = SeqSetFromMap(factory) + + def fromMap[A](map: SeqMap[A, Unit]): SeqSet[A] = SeqSetFromMap(map) +} diff --git a/src/main/scala/scala/collection/SetFromMap.scala b/src/main/scala/scala/collection/SetFromMap.scala new file mode 100644 index 0000000..699ea27 --- /dev/null +++ b/src/main/scala/scala/collection/SetFromMap.scala @@ -0,0 +1,145 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala +package collection + +import scala.collection.generic.DefaultSerializable + +@SerialVersionUID(3L) +private class SetFromMap[A](protected[collection] val underlying: Map[A, Unit]) + extends AbstractSet[A] + with SetFromMapOps.Unknown[A, Map, Map[A, Unit], SetFromMap, SetFromMap[A]] + with SetFromMapOps.Unsorted[A, Map, SetFromMap] + with SetFromMapOps.DynamicClassName + with IterableFactoryDefaults[A, SetFromMap] + with DefaultSerializable { + protected[this] def fromMap[B](m: Map[B, Unit]): SetFromMap[B] = new SetFromMap(m) + + override def iterableFactory: IterableFactory[SetFromMap] = + new SetFromMap.WrapperFactory(underlying.mapFactory) +} + +private object SetFromMap extends SetFromMapMetaFactory[Map, Set] { + def apply(factory: MapFactory[Map]): IterableFactory[Set] = new DynamicFactory(factory) + + // Dynamically create a narrower return type as a best-effort + // not to lose runtime type information from the `Map`. + def apply[A](map: Map[A, Unit]): Set[A] = map match { + case map: immutable.Map[A, Unit] => immutable.SetFromMap(map) + case map: concurrent.Map[A, Unit] => concurrent.SetFromMap(map) + case map: mutable.Map[A, Unit] => mutable.SetFromMap(map) + case map: SeqMap[A, Unit] => new SeqSetFromMap(map) + case map: SortedMap[A, Unit] => new SortedSetFromMap(map)(map.ordering) + case map => new SetFromMap(map) + } + + @SerialVersionUID(3L) + private class WrapperFactory(mf: MapFactory[Map]) extends SetFromMapFactory[Map, SetFromMap](mf) { + protected[this] def fromMap[A](map: Map[A, Unit]): SetFromMap[A] = + new SetFromMap(map) + } + + @SerialVersionUID(3L) + private class DynamicFactory(mf: MapFactory[Map]) extends SetFromMapFactory[Map, Set](mf) { + protected[this] def fromMap[A](map: Map[A, Unit]): Set[A] = SetFromMap(map) + } + +} + +@SerialVersionUID(3L) +private class SeqSetFromMap[A](protected[collection] val underlying: SeqMap[A, Unit]) + extends AbstractSet[A] + with SetFromMapOps.Unknown[A, SeqMap, SeqMap[A, Unit], SeqSetFromMap, SeqSetFromMap[A]] + with SetFromMapOps.Unsorted[A, SeqMap, SeqSetFromMap] + with SetFromMapOps.DynamicClassName + with SeqSet[A] + with IterableFactoryDefaults[A, SeqSetFromMap] + with DefaultSerializable { + protected[this] def fromMap[B](m: SeqMap[B, Unit]): SeqSetFromMap[B] = new SeqSetFromMap(m) + + override def iterableFactory: IterableFactory[SeqSetFromMap] = + new SeqSetFromMap.WrapperFactory(underlying.mapFactory) +} + +private object SeqSetFromMap extends SetFromMapMetaFactory[SeqMap, SeqSet] { + def apply(factory: MapFactory[SeqMap]): IterableFactory[SeqSet] = new DynamicFactory(factory) + + def apply[A](map: SeqMap[A, Unit]): SeqSet[A] = map match { + case map: immutable.SeqMap[A, Unit] => immutable.SeqSetFromMap(map) + case map: mutable.SeqMap[A, Unit] => mutable.SeqSetFromMap(map) + case map => new SeqSetFromMap(map) + } + + @SerialVersionUID(3L) + private class WrapperFactory(mf: MapFactory[SeqMap]) + extends SetFromMapFactory[SeqMap, SeqSetFromMap](mf) { + protected[this] def fromMap[A](map: SeqMap[A, Unit]): SeqSetFromMap[A] = + new SeqSetFromMap(map) + } + + @SerialVersionUID(3L) + private class DynamicFactory(mf: MapFactory[SeqMap]) + extends SetFromMapFactory[SeqMap, SeqSet](mf) { + protected[this] def fromMap[A](map: SeqMap[A, Unit]): SeqSet[A] = SeqSetFromMap(map) + } + +} + +@SerialVersionUID(3L) +private class SortedSetFromMap[A](protected[collection] val underlying: SortedMap[A, Unit])(implicit + val ordering: Ordering[A] +) extends AbstractSet[A] + with SetFromMapOps.Unknown[A, Map, SortedMap[A, Unit], Set, SortedSetFromMap[A]] + with SetFromMapOps.Sorted[A, SortedMap, Set, SortedSetFromMap] + with SetFromMapOps.DynamicClassName + with SortedSet[A] + with SortedSetOps[A, SortedSetFromMap, SortedSetFromMap[A]] + with IterableFactoryDefaults[A, Set] + with SortedSetFactoryDefaults[A, SortedSetFromMap, Set] + with DefaultSerializable { + protected[this] def fromMap[B](m: Map[B, Unit]): SetFromMap[B] = new SetFromMap(m) + + protected[this] def fromSortedMap[B: Ordering](m: SortedMap[B, Unit]): SortedSetFromMap[B] = + new SortedSetFromMap(m) + + override def iterableFactory: IterableFactory[Set] = SetFromMap(underlying.mapFactory) + + override def sortedIterableFactory: SortedIterableFactory[SortedSetFromMap] = + new SortedSetFromMap.WrapperFactory(underlying.sortedMapFactory) +} + +private object SortedSetFromMap extends SortedSetFromMapMetaFactory[SortedMap, SortedSet] { + def apply(factory: SortedMapFactory[SortedMap]): SortedIterableFactory[SortedSet] = + new DynamicFactory(factory) + + def apply[A](map: SortedMap[A, Unit]): SortedSet[A] = map match { + case map: immutable.SortedMap[A, Unit] => immutable.SortedSetFromMap(map) + case map: mutable.SortedMap[A, Unit] => mutable.SortedSetFromMap(map) + case map => new SortedSetFromMap(map)(map.ordering) + } + + @SerialVersionUID(3L) + private final class WrapperFactory(mf: SortedMapFactory[SortedMap]) + extends SortedSetFromMapFactory[SortedMap, SortedSetFromMap](mf) { + protected[this] def fromMap[A](map: SortedMap[A, Unit]): SortedSetFromMap[A] = + new SortedSetFromMap(map)(map.ordering) + } + + @SerialVersionUID(3L) + private class DynamicFactory(mf: SortedMapFactory[SortedMap]) + extends SortedSetFromMapFactory[SortedMap, SortedSet](mf) { + protected[this] def fromMap[A](map: SortedMap[A, Unit]): SortedSet[A] = + SortedSetFromMap(map) + } + +} diff --git a/src/main/scala/scala/collection/SetFromMapOps.scala b/src/main/scala/scala/collection/SetFromMapOps.scala new file mode 100644 index 0000000..ffdd361 --- /dev/null +++ b/src/main/scala/scala/collection/SetFromMapOps.scala @@ -0,0 +1,399 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala +package collection + +import scala.annotation.implicitNotFound +import scala.collection.SetFromMapOps.WrappedMap +import scala.reflect.ClassTag + +// Implementation note: The `concurrent.Set` implementation +// inherits from this, so we have to be careful about +// making changes that do more than forward to the +// underlying `Map`. If we have a method implementation +// that is not atomic, we MUST override that method in +// `concurrent.SetFromMap`. +private trait SetFromMapOps[ + A, + +MM[K, V] <: MapOps[K, V, MM, _], + +M <: MapOps[A, Unit, MM, M], + +CC[_], + +C <: SetFromMapOps[A, MM, M, CC, C], +] extends SetOps[A, CC, C] + with WrappedMap[A] + with Serializable { + protected[collection] val underlying: M + + protected[this] def fromMap[B](m: MM[B, Unit]): CC[B] + + protected[this] def fromSpecificMap(m: M): C + + // methods for adapting functions for a set to functions for a map + @inline protected[this] def adapted[B](f: A => B): ((A, Unit)) => B = { case (elem, _) => + f(elem) + } + + @inline protected[this] def adaptedTuple[B](f: A => B): ((A, Unit)) => (B, Unit) = { + case (elem, _) => f(elem) -> () + } + + @inline protected[this] def adaptedTuplePF[B]( + pf: PartialFunction[A, B] + ): PartialFunction[(A, Unit), (B, Unit)] = + adapted(pf.lift).andThen(_.map(_ -> ())).unlift + + def contains(elem: A): Boolean = underlying contains elem + + def iterator: Iterator[A] = underlying.keysIterator + + override def isEmpty: Boolean = underlying.isEmpty + + override def size: Int = underlying.size + + override def knownSize: Int = underlying.knownSize + + override def head: A = underlying.head._1 + + override def headOption: Option[A] = underlying.headOption.map(_._1) + + override def last: A = underlying.last._1 + + override def lastOption: Option[A] = underlying.lastOption.map(_._1) + + override def collect[B](pf: PartialFunction[A, B]): CC[B] = fromMap( + underlying collect adaptedTuplePF(pf) + ) + + override def collectFirst[B](pf: PartialFunction[A, B]): Option[B] = + underlying collectFirst adapted(pf.lift).unlift + + override def copyToArray[B >: A](xs: Array[B], start: Int): Int = + underlying.keySet.copyToArray(xs, start) + + override def copyToArray[B >: A](xs: Array[B], start: Int, len: Int): Int = + underlying.keySet.copyToArray(xs, start, len) + + override def count(p: A => Boolean): Int = underlying.keySet count p + + override def drop(n: Int): C = fromSpecificMap(underlying drop n) + + override def dropRight(n: Int): C = fromSpecificMap(underlying dropRight n) + + override def dropWhile(p: A => Boolean): C = fromSpecificMap(underlying dropWhile adapted(p)) + + override def exists(p: A => Boolean): Boolean = underlying exists adapted(p) + + override def filter(pred: A => Boolean): C = fromSpecificMap(underlying filter adapted(pred)) + + override def filterNot(pred: A => Boolean): C = fromSpecificMap( + underlying filterNot adapted(pred) + ) + + override def find(p: A => Boolean): Option[A] = underlying.keySet find p + + override def flatMap[B](f: A => IterableOnce[B]): CC[B] = fromMap { + underlying flatMap { case (elem, _) => + f(elem) match { + case that: WrappedMap[B] => that.underlying + case that => that.iterator map { _ -> () } + } + } + } + + override def flatten[B](implicit asIterable: A => IterableOnce[B]): CC[B] = flatMap(asIterable) + + override def foldLeft[B](z: B)(op: (B, A) => B): B = underlying.keySet.foldLeft(z)(op) + + override def foldRight[B](z: B)(op: (A, B) => B): B = underlying.keySet.foldRight(z)(op) + + override def forall(p: A => Boolean): Boolean = underlying.keySet forall p + + override def foreach[U](f: A => U): Unit = underlying.keySet foreach f + + override def groupMapReduce[K, B](key: A => K)(f: A => B)( + reduce: (B, B) => B + ): immutable.Map[K, B] = + underlying.keySet.groupMapReduce(key)(f)(reduce) + + @deprecated( + "Check .knownSize instead of .hasDefiniteSize for more actionable information (see scaladoc for details)", + "2.13.0", + ) + override def hasDefiniteSize: Boolean = underlying.hasDefiniteSize + + override def map[B](f: A => B): CC[B] = fromMap(underlying map adaptedTuple(f)) + + override def max[B >: A: Ordering]: A = underlying.keySet.max[B] + + override def maxBy[B: Ordering](f: A => B): A = underlying.keySet maxBy f + + override def min[B >: A: Ordering]: A = underlying.keySet.min[B] + + override def minBy[B: Ordering](f: A => B): A = underlying.keySet minBy f + + override def partition(p: A => Boolean): (C, C) = { + val (a, b) = underlying partition adapted(p) + (fromSpecificMap(a), fromSpecificMap(b)) + } + + override def partitionMap[A1, A2](f: A => Either[A1, A2]): (CC[A1], CC[A2]) = { + val (a, b) = underlying partitionMap adapted(f) + (iterableFactory.from(a), iterableFactory.from(b)) + } + + override def reduceLeft[B >: A](op: (B, A) => B): B = underlying.keySet reduceLeft op + + override def reduceLeftOption[B >: A](op: (B, A) => B): Option[B] = + underlying.keySet reduceLeftOption op + + override def reduceRight[B >: A](op: (A, B) => B): B = underlying.keySet reduceRight op + + override def reduceRightOption[B >: A](op: (A, B) => B): Option[B] = + underlying.keySet reduceRightOption op + + override def scanLeft[B](z: B)(op: (B, A) => B): CC[B] = + iterableFactory.from(underlying.scanLeft(z)((acc, t) => op(acc, t._1))) + + override def scanRight[B](z: B)(op: (A, B) => B): CC[B] = + iterableFactory.from(underlying.scanRight(z)((t, acc) => op(t._1, acc))) + + override def slice(from: Int, until: Int): C = fromSpecificMap(underlying.slice(from, until)) + + override def span(p: A => Boolean): (C, C) = { + val (a, b) = underlying span adapted(p) + (fromSpecificMap(a), fromSpecificMap(b)) + } + + override def splitAt(n: Int): (C, C) = { + val (a, b) = underlying splitAt n + (fromSpecificMap(a), fromSpecificMap(b)) + } + + override def stepper[S <: Stepper[_]](implicit shape: StepperShape[A, S]): S = + underlying.keyStepper + + override def take(n: Int): C = fromSpecificMap(underlying take n) + + override def takeRight(n: Int): C = fromSpecificMap(underlying takeRight n) + + override def takeWhile(p: A => Boolean): C = fromSpecificMap(underlying takeWhile adapted(p)) + + override def tapEach[U](f: A => U): C = fromSpecificMap(underlying tapEach adapted(f)) + + override def toArray[B >: A: ClassTag]: Array[B] = underlying.keySet.toArray[B] + + override def view: View[A] = underlying.keySet.view +} + +private object SetFromMapOps { + + // top type to make pattern matching easier + sealed trait WrappedMap[A] extends IterableOnce[A] { + protected[collection] val underlying: IterableOnce[(A, Unit)] + } + + trait DynamicClassName { + self: Iterable[_] => + protected[collection] val underlying: Iterable[_] + + override protected[this] def className: String = s"SetFrom_${underlying.collectionClassName}" + } + + // unknown whether mutable or immutable + trait Unknown[ + A, + +MM[K, V] <: MapOps[K, V, MM, _], + +M <: MapOps[A, Unit, MM, M], + +CC[_], + +C <: Unknown[A, MM, M, CC, C], + ] extends SetFromMapOps[A, MM, M, CC, C] { + def diff(that: Set[A]): C = + toIterable + .foldLeft(newSpecificBuilder)((b, elem) => if (that contains elem) b else b += elem) + .result() + } + + trait Unsorted[A, +MM[K, V] <: MapOps[K, V, MM, MM[K, V]], +CC[X] <: Unsorted[X, MM, CC]] + extends SetFromMapOps[A, MM, MM[A, Unit], CC, CC[A]] { + protected[this] final def fromSpecificMap(m: MM[A, Unit]): CC[A] = fromMap(m) + + override def concat(that: IterableOnce[A]): CC[A] = fromMap { + that match { + case coll: WrappedMap[A] => underlying concat coll.underlying + case coll => underlying concat coll.iterator.map((_, ())) + } + } + } + + trait Sorted[ + A, + +MM[K, V] <: Map[K, V] with SortedMapOps[K, V, MM, MM[K, V]], + +UnsortedCC[X] <: Set[X], + +CC[X] <: Sorted[X, MM, UnsortedCC, CC] with SortedSet[X] with SortedSetOps[X, CC, CC[X]], + ] extends SetFromMapOps[A, Map, MM[A, Unit], UnsortedCC, CC[A]] + with SortedSetOps[A, CC, CC[A]] { + override protected[collection] val underlying: MM[A, Unit] + + @inline protected[this] final implicit def implicitOrd: Ordering[A] = ordering + + protected[this] def fromSortedMap[B: Ordering](m: MM[B, Unit]): CC[B] + + protected[this] final def fromSpecificMap(m: MM[A, Unit]): CC[A] = fromSortedMap(m) + + def iteratorFrom(start: A): Iterator[A] = underlying.keysIteratorFrom(start) + + def rangeImpl(from: Option[A], until: Option[A]): CC[A] = + fromSortedMap(underlying.rangeImpl(from, until)) + + override def rangeTo(to: A): CC[A] = fromSortedMap(underlying rangeTo to) + + override def head: A = underlying.firstKey + + override def firstKey: A = underlying.firstKey + + override def headOption: Option[A] = underlying.headOption.map(_._1) + + override def last: A = underlying.lastKey + + override def lastKey: A = underlying.lastKey + + override def lastOption: Option[A] = underlying.lastOption.map(_._1) + + override def collect[B](pf: PartialFunction[A, B])(implicit + @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B] + ): CC[B] = + fromSortedMap(underlying collect adaptedTuplePF(pf)) + + override def concat(that: IterableOnce[A]): CC[A] = fromSortedMap { + that match { + case coll: WrappedMap[A] => underlying concat coll.underlying + case coll => underlying concat coll.iterator.map((_, ())) + } + } + + override def flatMap[B]( + f: A => IterableOnce[B] + )(implicit @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B]): CC[B] = + fromSortedMap { + underlying flatMap { case (elem, _) => + f(elem) match { + case that: WrappedMap[B] => that.underlying + case that => that.iterator map { _ -> () } + } + } + } + + override def map[B](f: A => B)(implicit + @implicitNotFound(SortedSetOps.ordMsg) ev: Ordering[B] + ): CC[B] = + fromSortedMap(underlying map adaptedTuple(f)) + + override def max[B >: A: Ordering]: A = super[SortedSetOps].max[B] + + override def maxBefore(key: A): Option[A] = underlying maxBefore key map { _._1 } + + override def min[B >: A: Ordering]: A = super[SortedSetOps].min + + override def minAfter(key: A): Option[A] = underlying minAfter key map { _._1 } + } + +} + +private abstract class SetFromMapFactory[+MM[K, V] <: Map[K, V], +CC[A] <: Set[A]]( + mf: MapFactory[MM] +) extends IterableFactory[CC] + with Serializable { + protected[this] def fromMap[A](map: MM[A, Unit]): CC[A] + + def from[A](source: IterableOnce[A]): CC[A] = + source match { + case coll: WrappedMap[A] => fromMap(mf from coll.underlying) + case coll => newBuilder[A].addAll(coll).result() + } + + def empty[A]: CC[A] = fromMap(mf.empty) + + def newBuilder[A]: mutable.Builder[A, CC[A]] = new WrappedBuilder(mf.newBuilder) + + private final class WrappedBuilder[A](b: mutable.Builder[(A, Unit), MM[A, Unit]]) + extends mutable.Builder[A, CC[A]] { + def clear(): Unit = b.clear() + + def result(): CC[A] = fromMap(b.result()) + + def addOne(elem: A): this.type = { b.addOne((elem, ())); this } + + override def addAll(xs: IterableOnce[A]): this.type = + xs match { + case coll: WrappedMap[A] => + b.addAll(coll.underlying) + this + case coll => super.addAll(coll) + } + + override def sizeHint(size: Int): Unit = b.sizeHint(size) + } + +} + +private abstract class SortedSetFromMapFactory[+MM[K, V] <: SortedMap[K, V], +CC[A] <: Set[A]]( + mf: SortedMapFactory[MM] +) extends SortedIterableFactory[CC] + with Serializable { + protected[this] def fromMap[A](map: MM[A, Unit]): CC[A] + + def from[A: Ordering](it: IterableOnce[A]): CC[A] = + it match { + case coll: WrappedMap[A] => fromMap(mf from coll.underlying) + case coll => newBuilder[A].addAll(coll).result() + } + + def empty[A: Ordering]: CC[A] = fromMap(mf.empty) + + def newBuilder[A: Ordering]: mutable.Builder[A, CC[A]] = new WrapperBuilder[A](mf.newBuilder) + + private final class WrapperBuilder[A: Ordering](b: mutable.Builder[(A, Unit), MM[A, Unit]]) + extends mutable.Builder[A, CC[A]] { + def clear(): Unit = b.clear() + + def result(): CC[A] = fromMap(b.result()) + + def addOne(elem: A): this.type = { b.addOne((elem, ())); this } + + override def addAll(xs: IterableOnce[A]): this.type = + xs match { + case coll: WrappedMap[A] => + b.addAll(coll.underlying) + this + case coll => super.addAll(coll) + } + + override def sizeHint(size: Int): Unit = b.sizeHint(size) + } + +} + +private sealed abstract class SetFromMapMetaFactoryBase[MM[K, V] <: Map[K, V], +CC[A] <: Set[A]] { + def apply[A](map: MM[A, Unit]): CC[A] +} + +private abstract class SetFromMapMetaFactory[MM[K, V] <: Map[K, V], +CC[A] <: Set[A]] + extends SetFromMapMetaFactoryBase[MM, CC] { + def apply(factory: MapFactory[MM]): IterableFactory[CC] +} + +private abstract class SortedSetFromMapMetaFactory[MM[K, V] <: SortedMap[K, V], +CC[A] <: SortedSet[ + A +]] extends SetFromMapMetaFactoryBase[MM, CC] { + def apply(factory: SortedMapFactory[MM]): SortedIterableFactory[CC] +} diff --git a/src/main/scala/scala/collection/concurrent/Set.scala b/src/main/scala/scala/collection/concurrent/Set.scala new file mode 100644 index 0000000..73faaa1 --- /dev/null +++ b/src/main/scala/scala/collection/concurrent/Set.scala @@ -0,0 +1,37 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala +package collection +package concurrent + +/** + * A template trait for mutable sets that allow concurrent access. + * + * $concurrentsetinfo + * + * @tparam A the value type of the set + * @define Coll `concurrent.Set` + * @define coll concurrent set + * @define concurrentsetinfo + * This is a base trait for all Scala concurrent set implementations. It + * provides all of the methods a `Set` does, with the difference that all the + * changes are atomic. + * @note The concurrent set do not accept `null` for values. + */ +trait Set[A] extends scala.collection.mutable.Set[A] + +object Set extends IterableFactory.Delegate[Set](SetFromMap(TrieMap)) { + def fromMap(factory: MapFactory[Map]): IterableFactory[Set] = SetFromMap(factory) + + def fromMap[A](map: Map[A, Unit]): Set[A] = SetFromMap(map) +} diff --git a/src/main/scala/scala/collection/concurrent/SetFromMap.scala b/src/main/scala/scala/collection/concurrent/SetFromMap.scala new file mode 100644 index 0000000..bc602aa --- /dev/null +++ b/src/main/scala/scala/collection/concurrent/SetFromMap.scala @@ -0,0 +1,56 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala +package collection +package concurrent + +import scala.collection.generic.DefaultSerializable +import scala.collection.{mutable => m} + +@SerialVersionUID(3L) +private[collection] class SetFromMap[A](override protected[collection] val underlying: Map[A, Unit]) + extends mutable.SetFromMap[A](underlying) + with Set[A] + with mutable.SetFromMapOps[A, m.Map, m.Map[A, Unit], m.SetFromMap, m.SetFromMap[A]] + with IterableFactoryDefaults[A, m.SetFromMap] + with DefaultSerializable { + override protected[this] def fromMap[B](m: mutable.Map[B, Unit]): mutable.SetFromMap[B] = + SetFromMap.fromMutableMap(m) + + override def iterableFactory: IterableFactory[m.SetFromMap] = + new SetFromMap.MutableFactory(underlying.mapFactory) +} + +private[collection] object SetFromMap extends SetFromMapMetaFactory[Map, Set] { + def apply(factory: MapFactory[Map]): IterableFactory[Set] = new WrapperFactory(factory) + + def apply[A](map: Map[A, Unit]): Set[A] = new SetFromMap(map) + + @inline private def fromMutableMap[A](map: m.Map[A, Unit]): m.SetFromMap[A] = + map match { + case conc: Map[A, Unit] => new SetFromMap(conc) + case mut => new m.SetFromMap(mut) + } + + @SerialVersionUID(3L) + private class WrapperFactory(mf: MapFactory[Map]) extends SetFromMapFactory[Map, SetFromMap](mf) { + protected[this] def fromMap[A](map: Map[A, Unit]): SetFromMap[A] = new SetFromMap(map) + } + + @SerialVersionUID(3L) + private class MutableFactory(mf: MapFactory[m.Map]) + extends SetFromMapFactory[m.Map, m.SetFromMap](mf) { + protected[this] def fromMap[A](map: m.Map[A, Unit]): m.SetFromMap[A] = fromMutableMap(map) + } + +} diff --git a/src/main/scala/scala/collection/immutable/SeqSet.scala b/src/main/scala/scala/collection/immutable/SeqSet.scala new file mode 100644 index 0000000..e09f40b --- /dev/null +++ b/src/main/scala/scala/collection/immutable/SeqSet.scala @@ -0,0 +1,40 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala +package collection +package immutable + +/** + * A generic trait for ordered immutable sets. Concrete classes have to provide + * functionality for the abstract methods in `SeqSet`. + * + * Note that when checking for equality [[SeqSet]] does not take into account + * ordering. + * + * @tparam A the type of the values contained in this linked set. + * @define coll immutable seq set + * @define Coll `immutable.SeqSet` + */ +trait SeqSet[A] + extends Set[A] + with collection.SeqSet[A] + with SetOps[A, SeqSet, SeqSet[A]] + with IterableFactoryDefaults[A, SeqSet] { + override def iterableFactory: IterableFactory[SeqSet] = SeqSet +} + +object SeqSet extends IterableFactory.Delegate[SeqSet](SeqSetFromMap(SeqMap)) { + def fromMap(factory: MapFactory[SeqMap]): IterableFactory[SeqSet] = SeqSetFromMap(factory) + + def fromMap[A](map: SeqMap[A, Unit]): SeqSet[A] = SeqSetFromMap(map) +} diff --git a/src/main/scala/scala/collection/immutable/SetFromMap.scala b/src/main/scala/scala/collection/immutable/SetFromMap.scala new file mode 100644 index 0000000..9c6c9df --- /dev/null +++ b/src/main/scala/scala/collection/immutable/SetFromMap.scala @@ -0,0 +1,153 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala +package collection +package immutable + +import scala.collection.generic.DefaultSerializable + +private[collection] trait SetFromMapOps[ + A, + +MM[K, +V] <: MapOps[K, V, MM, _], + +M <: MapOps[A, Unit, MM, M], + +CC[_], + +C <: SetFromMapOps[A, MM, M, CC, C], +] extends SetOps[A, CC, C] + with collection.SetFromMapOps[A, MM, M, CC, C] { + def excl(elem: A): C = fromSpecificMap(underlying removed elem) + + override def removedAll(that: IterableOnce[A]): C = fromSpecificMap(underlying removedAll that) +} + +private[collection] object SetFromMapOps { + + trait Unsorted[ + A, + +MM[K, +V] <: MapOps[K, V, MM, MM[K, V]], + +CC[X] <: Unsorted[X, MM, CC], + ] extends SetFromMapOps[A, MM, MM[A, Unit], CC, CC[A]] + with collection.SetFromMapOps.Unsorted[A, MM, CC] { + def incl(elem: A): CC[A] = fromMap(underlying.updated(elem, ())) + } + +} + +@SerialVersionUID(3L) +private[collection] class SetFromMap[A](protected[collection] val underlying: Map[A, Unit]) + extends AbstractSet[A] + with SetFromMapOps.Unsorted[A, Map, SetFromMap] + with collection.SetFromMapOps.DynamicClassName + with IterableFactoryDefaults[A, SetFromMap] + with DefaultSerializable { + protected[this] def fromMap[B](m: Map[B, Unit]): SetFromMap[B] = new SetFromMap(m) + + override def iterableFactory: IterableFactory[SetFromMap] = + new SetFromMap.WrapperFactory(underlying.mapFactory) +} + +private[collection] object SetFromMap extends SetFromMapMetaFactory[Map, Set] { + def apply(factory: MapFactory[Map]): IterableFactory[Set] = new DynamicFactory(factory) + + def apply[A](map: Map[A, Unit]): Set[A] = map match { + case map: SeqMap[A, Unit] => SeqSetFromMap(map) + case map: SortedMap[A, Unit] => SortedSetFromMap(map) + case map => apply(map) + } + + @SerialVersionUID(3L) + private class WrapperFactory(mf: MapFactory[Map]) extends SetFromMapFactory[Map, SetFromMap](mf) { + protected[this] def fromMap[A](map: Map[A, Unit]): SetFromMap[A] = new SetFromMap(map) + } + + @SerialVersionUID(3L) + private class DynamicFactory(mf: MapFactory[Map]) extends SetFromMapFactory[Map, Set](mf) { + protected[this] def fromMap[A](map: Map[A, Unit]): Set[A] = SetFromMap(map) + } + +} + +@SerialVersionUID(3L) +private[collection] class SeqSetFromMap[A](protected[collection] val underlying: SeqMap[A, Unit]) + extends AbstractSet[A] + with SetFromMapOps.Unsorted[A, SeqMap, SeqSetFromMap] + with collection.SetFromMapOps.DynamicClassName + with SeqSet[A] + with IterableFactoryDefaults[A, SeqSetFromMap] + with DefaultSerializable { + protected[this] def fromMap[B](m: SeqMap[B, Unit]): SeqSetFromMap[B] = + new SeqSetFromMap(m) + + override def iterableFactory: IterableFactory[SeqSetFromMap] = + new SeqSetFromMap.WrapperFactory(underlying.mapFactory) +} + +private[collection] object SeqSetFromMap extends SetFromMapMetaFactory[SeqMap, SeqSet] { + def apply(factory: MapFactory[SeqMap]): IterableFactory[SeqSet] = new WrapperFactory(factory) + + def apply[A](map: SeqMap[A, Unit]): SeqSet[A] = new SeqSetFromMap(map) + + @SerialVersionUID(3L) + private class WrapperFactory(mf: MapFactory[SeqMap]) + extends SetFromMapFactory[SeqMap, SeqSetFromMap](mf) { + protected[this] def fromMap[A](map: SeqMap[A, Unit]): SeqSetFromMap[A] = new SeqSetFromMap(map) + } + +} + +@SerialVersionUID(3L) +private[collection] class SortedSetFromMap[A]( + protected[collection] val underlying: SortedMap[A, Unit] +)(implicit val ordering: Ordering[A]) + extends AbstractSet[A] + with SetFromMapOps[A, Map, SortedMap[A, Unit], Set, SortedSetFromMap[A]] + with collection.SetFromMapOps.Sorted[A, SortedMap, Set, SortedSetFromMap] + with collection.SetFromMapOps.DynamicClassName + with SortedSet[A] + with SortedSetOps[A, SortedSetFromMap, SortedSetFromMap[A]] + with IterableFactoryDefaults[A, Set] + with SortedSetFactoryDefaults[A, SortedSetFromMap, Set] + with DefaultSerializable { + + import SortedSetFromMap.ssfm + + protected[this] def fromMap[B](m: Map[B, Unit]): Set[B] = new SetFromMap(m) + + protected[this] def fromSortedMap[B: Ordering](m: SortedMap[B, Unit]): SortedSetFromMap[B] = + new SortedSetFromMap(m) + + override def iterableFactory: IterableFactory[Set] = SetFromMap(underlying.mapFactory) + + override def sortedIterableFactory: SortedIterableFactory[SortedSetFromMap] = + new SortedSetFromMap.WrapperFactory(underlying.sortedMapFactory) + + override def incl(elem: A): SortedSetFromMap[A] = ssfm(underlying.updated(elem, ())) +} + +private[collection] object SortedSetFromMap + extends SortedSetFromMapMetaFactory[SortedMap, SortedSet] { + @inline private def ssfm[A: Ordering](map: SortedMap[A, Unit]): SortedSetFromMap[A] = + new SortedSetFromMap(map) + + def apply(factory: SortedMapFactory[SortedMap]): SortedIterableFactory[SortedSet] = + new WrapperFactory(factory) + + def apply[A](map: SortedMap[A, Unit]): SortedSet[A] = ssfm(map)(map.ordering) + + @SerialVersionUID(3L) + private final class WrapperFactory(mf: SortedMapFactory[SortedMap]) + extends SortedSetFromMapFactory[SortedMap, SortedSetFromMap](mf) { + protected[this] def fromMap[A](map: SortedMap[A, Unit]): SortedSetFromMap[A] = + ssfm(map)(map.ordering) + } + +} diff --git a/src/main/scala/scala/collection/immutable/next/package.scala b/src/main/scala/scala/collection/immutable/next/package.scala new file mode 100644 index 0000000..292e30f --- /dev/null +++ b/src/main/scala/scala/collection/immutable/next/package.scala @@ -0,0 +1,34 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala +package collection +package immutable + +import scala.annotation.unused + +package object next { + implicit final class NextSCISetCompanionExtensions(@unused private val self: Set.type) + extends AnyVal { + def fromMap(factory: MapFactory[Map]): IterableFactory[Set] = SetFromMap(factory) + + def fromMap[A](map: Map[A, Unit]): Set[A] = SetFromMap(map) + } + + implicit final class NextSCISortedSetCompanionExtensions(@unused private val self: SortedSet.type) + extends AnyVal { + def fromMap(factory: SortedMapFactory[SortedMap]): SortedIterableFactory[SortedSet] = + SortedSetFromMap(factory) + + def fromMap[A](map: SortedMap[A, Unit]): SortedSet[A] = SortedSetFromMap(map) + } +} diff --git a/src/main/scala/scala/collection/mutable/SeqSet.scala b/src/main/scala/scala/collection/mutable/SeqSet.scala new file mode 100644 index 0000000..9ec1279 --- /dev/null +++ b/src/main/scala/scala/collection/mutable/SeqSet.scala @@ -0,0 +1,41 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala +package collection +package mutable + +/** + * A generic trait for ordered mutable sets. Concrete classes have to provide + * functionality for the abstract methods in `SeqSet`. + * + * Note that when checking for equality [[SeqSet]] does not take into account + * ordering. + * + * @tparam A the type of the values contained in this linked set. + * @define coll mutable seq set + * @define Coll `mutable.SeqSet` + */ +trait SeqSet[A] + extends Set[A] + with collection.SeqSet[A] + with SetOps[A, SeqSet, SeqSet[A]] + with IterableFactoryDefaults[A, SeqSet] { + override def iterableFactory: IterableFactory[SeqSet] = SeqSet +} + +object SeqSet extends IterableFactory.Delegate[SeqSet](SeqSetFromMap(SeqMap)) { + // TODO: migrate? + def fromMap(factory: MapFactory[SeqMap]): IterableFactory[SeqSet] = SeqSetFromMap(factory) + + def fromMap[A](map: SeqMap[A, Unit]): SeqSet[A] = SeqSetFromMap(map) +} diff --git a/src/main/scala/scala/collection/mutable/SetFromMap.scala b/src/main/scala/scala/collection/mutable/SetFromMap.scala new file mode 100644 index 0000000..a2ef4eb --- /dev/null +++ b/src/main/scala/scala/collection/mutable/SetFromMap.scala @@ -0,0 +1,163 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala +package collection +package mutable + +import scala.collection.SetFromMapOps.WrappedMap +import scala.collection.generic.DefaultSerializable + +// Implementation note: The `concurrent.Set` implementation +// inherits from this, so we have to be careful about +// making changes that do more than forward to the +// underlying `Map`. If we have a method implementation +// that is not atomic, we MUST override that method in +// `concurrent.SetFromMap`. +private[collection] trait SetFromMapOps[ + A, + +MM[K, V] <: MapOps[K, V, MM, _], + +M <: MapOps[A, Unit, MM, M], + +CC[_], + +C <: SetFromMapOps[A, MM, M, CC, C], +] extends SetOps[A, CC, C] + with collection.SetFromMapOps[A, MM, M, CC, C] { + def clear(): Unit = underlying.clear() + + def addOne(elem: A): this.type = { underlying.update(elem, ()); this } + + override def add(elem: A): Boolean = underlying.put(elem, ()).isEmpty + + override def addAll(xs: IterableOnce[A]): this.type = + xs match { + case coll: WrappedMap[A] => + underlying.addAll(coll.underlying) + this + case coll => super.addAll(coll) + } + + def subtractOne(elem: A): this.type = { underlying.subtractOne(elem); this } + + override def remove(elem: A): Boolean = underlying.remove(elem).isDefined + + override def subtractAll(xs: IterableOnce[A]): this.type = { underlying.subtractAll(xs); this } + + // We need to define this explicitly because there's a multiple inheritance diamond + override def knownSize: Int = super[SetFromMapOps].knownSize +} + +@SerialVersionUID(3L) +private[collection] class SetFromMap[A](protected[collection] val underlying: Map[A, Unit]) + extends AbstractSet[A] + with SetFromMapOps[A, Map, Map[A, Unit], SetFromMap, SetFromMap[A]] + with SetFromMapOps.Unsorted[A, Map, SetFromMap] + with SetFromMapOps.DynamicClassName + with IterableFactoryDefaults[A, SetFromMap] + with DefaultSerializable { + protected[this] def fromMap[B](m: Map[B, Unit]): SetFromMap[B] = new SetFromMap(m) + + override def iterableFactory: IterableFactory[SetFromMap] = + new SetFromMap.WrapperFactory(underlying.mapFactory) +} + +private[collection] object SetFromMap extends SetFromMapMetaFactory[Map, Set] { + def apply(factory: MapFactory[Map]): IterableFactory[Set] = new DynamicFactory(factory) + + def apply[A](map: Map[A, Unit]): Set[A] = map match { + case map: concurrent.Map[A, Unit] => concurrent.SetFromMap(map) + case map: SeqMap[A, Unit] => SeqSetFromMap(map) + case map: SortedMap[A, Unit] => SortedSetFromMap(map) + case map => new SetFromMap(map) + } + + @SerialVersionUID(3L) + private class WrapperFactory(mf: MapFactory[Map]) extends SetFromMapFactory[Map, SetFromMap](mf) { + protected[this] def fromMap[A](map: Map[A, Unit]): SetFromMap[A] = new SetFromMap(map) + } + + @SerialVersionUID(3L) + private class DynamicFactory(mf: MapFactory[Map]) extends SetFromMapFactory[Map, Set](mf) { + protected[this] def fromMap[A](map: Map[A, Unit]): Set[A] = SetFromMap(map) + } + +} + +@SerialVersionUID(3L) +private[collection] class SeqSetFromMap[A](protected[collection] val underlying: SeqMap[A, Unit]) + extends AbstractSet[A] + with SetFromMapOps[A, SeqMap, SeqMap[A, Unit], SeqSetFromMap, SeqSetFromMap[A]] + with SetFromMapOps.Unsorted[A, SeqMap, SeqSetFromMap] + with SetFromMapOps.DynamicClassName + with SeqSet[A] + with IterableFactoryDefaults[A, SeqSetFromMap] + with DefaultSerializable { + protected[this] def fromMap[B](m: SeqMap[B, Unit]): SeqSetFromMap[B] = new SeqSetFromMap(m) + + override def iterableFactory: IterableFactory[SeqSetFromMap] = + new SeqSetFromMap.WrapperFactory(underlying.mapFactory) +} + +private[collection] object SeqSetFromMap extends SetFromMapMetaFactory[SeqMap, SeqSet] { + def apply(factory: MapFactory[SeqMap]): IterableFactory[SeqSet] = + new WrapperFactory(factory) + + def apply[A](map: SeqMap[A, Unit]): mutable.SeqSet[A] = new SeqSetFromMap(map) + + @SerialVersionUID(3L) + private class WrapperFactory(mf: MapFactory[SeqMap]) + extends SetFromMapFactory[SeqMap, SeqSetFromMap](mf) { + protected[this] def fromMap[A](map: SeqMap[A, Unit]): SeqSetFromMap[A] = new SeqSetFromMap(map) + } + +} + +@SerialVersionUID(3L) +private[collection] class SortedSetFromMap[A]( + protected[collection] val underlying: SortedMap[A, Unit] +)(implicit val ordering: Ordering[A]) + extends AbstractSet[A] + with SetFromMapOps[A, Map, SortedMap[A, Unit], Set, SortedSetFromMap[A]] + with SetFromMapOps.Sorted[A, SortedMap, Set, SortedSetFromMap] + with SetFromMapOps.DynamicClassName + with SortedSet[A] + with SortedSetOps[A, SortedSetFromMap, SortedSetFromMap[A]] + with IterableFactoryDefaults[A, Set] + with SortedSetFactoryDefaults[A, SortedSetFromMap, Set] + with DefaultSerializable { + protected[this] def fromMap[B](m: Map[B, Unit]): SetFromMap[B] = new SetFromMap(m) + + protected[this] def fromSortedMap[B: Ordering](m: SortedMap[B, Unit]): SortedSetFromMap[B] = + new SortedSetFromMap(m) + + override def iterableFactory: IterableFactory[Set] = SetFromMap(underlying.mapFactory) + + override def sortedIterableFactory: SortedIterableFactory[SortedSetFromMap] = + new SortedSetFromMap.WrapperFactory(underlying.sortedMapFactory) +} + +private[collection] object SortedSetFromMap + extends SortedSetFromMapMetaFactory[SortedMap, SortedSet] { + def apply(factory: SortedMapFactory[SortedMap]): SortedIterableFactory[SortedSet] = + new WrapperFactory(factory) + + def apply[A](map: SortedMap[A, Unit]): mutable.SortedSet[A] = new SortedSetFromMap(map)( + map.ordering + ) + + @SerialVersionUID(3L) + private final class WrapperFactory(mf: SortedMapFactory[SortedMap]) + extends SortedSetFromMapFactory[SortedMap, SortedSetFromMap](mf) { + protected[this] def fromMap[A](map: SortedMap[A, Unit]): SortedSetFromMap[A] = + new SortedSetFromMap(map)(map.ordering) + } + +} diff --git a/src/main/scala/scala/collection/mutable/next/package.scala b/src/main/scala/scala/collection/mutable/next/package.scala new file mode 100644 index 0000000..4c87d5c --- /dev/null +++ b/src/main/scala/scala/collection/mutable/next/package.scala @@ -0,0 +1,34 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala +package collection +package mutable + +import scala.annotation.unused + +package object next { + implicit final class NextSCMSetCompanionExtensions(@unused private val self: Set.type) + extends AnyVal { + def fromMap(factory: MapFactory[Map]): IterableFactory[Set] = SetFromMap(factory) + + def fromMap[A](map: Map[A, Unit]): Set[A] = SetFromMap(map) + } + + implicit final class NextSCMSortedSetCompanionExtensions(@unused private val self: SortedSet.type) + extends AnyVal { + def fromMap(factory: SortedMapFactory[SortedMap]): SortedIterableFactory[SortedSet] = + SortedSetFromMap(factory) + + def fromMap[A](map: SortedMap[A, Unit]): SortedSet[A] = SortedSetFromMap(map) + } +} diff --git a/src/main/scala/scala/collection/next/package.scala b/src/main/scala/scala/collection/next/package.scala new file mode 100644 index 0000000..6a32f1f --- /dev/null +++ b/src/main/scala/scala/collection/next/package.scala @@ -0,0 +1,33 @@ +/* + * Scala (https://www.scala-lang.org) + * + * Copyright EPFL and Lightbend, Inc. + * + * Licensed under Apache License 2.0 + * (http://www.apache.org/licenses/LICENSE-2.0). + * + * See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + */ + +package scala +package collection + +import scala.annotation.unused + +package object next { + implicit final class NextSCSetCompanionExtensions(@unused private val self: Set.type) + extends AnyVal { + def fromMap(factory: MapFactory[Map]): IterableFactory[Set] = SetFromMap(factory) + + def fromMap[A](map: Map[A, Unit]): Set[A] = SetFromMap(map) + } + + implicit final class NextSCSortedSetCompanionExtensions(@unused private val self: SortedSet.type) + extends AnyVal { + def fromMap(factory: SortedMapFactory[SortedMap]): SortedIterableFactory[SortedSet] = + SortedSetFromMap(factory) + + def fromMap[A](map: SortedMap[A, Unit]): SortedSet[A] = SortedSetFromMap(map) + } +}