Skip to content
17 changes: 2 additions & 15 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import com.typesafe.tools.mima.core._
import sbtcrossproject.CrossPlugin.autoImport.{crossProject, CrossType}
import Dependencies._

addCommandAlias("fmt", "; scalafmtAll; scalafmtSbt")
addCommandAlias("fmtCheck", "; scalafmtCheckAll; scalafmtSbtCheck")

Expand Down Expand Up @@ -140,29 +139,17 @@ lazy val core = crossProject(JSPlatform, JVMPlatform)
*/
if (tlIsScala3.value)
List(
ProblemFilters.exclude[DirectMissingMethodProblem]("cats.parse.Parser#Impl.mergeCharIn"),
ProblemFilters.exclude[DirectMissingMethodProblem]("cats.parse.Parser#Impl.mergeStrIn"),
ProblemFilters.exclude[DirectMissingMethodProblem]("cats.parse.RadixNode.children"),
ProblemFilters.exclude[DirectMissingMethodProblem]("cats.parse.RadixNode.fsts"),
ProblemFilters.exclude[DirectMissingMethodProblem]("cats.parse.RadixNode.prefixes"),
ProblemFilters.exclude[DirectMissingMethodProblem]("cats.parse.RadixNode.word"),
ProblemFilters.exclude[FinalClassProblem]("cats.parse.RadixNode"),
ProblemFilters.exclude[IncompatibleMethTypeProblem]("cats.parse.Parser#State.error_="),
ProblemFilters.exclude[IncompatibleMethTypeProblem]("cats.parse.RadixNode.this"),
ProblemFilters
.exclude[IncompatibleResultTypeProblem]("cats.parse.Parser#Impl#StringIn.parseMut"),
ProblemFilters.exclude[IncompatibleResultTypeProblem]("cats.parse.Parser#Impl.stringIn"),
ProblemFilters.exclude[IncompatibleResultTypeProblem]("cats.parse.Parser#State.error")
)
else
List(
ProblemFilters.exclude[DirectMissingMethodProblem]("cats.parse.Parser#Impl.mergeCharIn"),
ProblemFilters.exclude[DirectMissingMethodProblem]("cats.parse.Parser#Impl.mergeStrIn"),
ProblemFilters
.exclude[IncompatibleResultTypeProblem]("cats.parse.Parser#Impl#StringIn.parseMut"),
ProblemFilters.exclude[IncompatibleResultTypeProblem]("cats.parse.Parser#Impl.stringIn")
)
}
else Nil
} ++ MimaExclusionRules.parserImpl ++ MimaExclusionRules.bitSetUtil
)
.jsSettings(
crossScalaVersions := (ThisBuild / crossScalaVersions).value.filterNot(_.startsWith("2.11")),
Expand Down
47 changes: 1 addition & 46 deletions core/js/src/main/scala/cats/parse/BitSet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,49 +21,4 @@

package cats.parse

import scala.collection.mutable.BitSet

object BitSetUtil {
type Tpe = BitSet

@inline final val isScalaJs = true
@inline final val isScalaJvm = false

@inline final def isSet(b: BitSet, idx: Int): Boolean =
(idx >= 0) && b(idx)

def bitSetFor(charArray: Array[Char]): BitSet = {
val min = charArray(0).toInt
val bs = new BitSet(charArray(charArray.length - 1).toInt + 1 - min)
var idx = 0
while (idx < charArray.length) {
bs += charArray(idx).toInt - min
idx += 1
}

bs
}

def isSingleton(t: Tpe): Boolean = t.size == 1

def union(bs: List[(Int, BitSet)]): Iterable[Char] =
union(bs.iterator)

// what are all the Chars in these bitsets
def union(bs: Iterator[(Int, BitSet)]): Iterable[Char] = {
def toIter(m: Int, bs: BitSet): Iterator[Char] =
bs.iterator.map { i => (i + m).toChar } ++ Iterator.single(m.toChar)

bs.flatMap { case (m, bs) => toIter(m, bs) }.toSet
}

def bitSetForRange(count: Int): BitSet = {
val bs = new BitSet(count)
var cur = 0
while (cur < count) {
bs += cur
cur += 1
}
bs
}
}
object BitSetUtil extends BitSetUtilCompat(true, false)
48 changes: 1 addition & 47 deletions core/jvm/src/main/scala/cats/parse/BitSet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -21,50 +21,4 @@

package cats.parse

import java.util.BitSet

object BitSetUtil {
type Tpe = BitSet

@inline final val isScalaJs = false
@inline final val isScalaJvm = true

@inline final def isSet(b: BitSet, idx: Int): Boolean =
// BitSet can't deal with negatives, so mask those out
b.get(idx & Int.MaxValue)

// we require a sorted, nonEmpty, charArray
def bitSetFor(charArray: Array[Char]): BitSet = {
val min = charArray(0).toInt
val bs = new BitSet(charArray(charArray.length - 1).toInt + 1 - min)
var idx = 0
while (idx < charArray.length) {
bs.set(charArray(idx).toInt - min)
idx += 1
}

bs
}

def isSingleton(t: Tpe): Boolean = t.cardinality() == 1

// what are all the Chars in these bitsets
def union(bs: List[(Int, BitSet)]): Iterable[Char] =
union(bs.iterator)

def union(bs: Iterator[(Int, BitSet)]): Iterable[Char] = {
def toIter(m: Int, bs: BitSet): Iterator[Char] =
Iterator
.iterate(0) { m => bs.nextSetBit(m + 1) }
.takeWhile(_ >= 0)
.map { i => (m + i).toChar }

bs.flatMap { case (m, bs) => toIter(m, bs) }.toSet
}

def bitSetForRange(count: Int): BitSet = {
val bs = new BitSet(count)
bs.flip(0, count)
bs
}
}
object BitSetUtil extends BitSetUtilCompat(false, true)
70 changes: 70 additions & 0 deletions core/shared/src/main/scala/cats/parse/BitSetCompat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2021 Typelevel
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package cats.parse

import java.util.BitSet
private[parse] abstract class BitSetUtilCompat(
// TODO: Remove isScalaJs/isScalaJvm in next minor version update. See https://github.com/typelevel/cats-parse/issues/391.
@inline final val isScalaJs: Boolean,
@inline final val isScalaJvm: Boolean
) {
type Tpe = BitSet

@inline final def isSet(b: BitSet, idx: Int): Boolean =
// BitSet can't deal with negatives, so mask those out
b.get(idx & Int.MaxValue)

// we require a sorted, nonEmpty, charArray
def bitSetFor(charArray: Array[Char]): BitSet = {
val min = charArray(0).toInt
val bs = new BitSet(charArray(charArray.length - 1).toInt + 1 - min)
var idx = 0
while (idx < charArray.length) {
bs.set(charArray(idx).toInt - min)
idx += 1
}

bs
}

def isSingleton(t: Tpe): Boolean = t.cardinality() == 1

// what are all the Chars in these bitsets
def union(bs: List[(Int, BitSet)]): Iterable[Char] =
union(bs.iterator)

def union(bs: Iterator[(Int, BitSet)]): Iterable[Char] = {
def toIter(m: Int, bs: BitSet): Iterator[Char] =
Iterator
.iterate(0) { m => bs.nextSetBit(m + 1) }
.takeWhile(_ >= 0)
.map { i => (m + i).toChar }

bs.flatMap { case (m, bs) => toIter(m, bs) }.toSet
}

def bitSetForRange(count: Int): BitSet = {
val bs = new BitSet(count)
bs.flip(0, count)
bs
}
}
1 change: 1 addition & 0 deletions core/shared/src/test/scala/cats/parse/BitSetTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ package cats.parse
import org.scalacheck.Prop.forAll

class BitSetTest extends munit.ScalaCheckSuite {
// TODO: Remove isScalaJs/isScalaJvm in next minor version update. See https://github.com/typelevel/cats-parse/issues/391.
test("isScalaJs/isScalaJvm is consistent") {
Comment thread
i10416 marked this conversation as resolved.
// This will need to be updated if we ever add scala-native
assert(!(BitSetUtil.isScalaJs && BitSetUtil.isScalaJvm))
Expand Down
29 changes: 29 additions & 0 deletions project/MimaExclusionRules.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import com.typesafe.tools.mima.core.ProblemFilters
import com.typesafe.tools.mima.core.IncompatibleMethTypeProblem
import com.typesafe.tools.mima.core.IncompatibleResultTypeProblem
import com.typesafe.tools.mima.core.DirectMissingMethodProblem
object MimaExclusionRules {
val parserImpl = Seq(
"cats.parse.Parser#Impl.mergeCharIn",
"cats.parse.Parser#Impl.mergeStrIn",
"cats.parse.Parser#Impl#CharIn.copy",
"cats.parse.Parser#Impl#CharIn.apply",
"cats.parse.Parser#Impl#CharIn.this"
).map(ProblemFilters.exclude[IncompatibleMethTypeProblem](_)) ++ Seq(
"cats.parse.Parser#Impl#StringIn.parseMut",
"cats.parse.Parser#Impl.stringIn",
"cats.parse.Parser#Impl#CharIn.copy$default$2",
"cats.parse.Parser#Impl#CharIn.bitSet",
"cats.parse.Parser#Impl#CharIn._2"
).map(ProblemFilters.exclude[IncompatibleResultTypeProblem](_)) ++ Seq(
"cats.parse.Parser#Impl.mergeCharIn",
"cats.parse.Parser#Impl.mergeStrIn"
).map(ProblemFilters.exclude[DirectMissingMethodProblem](_))
// TODO: Remove these rules in future release.
val bitSetUtil = Seq(
"cats.parse.BitSetUtil.isSingleton",
"cats.parse.BitSetUtil.isSet"
).map(ProblemFilters.exclude[IncompatibleMethTypeProblem](_)) ++ Seq(
"cats.parse.BitSetUtil.bitSetFor"
).map(ProblemFilters.exclude[IncompatibleResultTypeProblem](_))
}