-
Notifications
You must be signed in to change notification settings - Fork 604
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Chunk support for ArraySeq #1905
Changes from 4 commits
3c525df
3afd549
3e9195c
357b07d
9743240
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package fs2 | ||
|
||
import scala.collection.mutable.WrappedArray | ||
|
||
trait ChunkPlatform[+O] { self: Chunk[O] => } | ||
|
||
trait ChunkCompanionPlatform { self: Chunk.type => | ||
|
||
protected def platformIterable[O](i: Iterable[O]): Option[Chunk[O]] = | ||
i match { | ||
case a: WrappedArray[O] => Some(wrappedArray(a)) | ||
case _ => None | ||
} | ||
|
||
/** | ||
* Creates a chunk backed by a `WrappedArray` | ||
*/ | ||
def wrappedArray[O](wrappedArray: WrappedArray[O]): Chunk[O] = | ||
array(wrappedArray.array.asInstanceOf[Array[O]]) | ||
|
||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
package fs2 | ||
|
||
import scala.collection.immutable.ArraySeq | ||
import scala.collection.immutable | ||
import scala.reflect.ClassTag | ||
|
||
trait ChunkPlatform[+O] { self: Chunk[O] => | ||
|
||
def toArraySeq[O2 >: O: ClassTag]: ArraySeq[O2] = { | ||
val array: Array[O2] = new Array[O2](size) | ||
copyToArray(array) | ||
ArraySeq.unsafeWrapArray[O2](array) | ||
Comment on lines
+11
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to be the most efficient way to construct an |
||
} | ||
|
||
def toArraySeqUntagged: ArraySeq[O] = | ||
self match { | ||
case knownType: Chunk.KnownElementType[O] => toArraySeq[O](knownType.elementClassTag) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We attempt to specialise the |
||
case _ => | ||
val buf = ArraySeq.untagged.newBuilder[O] | ||
buf.sizeHint(size) | ||
var i = 0 | ||
while (i < size) { | ||
buf += apply(i) | ||
i += 1 | ||
} | ||
buf.result() | ||
} | ||
|
||
} | ||
|
||
trait ChunkCompanionPlatform { self: Chunk.type => | ||
|
||
protected def platformIterable[O](i: Iterable[O]): Option[Chunk[O]] = | ||
i match { | ||
case a: immutable.ArraySeq[O] => Some(arraySeq(a)) | ||
case _ => None | ||
} | ||
|
||
/** | ||
* Creates a chunk backed by an immutable `ArraySeq`. | ||
*/ | ||
def arraySeq[O](arraySeq: immutable.ArraySeq[O]): Chunk[O] = | ||
array(arraySeq.unsafeArray.asInstanceOf[Array[O]]) | ||
|
||
} |
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
package fs2 | ||
|
||
import org.scalatest.prop.{CommonGenerators, Generator} | ||
|
||
import scala.collection.immutable.ArraySeq | ||
import scala.collection.{immutable, mutable} | ||
import scala.reflect.ClassTag | ||
|
||
class ChunkPlatformSpec extends Fs2Spec { | ||
|
||
private implicit val genUnit: Generator[Unit] = CommonGenerators.specificValue(()) | ||
private implicit def genArraySeq[A: Generator: ClassTag]: Generator[ArraySeq[A]] = | ||
Generator.vectorGenerator[A].map(ArraySeq.from) | ||
private implicit def genMutableArraySeq[A: Generator: ClassTag]: Generator[mutable.ArraySeq[A]] = | ||
implicitly[Generator[ArraySeq[A]]].map(_.to(mutable.ArraySeq)) | ||
|
||
private def testChunkToArraySeq[A]( | ||
testName: String, | ||
shouldSpecialise: Boolean, | ||
f: Chunk[A] => ArraySeq[A] | ||
)(implicit generator: Generator[Chunk[A]]): Unit = | ||
s"Chunk toArraySeq $testName" - { | ||
"values" in forAll { chunk: Chunk[A] => | ||
assert(f(chunk).toVector == chunk.toVector) | ||
} | ||
|
||
if (shouldSpecialise) | ||
"specialised" in forAll { chunk: Chunk[A] => | ||
f(chunk) match { | ||
case _: ArraySeq.ofRef[A] => | ||
fail("Expected specialised ArraySeq but was not specialised") | ||
case _ => succeed | ||
} | ||
} | ||
} | ||
|
||
private def testChunkToArraySeqTagged[A: ClassTag](testName: String, shouldSpecialise: Boolean)( | ||
implicit generator: Generator[Chunk[A]] | ||
): Unit = | ||
testChunkToArraySeq[A](testName, shouldSpecialise, f = _.toArraySeq[A]) | ||
|
||
private def testChunkToArraySeqUntagged[A]( | ||
testName: String | ||
)(implicit generator: Generator[Chunk[A]]): Unit = | ||
testChunkToArraySeq[A](testName, shouldSpecialise = false, f = _.toArraySeqUntagged) | ||
|
||
testChunkToArraySeqTagged[Int]("Int tagged", shouldSpecialise = true) | ||
testChunkToArraySeqTagged[Double]("Double tagged", shouldSpecialise = true) | ||
testChunkToArraySeqTagged[Long]("Long tagged", shouldSpecialise = true) | ||
testChunkToArraySeqTagged[Float]("Float tagged", shouldSpecialise = true) | ||
testChunkToArraySeqTagged[Char]("Char tagged", shouldSpecialise = true) | ||
testChunkToArraySeqTagged[Byte]("Byte tagged", shouldSpecialise = true) | ||
testChunkToArraySeqTagged[Short]("Short tagged", shouldSpecialise = true) | ||
testChunkToArraySeqTagged[Boolean]("Boolean tagged", shouldSpecialise = true) | ||
testChunkToArraySeqTagged[String]("String tagged", shouldSpecialise = false) | ||
testChunkToArraySeqTagged[Unit]("Unit tagged", shouldSpecialise = false) | ||
|
||
testChunkToArraySeqUntagged[Int]("Int untagged") | ||
testChunkToArraySeqUntagged[Double]("Double untagged") | ||
testChunkToArraySeqUntagged[Long]("Long untagged") | ||
testChunkToArraySeqUntagged[Float]("Float untagged") | ||
testChunkToArraySeqUntagged[Char]("Char untagged") | ||
testChunkToArraySeqUntagged[Byte]("Byte untagged") | ||
testChunkToArraySeqUntagged[Short]("Short untagged") | ||
testChunkToArraySeqUntagged[Boolean]("Boolean untagged") | ||
testChunkToArraySeqUntagged[Unit]("Unit untagged") | ||
testChunkToArraySeqUntagged[String]("String untagged") | ||
|
||
private def testChunkFromArraySeq[A: ClassTag: Generator]: Unit = { | ||
val testTypeName: String = implicitly[ClassTag[A]].runtimeClass.getSimpleName | ||
|
||
s"fromArraySeq ArraySeq[$testTypeName]" - { | ||
"mutable" in forAll { arraySeq: mutable.ArraySeq[A] => | ||
assert(Chunk.arraySeq(arraySeq).toVector == arraySeq.toVector) | ||
} | ||
|
||
"immutable" in forAll { arraySeq: immutable.ArraySeq[A] => | ||
assert(Chunk.arraySeq(arraySeq).toVector == arraySeq.toVector) | ||
} | ||
} | ||
} | ||
|
||
"Chunk from ArraySeq" - { | ||
testChunkFromArraySeq[Int] | ||
testChunkFromArraySeq[Double] | ||
testChunkFromArraySeq[Long] | ||
testChunkFromArraySeq[Float] | ||
testChunkFromArraySeq[Char] | ||
testChunkFromArraySeq[Byte] | ||
testChunkFromArraySeq[Short] | ||
testChunkFromArraySeq[Boolean] | ||
testChunkFromArraySeq[Unit] | ||
testChunkFromArraySeq[String] | ||
} | ||
|
||
"Chunk iterable" - { | ||
"mutable ArraySeq" in forAll { a: mutable.ArraySeq[String] => | ||
assert(Chunk.iterable(a).toVector == a.toVector) | ||
} | ||
|
||
"immutable ArraySeq" in forAll { a: immutable.ArraySeq[String] => | ||
assert(Chunk.iterable(a).toVector == a.toVector) | ||
} | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you make this trait and it’s companion
private[fs2]
both here and in 2.13 file? Otherwise looks ready for merge. Thanks!