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

basis.form.JsonExprFactory.scala Maven / Gradle / Ivy

//      ____              ___
//     / __ | ___  ____  /__/___      A library of building blocks
//    / __  / __ |/ ___|/  / ___|
//   / /_/ / /_/ /\__ \/  /\__ \      (c) 2012-2015 Chris Sachs
//  |_____/\_____\____/__/\____/      http://basis.reify.it

package basis.form

import basis._
import basis.collections._
import basis.text._
import scala.reflect.macros._

private[form] final class JsonExprFactory[C <: blackbox.Context, V <: JsonVariant](val c: C)(v: C#Expr[V]) extends JsonFactory {
  import c.{ Expr, Tree, WeakTypeTag }
  import c.universe._
  import c.universe.internal._

  protected val variant: Expr[V] = v.asInstanceOf[Expr[V]]

  override type JsonValue     = Expr[V#AnyForm]
  override type JsonObject    = Expr[V#ObjectForm]
  override type JsonArray     = Expr[V#SeqForm]
  override type JsonString    = Expr[V#TextForm]
  override type JsonNumber    = Expr[V#NumberForm]
  override type JsonBoolean   = Expr[V#BoolForm]
  override type JsonNull      = Expr[V#NullForm]
  override type JsonUndefined = Expr[V#NoForm]

  implicit protected def AnyFormTag    = WeakTypeTag[V#AnyForm](VariantType("AnyForm"))
  implicit protected def ObjectFormTag = WeakTypeTag[V#ObjectForm](VariantType("ObjectForm"))
  implicit protected def SeqFormTag    = WeakTypeTag[V#SeqForm](VariantType("SeqForm"))
  implicit protected def TextFormTag   = WeakTypeTag[V#TextForm](VariantType("TextForm"))
  implicit protected def NumberFormTag = WeakTypeTag[V#NumberForm](VariantType("NumberForm"))
  implicit protected def BoolFormTag   = WeakTypeTag[V#BoolForm](VariantType("BoolForm"))
  implicit protected def NullFormTag   = WeakTypeTag[V#NullForm](VariantType("NullForm"))
  implicit protected def NoFormTag     = WeakTypeTag[V#NoForm](VariantType("NoForm"))

  override def JsonObjectValue(expr: Expr[V#ObjectForm]) = Expr[V#AnyForm](q"$variant.JsonObjectValue($expr)")
  override def JsonArrayValue(expr: Expr[V#SeqForm])     = Expr[V#AnyForm](q"$variant.JsonArrayValue($expr)")
  override def JsonStringValue(expr: Expr[V#TextForm])   = Expr[V#AnyForm](q"$variant.JsonStringValue($expr)")

  override def JsonObjectBuilder: Builder[(String, Expr[V#AnyForm])] with State[Expr[V#ObjectForm]] = new JsonObjectBuilder
  override def JsonArrayBuilder: Builder[Expr[V#AnyForm]] with State[Expr[V#SeqForm]]               = new JsonArrayBuilder
  override def JsonStringBuilder: StringBuilder with State[Expr[V#TextForm]]                        = new JsonStringBuilder

  override def JsonString(value: String)  = Expr[V#TextForm](if (value.length == 0) q"$variant.TextForm.empty" else q"$variant.JsonString($value)")
  override def JsonNumber(value: String)  = Expr[V#NumberForm](q"$variant.JsonNumber(${JsonNumberLiteral(value)})")
  override def JsonInteger(value: String) = Expr[V#NumberForm](q"$variant.JsonNumber(${JsonIntegerLiteral(value)})")
  override def JsonTrue                   = Expr[V#BoolForm](q"$variant.JsonTrue")
  override def JsonFalse                  = Expr[V#BoolForm](q"$variant.JsonFalse")
  override def JsonNull                   = Expr[V#NullForm](q"$variant.JsonNull")
  override def JsonUndefined              = Expr[V#NoForm](q"$variant.JsonUndefined")

  override def JsonNew(identifier: String, arguments: Expr[V#SeqForm]) = Expr[V#AnyForm](q"$variant.JsonNew($identifier, $arguments)")

  private def JsonNumberLiteral(value: String): Tree = {
    try Literal(Constant(java.lang.Double.parseDouble(value)))
    catch {
      case _: NumberFormatException =>
        Literal(Constant(value))
    }
  }

  private def JsonIntegerLiteral(value: String): Tree = {
    try Literal(Constant(java.lang.Integer.parseInt(value)))
    catch {
      case _: NumberFormatException =>
        try Literal(Constant(java.lang.Long.parseLong(value)))
        catch {
          case _: NumberFormatException =>
            Literal(Constant(value))
        }
    }
  }

  private final class JsonObjectBuilder extends Builder[(String, Expr[V#AnyForm])] with State[Expr[V#ObjectForm]] {
    private[this] val underlying                                    = mutable.ArrayBuffer.empty[(String, Expr[V#AnyForm])]
    override def clear(): Unit                                      = underlying.clear()
    override def expect(count: Int): this.type                      = { underlying.expect(count); this }
    override def append(fieldExpr: (String, Expr[V#AnyForm])): Unit = underlying.append(fieldExpr)

    override def state = Expr[V#ObjectForm] {
      if (underlying.isEmpty) q"$variant.ObjectForm.empty"
      else {
        val builder = underlying.foldLeft(q"$variant.JsonObjectBuilder.expect(${underlying.length})")((b, e) => q"$b += ((${e._1}, ${e._2}))")
        q"$builder.state"
      }
    }
  }

  private final class JsonArrayBuilder extends Builder[Expr[V#AnyForm]] with State[Expr[V#SeqForm]] {
    private[this] val underlying                     = mutable.ArrayBuffer.empty[Expr[V#AnyForm]]
    override def clear(): Unit                       = underlying.clear()
    override def expect(count: Int): this.type       = { underlying.expect(count); this }
    override def append(expr: Expr[V#AnyForm]): Unit = underlying.append(expr)

    override def state = Expr[V#SeqForm] {
      if (underlying.isEmpty) q"$variant.SeqForm.empty"
      else {
        val builder = underlying.foldLeft(q"$variant.JsonArrayBuilder.expect(${underlying.length})")((b, e) => q"$b += $e")
        q"$builder.state"
      }
    }
  }

  private final class JsonStringBuilder extends StringBuilder with State[Expr[V#TextForm]] {
    private[this] val underlying                = String.Builder
    override def clear(): Unit                  = underlying.clear()
    override def expect(count: Int): this.type  = { underlying.expect(count); this }
    override def append(c: Int): Unit           = underlying.append(c)
    override def append(cs: CharSequence): Unit = underlying.append(cs)
    override def state: Expr[V#TextForm]        = JsonString(underlying.state)
  }

  protected def VariantType(name: String): Type =
    typeRef(variant.staticType, variant.staticType.member(TypeName(name)), Nil).dealias
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy