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

io.circe.shapes.HListInstances.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2024 circe
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.circe.shapes

import io.circe.Decoder
import io.circe.DecodingFailure
import io.circe.DecodingFailure.Reason.WrongTypeExpectation
import io.circe.Encoder
import io.circe.HCursor
import io.circe.Json
import io.circe.JsonObject
import shapeless.::
import shapeless.HList
import shapeless.HNil

trait HListInstances extends LowPriorityHListInstances {
  implicit final def decodeSingletonHList[H](implicit decodeH: Decoder[H]): Decoder[H :: HNil] =
    Decoder[Tuple1[H]].map(t => t._1 :: HNil).withErrorMessage("HList")

  implicit final def encodeSingletonHList[H](implicit encodeH: Encoder[H]): Encoder.AsArray[H :: HNil] =
    new Encoder.AsArray[H :: HNil] {
      def encodeArray(a: H :: HNil): Vector[Json] = Vector(encodeH(a.head))
    }
}

private[shapes] trait LowPriorityHListInstances {
  implicit final val decodeHNil: Decoder[HNil] = new Decoder[HNil] {
    def apply(c: HCursor): Decoder.Result[HNil] =
      if (c.value.isObject) Right(HNil)
      else Left(DecodingFailure(WrongTypeExpectation("object", c.value), c.history))
  }

  implicit final val encodeHNil: Encoder.AsObject[HNil] = new Encoder.AsObject[HNil] {
    def encodeObject(a: HNil): JsonObject = JsonObject.empty
  }

  implicit final def decodeHCons[H, T <: HList](implicit
    decodeH: Decoder[H],
    decodeT: Decoder[T]
  ): Decoder[H :: T] = new Decoder[H :: T] {
    def apply(c: HCursor): Decoder.Result[H :: T] = {
      val first = c.downArray

      Decoder.resultInstance.map2(first.as(decodeH), decodeT.tryDecode(first.delete))(_ :: _)
    }

    override def decodeAccumulating(c: HCursor): Decoder.AccumulatingResult[H :: T] = {
      val first = c.downArray

      Decoder.accumulatingResultInstance.map2(
        decodeH.tryDecodeAccumulating(first),
        decodeT.tryDecodeAccumulating(first.delete)
      )(_ :: _)
    }
  }

  implicit final def encodeHCons[H, T <: HList](implicit
    encodeH: Encoder[H],
    encodeT: Encoder.AsArray[T]
  ): Encoder.AsArray[H :: T] = new Encoder.AsArray[H :: T] {
    def encodeArray(a: H :: T): Vector[Json] = encodeH(a.head) +: encodeT.encodeArray(a.tail)
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy