All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scala.build.options.ShadowingSeq.scala Maven / Gradle / Ivy

There is a newer version: 1.5.1
Show newest version
package scala.build.options

import dependency.AnyDependency

import scala.collection.mutable

/** Seq ensuring some of its values are unique according to some key */
final case class ShadowingSeq[T] private (values: Seq[Seq[T]]) {
  lazy val toSeq: Seq[T] = values.flatten
  def map[U](f: T => U)(implicit key: ShadowingSeq.KeyOf[U]): ShadowingSeq[U] =
    ShadowingSeq.empty[U] ++ toSeq.map(f)
  def mapSubSeq[U](f: Seq[T] => Seq[U]): ShadowingSeq[U] =
    ShadowingSeq[U](values.map(f))
  def filter(f: T => Boolean)(implicit key: ShadowingSeq.KeyOf[T]): ShadowingSeq[T] =
    ShadowingSeq.empty ++ toSeq.filter(f)
  def filterSubSeq(f: Seq[T] => Boolean): ShadowingSeq[T] =
    ShadowingSeq(values.filter(f))
  def filterKeys(f: T => Boolean): ShadowingSeq[T] =
    filterSubSeq {
      case Seq(head, _*) => f(head)
      case _             => true
    }
  def keys: Seq[T] = values.map(_.head)
  def ++(other: Seq[T])(implicit key: ShadowingSeq.KeyOf[T]): ShadowingSeq[T] =
    addGroups(ShadowingSeq.groups(other, key.groups(other)))
  private def addGroups(other: Seq[Seq[T]])(implicit key: ShadowingSeq.KeyOf[T]): ShadowingSeq[T] =
    if (other.isEmpty) this
    else {
      val l    = new mutable.ListBuffer[Seq[T]]
      val seen = new mutable.HashSet[String]
      for (group <- values.iterator ++ other.iterator) {
        assert(group.nonEmpty)
        val keyOpt = key.makeKey(group)
        if (!keyOpt.exists(seen.contains)) {
          l += group
          for (key <- keyOpt)
            seen += key
        }
      }

      ShadowingSeq(l.toList)
    }
  def keyValueMap: Map[T, Seq[T]] =
    values
      .flatMap {
        case Seq(head, tail*) => Some(head -> tail)
        case _                => None
      }
      .toMap

  def get(key: T): Seq[T] =
    keyValueMap
      .get(key)
      .toSeq.flatten
}

object ShadowingSeq {

  final case class KeyOf[T](
    makeKey: Seq[T] => Option[String],
    /** The indices at which sub-groups of values start */
    groups: Seq[T] => Seq[Int]
  )
  object KeyOf {
    implicit val keyOfAnyDependency: KeyOf[AnyDependency] =
      KeyOf(deps => deps.headOption.map(_.module.render), _.indices)
  }

  implicit def monoid[T](implicit key: KeyOf[T]): ConfigMonoid[ShadowingSeq[T]] =
    ConfigMonoid.instance(ShadowingSeq.empty[T]) { (a, b) =>
      a.addGroups(b.values)
    }
  implicit def hashedField[T](implicit
    hasher: HashedType[T]
  ): HasHashData[ShadowingSeq[T]] = {
    (name, seq, update) =>
      for (t <- seq.toSeq)
        update(s"$name+=${hasher.hashedValue(t)}")
  }

  def empty[T]: ShadowingSeq[T] = ShadowingSeq(Nil)

  def from[T](values: Seq[T])(implicit key: KeyOf[T]): ShadowingSeq[T] =
    empty[T] ++ values

  private def groups[T](values: Seq[T], indices: Seq[Int]): Seq[Seq[T]] = {
    val safeIndices = Seq(0) ++ indices ++ Seq(values.length)
    safeIndices
      .sliding(2)
      .map {
        case Seq(start, end) =>
          values.slice(start, end)
      }
      .filter(_.nonEmpty)
      .toVector
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy