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

io.circe.HCursor.scala Maven / Gradle / Ivy

There is a newer version: 0.13.0
Show newest version
package io.circe

import cats.Applicative
import io.circe.cursor.{ ArrayCursor, ObjectCursor, TopCursor }
import scala.annotation.tailrec

abstract class HCursor(lastCursor: HCursor, lastOp: CursorOp) extends ACursor(lastCursor, lastOp) {
  def value: Json

  def replace(newValue: Json, cursor: HCursor, op: CursorOp): HCursor
  def addOp(cursor: HCursor, op: CursorOp): HCursor

  final def withFocus(f: Json => Json): ACursor = replace(f(value), this, null)
  final def withFocusM[F[_]](f: Json => F[Json])(implicit F: Applicative[F]): F[ACursor] =
    F.map(f(value))(replace(_, this, null))

  final def succeeded: Boolean = true
  final def success: Option[HCursor] = Some(this)

  final def focus: Option[Json] = Some(value)

  final def values: Option[Iterable[Json]] = value match {
    case Json.JArray(vs) => Some(vs)
    case _               => None
  }

  final def keys: Option[Iterable[String]] = value match {
    case Json.JObject(o) => Some(o.keys)
    case _               => None
  }

  final def top: Option[Json] = {
    var current: HCursor = this

    while (!current.isInstanceOf[TopCursor]) {
      current = current.up.asInstanceOf[HCursor]
    }

    Some(current.asInstanceOf[TopCursor].value)
  }

  final def downArray: ACursor = value match {
    case Json.JArray(values) if !values.isEmpty =>
      new ArrayCursor(values, 0, this, false)(this, CursorOp.DownArray)
    case _ => fail(CursorOp.DownArray)
  }

  final def downField(k: String): ACursor = value match {
    case Json.JObject(o) =>
      if (!o.contains(k)) fail(CursorOp.DownField(k))
      else {
        new ObjectCursor(o, k, this, false)(this, CursorOp.DownField(k))
      }
    case _ => fail(CursorOp.DownField(k))
  }

  final def downN(n: Int): ACursor = value match {
    case Json.JArray(values) if n >= 0 && values.size > n =>
      new ArrayCursor(values, n, this, false)(this, CursorOp.DownN(n))
    case _ => fail(CursorOp.DownN(n))
  }

  final def leftN(n: Int): ACursor = if (n < 0) rightN(-n)
  else {
    @tailrec
    def go(i: Int, c: ACursor): ACursor = if (i == 0) c else go(i - 1, c.left)

    go(n, this)
  }

  final def rightN(n: Int): ACursor = if (n < 0) leftN(-n)
  else {
    @tailrec
    def go(i: Int, c: ACursor): ACursor = if (i == 0) c else go(i - 1, c.right)

    go(n, this)
  }

  /**
   * Create a new cursor that has failed on the given operation.
   *
   * @group Utilities
   */
  protected[this] final def fail(op: CursorOp): ACursor = new FailedCursor(this, op)
}

object HCursor {
  def fromJson(value: Json): HCursor = new TopCursor(value)(null, null)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy