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

mist.api.encoding.DefaultsPatcher.scala Maven / Gradle / Ivy

The newest version!
package mist.api.encoding

import mist.api.data.{JsMap, JsNull}
import shadedshapeless.labelled.FieldType
import shadedshapeless._

import scala.annotation.implicitNotFound

/**
  * Obtain defaults values from case classes and patch incoming js by encoding them into jsMap
  */
@implicitNotFound("Couldn't find DefaultsPatcher for ${A}. Ensure that there are JsEncoder instances for default values in current scope")
trait DefaultsPatcher[A] {
  def apply(js: JsMap): JsMap
}

object DefaultsPatcher {

  trait InternalPatcher[A] {
    def apply(a: A, js: JsMap): JsMap
  }

  object InternalPatcher {
    def create[A](f: (A, JsMap) => JsMap): InternalPatcher[A] = new InternalPatcher[A] {
      override def apply(a: A, js: JsMap): JsMap = f(a, js)
    }

    implicit val hHNilPatcher: InternalPatcher[HNil] = InternalPatcher.create((_, js) => js)

    implicit def hlistPatcher[K <: Symbol, H, T <: HList](implicit
      witness: Witness.Aux[K],
      lEnc: Lazy[JsEncoder[H]],
      tPath: InternalPatcher[T]
    ): InternalPatcher[FieldType[K, H] :: T] = {
      val enc = lEnc.value
      val key = witness.value.name
      InternalPatcher.create[FieldType[K, H] :: T]((hList, js) => {
        val patched = js.fieldValue(key) match {
          case JsNull => JsMap((key -> enc(hList.head)) +: js.fields: _*)
          case _ => js
        }
        tPath(hList.tail, patched)
      })
    }
  }


  implicit def labelled[A, H <: HList](implicit
    defaults: Default.AsRecord.Aux[A, H],
    intPatch: InternalPatcher[H]
  ): DefaultsPatcher[A] = new DefaultsPatcher[A] {
    override def apply(js: JsMap): JsMap = {
      intPatch.apply(defaults(), js)
    }
  }

  def apply[A](implicit patcher: DefaultsPatcher[A]): DefaultsPatcher[A] = patcher
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy