<commit_before>package adt.bson

import org.bson.BsonType
import org.bson.types.ObjectId
import org.joda.time.{DateTime, DateTimeZone}

import scala.util.Try
import scala.util.matching.Regex

/**
 * Generic Bson value.
 *
 * This is a closed algebraic data type for all values that can be stored in Mongo.
 *
 * See {@link http://bsonspec.org/spec.html}
 *
 * (Currently) Unsupported Types:
 * Undefined                \x06 / 6    (deprecated)
 * DBPointer                \x0C / 12   (deprecated)
 * JavaScript               \x0D / 13   (javascript in the database? are you sure you want this noose?)
 * Symbol                   \x0E / 14   (deprecated)
 * JavaScript (with scope)  \x0F / 15   (javascript in the database? with scope? really?)
 * Timestamp                \x11 / 17   (used for internal increment values)
 * Min key                  \xFF / 255  (used internally)
 * Max key                  \x7F / 127  (used internally)
 */
sealed trait BsonValue {
  @deprecated("Use (???: BsonValue).ScalaType instead.", "1.3.0")
  type $type = ScalaType
  @deprecated("Use (???: BsonValue).Type.getValue instead.", "1.3.0")
  def $type: Int = Type.getValue
  type ScalaType
  def Type: BsonType
  def value: ScalaType

  /**
   * Tries to convert the value into a [[T]], throwing an exception if it can't.
   * An implicit [[BsonReads]] of [[T]] must be defined.
   */
  def as[T](implicit reader: BsonReads[T]): T = reader reads this

  /**
   * Tries to convert the value into a [[T]]. An implicit [[BsonReads]] of [[T]] must be defined.
   * Any error is mapped to None
   *
   * @return Some[T] if it succeeds, None if it fails.
   */
  def asOpt[T](implicit reader: BsonReads[T]): Option[T] = Try(reader reads this).toOption.filter {
    case BsonUndefined() => false
    case _ => true
  }

  /**
   * Return the property corresponding to the fieldName, supposing we have a [[BsonObject]].
   *
   * @param fieldName the name of the property to lookup
   * @return the resulting [[BsonValue]].
   *         If the current node is not a [[BsonObject]] or doesn't have the property,
   *         a [[BsonUndefined]] will be returned.
   */
  def \(fieldName: String): BsonValue = BsonUndefined(s"'$fieldName' is undefined on object: $this")

  /**
   * Whether {{{value == null}}} would be true in JavaScript / Mongo.
   */
  def equalsNull: Boolean = false

  /**
   * Strips out any `null` values from arrays and `null` fields from objects.
   *
   * @note This does not remove empty arrays or objects.
   */
  def pruned: BsonValue = this

}

/**
 * Any [[BsonValue]] that can exist inside of another [[BsonContainer]], but has no children itself.
 *
 * @note this
 */
sealed trait BsonPrimitive extends BsonValue

/**
 * Any [[BsonValue]] that can potentially contain [[BsonPrimitive]] children.
 */
sealed trait BsonContainer extends BsonValue {

  def children: Iterable[BsonValue]
}

case class BsonBoolean(value: Boolean) extends BsonPrimitive {
  override type ScalaType = Boolean
  @inline final override def Type: BsonType = BsonType.BOOLEAN
}

case class BsonNumber(value: Double) extends BsonPrimitive {
  override type ScalaType = Double
  @inline final override def Type: BsonType = BsonType.DOUBLE
}

case class BsonInt(value: Int) extends BsonPrimitive {
  override type ScalaType = Int
  @inline final override def Type: BsonType = BsonType.INT32
}

case class BsonLong(value: Long) extends BsonPrimitive {
  override type ScalaType = Long
  @inline final override def Type: BsonType = BsonType.INT64
}

case class BsonString(value: String) extends BsonPrimitive {
  override type ScalaType = String
  @inline final override def Type: BsonType = BsonType.STRING
}

case class BsonBinary(value: Array[Byte]) extends BsonPrimitive with Proxy {
  override type ScalaType = Array[Byte]
  @inline final override def Type: BsonType = BsonType.BINARY
<commit_msg>Added deprecation for future major upgrade.<commit_after>package adt.bson

import org.bson.BsonType
import org.bson.types.ObjectId
import org.joda.time.{DateTime, DateTimeZone}

import scala.util.Try
import scala.util.matching.Regex

/**
 * Generic Bson value.
 *
 * This is a closed algebraic data type for all values that can be stored in Mongo.
 *
 * See {@link http://bsonspec.org/spec.html}
 *
 * (Currently) Unsupported Types:
 * Undefined                \x06 / 6    (deprecated)
 * DBPointer                \x0C / 12   (deprecated)
 * JavaScript               \x0D / 13   (javascript in the database? are you sure you want this noose?)
 * Symbol                   \x0E / 14   (deprecated)
 * JavaScript (with scope)  \x0F / 15   (javascript in the database? with scope? really?)
 * Timestamp                \x11 / 17   (used for internal increment values)
 * Min key                  \xFF / 255  (used internally)
 * Max key                  \x7F / 127  (used internally)
 */
sealed trait BsonValue {
  @deprecated("Use (???: BsonValue).ScalaType instead.", "1.3.0")
  type $type = ScalaType
  @deprecated("Use (???: BsonValue).Type.getValue instead.", "1.3.0")
  def $type: Int = Type.getValue
  type ScalaType
  def Type: BsonType
  def value: ScalaType

  /**
   * Tries to convert the value into a [[T]], throwing an exception if it can't.
   * An implicit [[BsonReads]] of [[T]] must be defined.
   */
  def as[T](implicit reader: BsonReads[T]): T = reader reads this

  /**
   * Tries to convert the value into a [[T]]. An implicit [[BsonReads]] of [[T]] must be defined.
   * Any error is mapped to None
   *
   * @return Some[T] if it succeeds, None if it fails.
   */
  def asOpt[T](implicit reader: BsonReads[T]): Option[T] = Try(reader reads this).toOption.filter {
    case BsonUndefined() => false
    case _ => true
  }

  /**
   * Return the property corresponding to the fieldName, supposing we have a [[BsonObject]].
   *
   * @param fieldName the name of the property to lookup
   * @return the resulting [[BsonValue]].
   *         If the current node is not a [[BsonObject]] or doesn't have the property,
   *         a [[BsonUndefined]] will be returned.
   */
  def \(fieldName: String): BsonValue = BsonUndefined(s"'$fieldName' is undefined on object: $this")

  /**
   * Whether {{{value == null}}} would be true in JavaScript / Mongo.
   */
  def equalsNull: Boolean = false

  /**
   * Strips out any `null` values from arrays and `null` fields from objects.
   *
   * @note This does not remove empty arrays or objects.
   */
  def pruned: BsonValue = this

}

/**
 * Any [[BsonValue]] that can exist inside of another [[BsonContainer]], but has no children itself.
 */
sealed trait BsonPrimitive extends BsonValue

object BsonPrimitive {

  def apply[T <: AnyVal : BsonWrites](value: T): BsonPrimitive = {
    val bson = Bson.toBson(value)
    bson match {
      case BsonPrimitive(prim) =>
      case other =>
        throw new IllegalArgumentException(s"BsonWrites for value $value did not produce a BsonPrimitive, but instead produced $bson")
    }
  }

  def unapply(bson: BsonValue): Option[BsonPrimitive] = bson match {
    case prim: BsonPrimitive => Some(prim)
    case _ => None
  }
}

/**
 * TODO: Expand this out in the next major version.
 *
 * Soon all numeric [[BsonValue]]s extend from this trait.
 */
sealed trait BsonNumber extends BsonValue

object BsonNumber {

  @deprecated("Use BsonDouble(value) instead.", "1.3.1")
  def apply(value: Double): BsonDouble = BsonDouble(value)

  @deprecated("Use case BsonDouble(value) instead", "1.3.1")
  def unapply(bson: BsonNumber): Option[Double] = bson match {
    case BsonDouble(value) => Some(value)
    case _ => None
  }
}

/**
 * Any [[BsonValue]] that can potentially contain [[BsonPrimitive]] children.
 */
sealed trait BsonContainer extends BsonValue {

  def children: Iterable[BsonValue]
}

case class BsonBoolean(value: Boolean) extends BsonPrimitive {
  override type ScalaType = Boolean
  @inline final override def Type: BsonType = BsonType.BOOLEAN
}

case class BsonDouble(value: Double) extends BsonPrimitive with BsonNumber {
  override type ScalaType = Double
  @inline final override def Type: BsonType = BsonType.DOUBLE
}

case class BsonInt(value: Int) extends BsonPrimitive {
  override type ScalaType = Int
  @inline final override def Type: BsonType = BsonType.INT32
}

case class BsonLong(value: Long) extends BsonPrimitive {
  override type ScalaType = Long
  @inline final override def Type: BsonType = BsonType.INT64
}

case class BsonString(value: String) extends BsonPrimitive {
  override type ScalaType = String
  @inline final override def Type: BsonType = BsonType.STRING
}

case class BsonBinary(value: Array[Byte]) extends BsonPrimitive with Proxy {
  override type ScalaType = Array[Byte]
  @inline final override def Type: BsonType = BsonType.BINARY

{'fraction_non_alphanumeric': 0.10643394934976044, 'fraction_numerical': 0.00889801505817933, 'mean_word_length': 3.2169312169312168, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3627546', 'n_tokens_mistral': 2768, 'n_tokens_neox': 2709, 'n_words': 954}