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

prickle.PConfig.scala Maven / Gradle / Ivy

package prickle

import scala.util.{Failure, Success, Try}
import collection.mutable

import microjson._

object PConfig {
  implicit val Default = new JsConfig()

}

trait PConfig[P] extends PReader[P] with PBuilder[P] {

  def prefix: String

  def areSharedObjectsSupported: Boolean

  @deprecated("Use areSharedObjectsSupported instead. (Misleadingly name)", "1.1.0")
  def isCyclesSupported: Boolean = areSharedObjectsSupported

}

case class JsConfig(val prefix: String = "#", val areSharedObjectsSupported: Boolean = true)
  extends PConfig[JsValue] with JsBuilder with JsReader {

  def onUnpickle(id: String, value: Any, state: mutable.Map[String, Any]) = {
    state += (id -> value)
  }

}
trait AcyclicPConfig[P] extends PConfig[P] {
  def areSharedObjectsSupported = false
}



trait PBuilder[P] {

  def makeNull(): P
  def makeBoolean(b: Boolean): P
  def makeNumber(x: Double): P
  def makeString(s: String): P
  def makeArray(elems: P*): P
  def makeObject(fields: Seq[(String, P)]): P

  def makeObject(k: String, v: P): P = makeObject(Seq((k, v)))
  def makeObjectFrom(fields: (String, P)*): P = makeObject(fields)
}

trait PReader[P] {

  def isNull(x: P): Boolean
  def readBoolean(x: P): Try[Boolean]
  def readNumber(x: P): Try[Double]
  def readString(x: P): Try[String]
  def readArrayLength(x: P): Try[Int]
  def readArrayElem(x: P, index: Int): Try[P]
  def readObjectField(x: P, field: String): Try[P]

  def readObjectFieldStr(x: P, field: String): Try[String] = readObjectField(x, field).flatMap(readString)

  def readObjectFieldNum(x: P, field: String): Try[Double] = readObjectField(x, field).flatMap(readNumber)
}


trait JsBuilder extends PBuilder[JsValue] {
  def makeNull(): JsValue = JsNull
  def makeBoolean(b: Boolean): JsValue = if (b) JsTrue else JsFalse
  def makeNumber(x: Double): JsValue = JsNumber(x.toString)

  def makeString(s: String): JsValue = JsString(s)
  def makeArray(elems: JsValue*): JsValue = JsArray(elems.toVector)
  def makeObject(fields: Seq[(String, JsValue)]): JsValue = JsObject(fields.toMap)
}

trait JsReader extends PReader[JsValue] {
  def isNull(x: JsValue): Boolean = x match {
    case JsNull => true
    case _ => false
  }
  def readBoolean(x: JsValue): Try[Boolean] = x match {
    case JsTrue => Success(true)
    case JsFalse => Success(false)
    case other => error("boolean", s"$other")
  }
  def readNumber(x: JsValue): Try[Double] = x match {
    case x: JsNumber => Try(x.value.toDouble)
    case other => error("number", s"$other")
  }
  def readString(x: JsValue): Try[String] = x match {
    case s: JsString => Success(s.value)
    case other => error("string", s"$other")
  }
  def readArrayLength(x: JsValue): Try[Int] = x match {
    case x: JsArray => Success(x.value.length)
    case other => error("array length", s"$other")
  }
  def readArrayElem(x: JsValue, index: Int): Try[JsValue] = x match {
    case x: JsArray if index < x.value.length => Success(x.value(index))
    case other => error(s"array($index)", s"$other")
  }
  def readObjectField(x: JsValue, field: String): Try[JsValue] = x match {
    case x: JsObject => Try(x.value(field)).orElse(fail(
      s"Cannot read field '$field' of '$x', available fields: ${x.value.values.mkString(", ")}"))
    case other =>  error(s"field \'$field\'", s"$other")
  }

  def error(exp: String, actual: String) = Failure(new RuntimeException(s"Expected: $exp  Actual: $actual"))

  def fail(msg: String) = Failure(new RuntimeException(msg))
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy