io.circe.DecodingFailure Scala Examples

The following examples show how to use io.circe.DecodingFailure. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: Analyzer.scala    From scarango   with MIT License 8 votes vote down vote up
package com.outr.arango

import io.circe.Decoder.Result
import io.circe.{Decoder, DecodingFailure, Encoder, HCursor, Json}

sealed abstract class Analyzer(val name: String)

object Analyzer {
  case object Identity extends Analyzer("identity")
  case object TextGerman extends Analyzer("text_de")
  case object TextEnglish extends Analyzer("text_en")
  case object TextSpanish extends Analyzer("text_es")
  case object TextFinnish extends Analyzer("text_fi")
  case object TextFrench extends Analyzer("text_fr")
  case object TextItalian extends Analyzer("text_it")
  case object TextDutch extends Analyzer("text_nl")
  case object TextNorwegian extends Analyzer("text_no")
  case object TextPortuguese extends Analyzer("text_pt")
  case object TextRussian extends Analyzer("text_ru")
  case object TextSwedish extends Analyzer("text_sv")
  case object TextChinese extends Analyzer("text_zh")

  private val map = List(Identity, TextGerman, TextEnglish, TextSpanish, TextFinnish, TextFrench, TextItalian, TextDutch, TextNorwegian, TextPortuguese, TextRussian, TextSwedish, TextChinese).map(a => a.name -> a).toMap

  def apply(name: String): Analyzer = map.getOrElse(name, throw new RuntimeException(s"Unable to find analyzer by name: $name"))

  implicit val decoder: Decoder[Analyzer] = new Decoder[Analyzer] {
    override def apply(c: HCursor): Result[Analyzer] = c.value.asString match {
      case Some(s) => Right(Analyzer(s))
      case None => Left(DecodingFailure(s"Expected String to decode Analyzer, but got: ${c.value}", Nil))
    }
  }

  implicit val encoder: Encoder[Analyzer] = new Encoder[Analyzer] {
    override def apply(a: Analyzer): Json = Json.fromString(a.name)
  }
} 
Example 2
Source File: TopicConfigurationParser.scala    From kafka-configurator   with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
package com.sky.kafka.configurator

import java.io.{Reader => JReader}

import cats.instances.either._
import cats.instances.list._
import cats.syntax.either._
import cats.syntax.traverse._
import io.circe
import io.circe.generic.AutoDerivation
import io.circe.yaml.parser._
import io.circe.{Decoder, DecodingFailure, Json}

import scala.collection.immutable.ListMap

object TopicConfigurationParser extends AutoDerivation {

  def apply(topicConfigReader: JReader): Either[circe.Error, List[Topic]] =
    for {
      ymlAsJson <- parse(topicConfigReader)
      topicConfigs <- if (ymlAsJson.isBoolean) List.empty[Topic].asRight else ymlAsJson.as[List[Topic]]
    } yield topicConfigs

  case class TopicConfig(partitions: Int, replication: Int, config: Map[String, String])

  implicit val topicsDecoder: Decoder[List[Topic]] = Decoder.instance { cursor =>
    for {
      configMap <- cursor.as[ListMap[String, TopicConfig]]
      topics = configMap.map { case (name, conf) => Topic(name, conf.partitions, conf.replication, conf.config) }
    } yield topics.toList
  }

  implicit val stringMapDecoder: Decoder[Map[String, String]] = Decoder.instance { cursor =>
    def stringify(json: Json): Json =
      json.asNumber.fold(json)(num =>
        Json.fromString(num.toLong.fold(num.toDouble.toString)(_.toString)))

    def failWithMsg(msg: String) = DecodingFailure(msg, List.empty)

    for {
      jsonObj <- cursor.value.asObject.toRight(failWithMsg(s"${cursor.value} is not an object"))
      valuesAsJsonStrings = jsonObj.mapValues(stringify)
      stringMap <- valuesAsJsonStrings.toList.traverse[Decoder.Result, (String, String)] {
        case (key, json) => json.asString.toRight(failWithMsg(s"$json is not a string")).map(key -> _)
      }
    } yield stringMap.toMap
  }
} 
Example 3
Source File: GraphQLResponseError.scala    From caliban   with Apache License 2.0 5 votes vote down vote up
package caliban.client

import caliban.client.GraphQLResponseError.Location
import io.circe.{ Decoder, DecodingFailure, HCursor }


case class GraphQLResponseError(
  message: String,
  locations: Option[List[Location]],
  path: Option[List[Either[String, Int]]]
)

object GraphQLResponseError {

  case class Location(line: Int, column: Int)

  implicit val decoderEither: Decoder[Either[String, Int]] = (c: HCursor) =>
    c.value.asNumber.flatMap(_.toInt).map(v => Right(Right(v))) orElse c.value.asString
      .map(v => Right(Left(v))) getOrElse Left(DecodingFailure("Value is not an Either[String, Int]", c.history))

  implicit val locationDecoder: Decoder[Location] = (c: HCursor) =>
    for {
      line   <- c.downField("line").as[Int]
      column <- c.downField("column").as[Int]
    } yield Location(line, column)

  implicit val decoder: Decoder[GraphQLResponseError] = (c: HCursor) =>
    for {
      message   <- c.downField("message").as[String]
      locations <- c.downField("locations").as[Option[List[Location]]]
      path      <- c.downField("path").as[Option[List[Either[String, Int]]]]
    } yield GraphQLResponseError(message, locations, path)

} 
Example 4
Source File: SignedTransactionSpec.scala    From iotchain   with MIT License 5 votes vote down vote up
package jbok.core.models

import cats.effect.IO
import io.circe.CursorOp.DownField
import io.circe.DecodingFailure
import jbok.core.CoreSpec
import jbok.core.validators.TxValidator
import jbok.crypto._
import jbok.crypto.signature.{ECDSA, Signature}
import io.circe.parser._

class SignedTransactionSpec extends CoreSpec {
  "SignedTransaction" should {
    "correctly set pointSign for chainId with chain specific signing schema" in {
      forAll { tx: Transaction =>
        val keyPair          = Signature[ECDSA].generateKeyPair[IO]().unsafeRunSync()
        val chainId: ChainId = ChainId(61)
        val address          = Address(keyPair.public.bytes.kec256)
        val result           = SignedTransaction.sign[IO](tx, keyPair, chainId).unsafeRunSync()
        val senderAddress    = result.senderAddress.getOrElse(Address.empty)
        address shouldBe senderAddress
        Long.MaxValue
      }
    }

    "respect chainId" in {
      forAll { tx: Transaction =>
        val keyPair          = Signature[ECDSA].generateKeyPair[IO]().unsafeRunSync()
        val chainId: ChainId = config.genesis.chainId
        val stx              = SignedTransaction.sign[IO](tx, keyPair, chainId).unsafeRunSync()
        TxValidator.checkSyntacticValidity[IO](stx, chainId).attempt.unsafeRunSync().isRight shouldBe true

        val stx2 = SignedTransaction.sign[IO](tx, keyPair, ChainId(2)).unsafeRunSync()
        TxValidator.checkSyntacticValidity[IO](stx2, chainId).attempt.unsafeRunSync().isLeft shouldBe true
      }
    }

    "decode huge json object" in {
      val left  = "{"
      val key   = "\"key\""
      val value = "100"
      val right = "}"

      def genJson(value: String, n: Int): String = {
        val obj = left + key + ":" + value + right
        if (n > 0) {
          genJson(obj, n - 1)
        } else {
          obj
        }
      }
      val json = genJson(value, 5000)
      parse(json)

      val error = decode[SignedTransaction](json)
      error shouldBe Left(DecodingFailure("Attempt to decode value on failed cursor", List(DownField("nonce"))))
    }
  }
} 
Example 5
Source File: DataEntry.scala    From Waves   with MIT License 5 votes vote down vote up
package com.wavesplatform.lang.v1.repl.node.http.response.model

import com.wavesplatform.lang.v1.traits.DataType
import io.circe.{Decoder, DecodingFailure, HCursor}

private[node] case class DataEntry(key: String, value: Any, `type`: DataType)

private[node] object DataEntry {
  implicit val decoder: Decoder[DataEntry] = (c: HCursor) =>
    for {
      rawType <- c.downField("type").as[String]
      key     <- c.downField("key").as[String]
      v = c.downField("value")
      (value, resolvedType) <- rawType match {
        case "binary"  => v.as[ByteString] map(b => (b.byteStr, DataType.ByteArray))
        case "boolean" => v.as[Boolean]    map((_, DataType.Boolean))
        case "integer" => v.as[Long]       map((_, DataType.Long))
        case "string"  => v.as[String]     map((_, DataType.String))
        case t         => Left(DecodingFailure(s"Illegal data entry type: $t", Nil))
      }
    } yield DataEntry(key, value, resolvedType)
} 
Example 6
Source File: Tag.scala    From cosmos   with Apache License 2.0 5 votes vote down vote up
package com.mesosphere.universe.v3.model

import com.mesosphere.cosmos.circe.Decoders._
import com.twitter.util.Return
import com.twitter.util.Throw
import com.twitter.util.Try
import io.circe.syntax.EncoderOps
import io.circe.Decoder
import io.circe.DecodingFailure
import io.circe.Encoder
import io.circe.HCursor
import java.util.regex.Pattern

final class Tag private(val value: String) extends AnyVal {

  override def toString: String = value

}

object Tag {

  val packageDetailsTagRegex: String = "^[^\\s]+$"
  val packageDetailsTagPattern: Pattern = Pattern.compile(packageDetailsTagRegex)

  def apply(s: String): Tag = validate(s).get

  def validate(s: String): Try[Tag] = {
    if (packageDetailsTagPattern.matcher(s).matches()) {
      Return(new Tag(s))
    } else {
      Throw(new IllegalArgumentException(
        s"Value '$s' does not conform to expected format $packageDetailsTagRegex"
      ))
    }
  }

  implicit val encodePackageDefinitionTag: Encoder[Tag] = {
    Encoder.instance(_.value.asJson)
  }

  implicit val decodePackageDefinitionTag: Decoder[Tag] =
    Decoder.instance[Tag] { (c: HCursor) =>
      c.as[String].map(validate(_)).flatMap {
        case Return(r) => Right(r)
        case Throw(ex) =>
          val msg = ex.getMessage.replaceAllLiterally("assertion failed: ", "")
          Left(DecodingFailure(msg, c.history))
      }
    }

} 
Example 7
Source File: ReleaseVersion.scala    From cosmos   with Apache License 2.0 5 votes vote down vote up
package com.mesosphere.universe.v3.model

import com.twitter.util.Return
import com.twitter.util.Throw
import com.twitter.util.Try
import io.circe.Decoder
import io.circe.DecodingFailure
import io.circe.Encoder
import io.circe.HCursor
import io.circe.syntax.EncoderOps

final class ReleaseVersion private(val value: Long) extends AnyVal

object ReleaseVersion {

  def apply(value: Long): ReleaseVersion = validate(value).get

  def validate(value: Long): Try[ReleaseVersion] = {
    if (value >= 0) {
      Return(new ReleaseVersion(value))
    } else {
      val message = s"Expected integer value >= 0 for release version, but found [$value]"
      Throw(new IllegalArgumentException(message))
    }
  }

  implicit val packageDefinitionReleaseVersionOrdering: Ordering[ReleaseVersion] = {
    Ordering.by(_.value)
  }

  implicit val encodePackageDefinitionReleaseVersion: Encoder[ReleaseVersion] = {
    Encoder.instance(_.value.asJson)
  }

  implicit val decodePackageDefinitionReleaseVersion: Decoder[ReleaseVersion] =
    Decoder.instance[ReleaseVersion] { (c: HCursor) =>
      c.as[Long].map(validate).flatMap {
        case Return(v) => Right(v)
        case Throw(e) => Left(DecodingFailure(e.getMessage, c.history))
      }
    }


} 
Example 8
Source File: Decoders.scala    From cosmos   with Apache License 2.0 5 votes vote down vote up
package com.mesosphere.cosmos.circe

import cats.syntax.either._
import com.mesosphere.cosmos.error.JsonDecodingError
import com.mesosphere.cosmos.error.JsonParsingError
import com.mesosphere.cosmos.finch.MediaTypedDecoder
import com.mesosphere.error.Result
import com.mesosphere.error.ResultOps
import com.mesosphere.http.MediaType
import io.lemonlabs.uri.Uri
import io.circe.Decoder
import io.circe.DecodingFailure
import io.circe.Error
import io.circe.Json
import io.circe.ParsingFailure
import java.nio.ByteBuffer
import java.nio.charset.StandardCharsets
import java.util.Base64
import scala.reflect.ClassTag
import scala.reflect.classTag

object Decoders {

  implicit val decodeUri: Decoder[Uri] = Decoder.decodeString.map(Uri.parse)

  implicit val decodeString: Decoder[String] = {
    Decoder.decodeString.withErrorMessage("String value expected")
  }

  implicit val decodeByteBuffer: Decoder[ByteBuffer] = Decoder.instance { c =>
    c.as[String].bimap(
      { _ => DecodingFailure("Base64 string value expected", c.history) },
      { s => ByteBuffer.wrap(Base64.getDecoder.decode(s)) }
    )
  }

  def decode[T: Decoder: ClassTag](value: String): Result[T] = {
    convertToCosmosError(io.circe.jawn.decode[T](value), value)
  }

  def mediaTypedDecode[T: ClassTag](
    value: String,
    mediaType: MediaType
  )(
    implicit decoder: MediaTypedDecoder[T]
  ): Result[T] = {
    for {
      json <- parse(value)
      result <- decoder(
        json.hcursor,
        mediaType
      )
    } yield result
  }

  def parse(value: String): Result[Json] = {
    convertToCosmosError(io.circe.jawn.parse(value), value)
  }

  def decode64[T: Decoder: ClassTag](value: String): T = {
    decode[T](base64DecodeString(value)).getOrThrow
  }

  def parse64(value: String): Json = {
    parse(base64DecodeString(value)).getOrThrow
  }

  def convertToCosmosError[T: ClassTag](
    result: Either[Error, T],
    inputValue: String
  ): Result[T] = result match {
    case Right(value) => Right(value)
    case Left(ParsingFailure(message, underlying)) =>
      Left(
        JsonParsingError(
          underlying.getClass.getName,
          message,
          inputValue
        )
      )
    case Left(DecodingFailure(message, _)) =>
      Left(
        JsonDecodingError(
          classTag[T].runtimeClass.getName,
          message,
          inputValue
        )
      )
  }

  private[this] def base64DecodeString(value: String): String = {
    new String(Base64.getDecoder.decode(value), StandardCharsets.UTF_8)
  }
} 
Example 9
Source File: CirceStreamSupport.scala    From akka-stream-json   with Apache License 2.0 5 votes vote down vote up
package de.knutwalker.akka.stream
package support

import akka.NotUsed
import akka.stream.scaladsl.Flow
import akka.util.ByteString

import io.circe.CursorOp.DownField
import io.circe.jawn.CirceSupportParser._
import io.circe.{ CursorOp, Decoder, DecodingFailure, Encoder, HCursor, Json, Printer }
import jawn.AsyncParser

object CirceStreamSupport extends CirceStreamSupport

trait CirceStreamSupport {

  def decode[A: Decoder]: Flow[ByteString, A, NotUsed] =
    JsonStreamParser.flow[Json].map(decodeJson[A])

  def decode[A: Decoder](mode: AsyncParser.Mode): Flow[ByteString, A, NotUsed] =
    JsonStreamParser.flow[Json](mode).map(decodeJson[A])

  def encode[A](implicit A: Encoder[A], P: Printer = Printer.noSpaces): Flow[A, String, NotUsed] =
    Flow[A].map(a => P.pretty(A(a)))

  case class JsonParsingException(df: DecodingFailure, cursor: HCursor)
    extends Exception(errorMessage(df.history, cursor, df.message), df)

  private[knutwalker] def decodeJson[A](json: Json)(implicit decoder: Decoder[A]): A = {
    val cursor = json.hcursor
    decoder(cursor) match {
      case Right(e) => e
      case Left(f)  => throw JsonParsingException(f, cursor)
    }
  }


  private[this] def errorMessage(hist: List[CursorOp], cursor: HCursor, typeHint: String) = {
    val ac = cursor.replay(hist)
    if (ac.failed && lastWasDownField(hist)) {
      s"The field [${CursorOp.opsToPath(hist)}] is missing."
    } else {
      s"Could not decode [${ac.focus.getOrElse(Json.Null)}] at [${CursorOp.opsToPath(hist)}] as [$typeHint]."
    }
  }

  private[this] def lastWasDownField(hist: List[CursorOp]) = hist.headOption match {
    case Some(DownField(_)) => true
    case _                  => false
  }
} 
Example 10
Source File: CirceProducerConsumerTest.scala    From pulsar4s   with Apache License 2.0 5 votes vote down vote up
package com.sksamuel.pulsar4s.circe

import java.util.UUID

import com.sksamuel.pulsar4s._
import io.circe.generic.auto._
import io.circe.CursorOp.DownField
import io.circe.DecodingFailure
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.matchers.should.Matchers

import scala.util.Failure

class CirceProducerConsumerTest extends AnyFunSuite with Matchers {

  test("producer and consumer synchronous round trip") {

    val client = PulsarClient("pulsar://localhost:6650")
    val topic = Topic("persistent://sample/standalone/ns1/test_" + UUID.randomUUID)

    val producer = client.producer[Cafe](ProducerConfig(topic))
    val cafe = Cafe("le table", Place(1, "Paris"))
    val messageId = producer.send(cafe)
    producer.close()

    val consumer = client.consumer[Cafe](ConsumerConfig(topics = Seq(topic), subscriptionName = Subscription.generate))
    consumer.seek(MessageId.earliest)
    val msg = consumer.receive
    msg.get.value shouldBe cafe
    consumer.close()

    client.close()
  }

  test("producer and consumer synchronous round trip with failed deserialization") {

    val client = PulsarClient("pulsar://localhost:6650")
    val topic = Topic("persistent://sample/standalone/ns1/test_" + UUID.randomUUID)

    val producer = client.producer[String](ProducerConfig(topic))
    val messageId = producer.send("""{"foo": "bar"}""")
    producer.close()

    val consumer = client.consumer[Cafe](ConsumerConfig(topics = Seq(topic), subscriptionName = Subscription.generate))
    consumer.seek(MessageId.earliest)
    val msg = consumer.receive
    msg.get.valueTry shouldBe Failure(DecodingFailure("Attempt to decode value on failed cursor", List(DownField("name"))))
    consumer.close()

    client.close()
  }

} 
Example 11
Source File: MigratorConfig.scala    From scylla-migrator   with Apache License 2.0 5 votes vote down vote up
package com.scylladb.migrator.config

import cats.implicits._
import com.datastax.spark.connector.rdd.partitioner.dht.{ BigIntToken, LongToken, Token }
import io.circe.generic.semiauto.{ deriveDecoder, deriveEncoder }
import io.circe.syntax._
import io.circe.yaml.parser
import io.circe.yaml.syntax._
import io.circe.{ Decoder, DecodingFailure, Encoder, Error, Json }

case class MigratorConfig(source: SourceSettings,
                          target: TargetSettings,
                          renames: List[Rename],
                          savepoints: Savepoints,
                          skipTokenRanges: Set[(Token[_], Token[_])],
                          validation: Validation) {
  def render: String = this.asJson.asYaml.spaces2
}
object MigratorConfig {
  implicit val tokenEncoder: Encoder[Token[_]] = Encoder.instance {
    case LongToken(value)   => Json.obj("type" := "long", "value"   := value)
    case BigIntToken(value) => Json.obj("type" := "bigint", "value" := value)
  }

  implicit val tokenDecoder: Decoder[Token[_]] = Decoder.instance { cursor =>
    for {
      tpe <- cursor.get[String]("type").right
      result <- tpe match {
                 case "long"    => cursor.get[Long]("value").right.map(LongToken(_))
                 case "bigint"  => cursor.get[BigInt]("value").right.map(BigIntToken(_))
                 case otherwise => Left(DecodingFailure(s"Unknown token type '$otherwise'", Nil))
               }
    } yield result
  }

  implicit val migratorConfigDecoder: Decoder[MigratorConfig] = deriveDecoder[MigratorConfig]
  implicit val migratorConfigEncoder: Encoder[MigratorConfig] = deriveEncoder[MigratorConfig]

  def loadFrom(path: String): MigratorConfig = {
    val configData = scala.io.Source.fromFile(path).mkString

    parser
      .parse(configData)
      .leftWiden[Error]
      .flatMap(_.as[MigratorConfig])
      .valueOr(throw _)
  }
} 
Example 12
Source File: SourceSettings.scala    From scylla-migrator   with Apache License 2.0 5 votes vote down vote up
package com.scylladb.migrator.config

import cats.implicits._
import io.circe.syntax._
import io.circe.{ Decoder, DecodingFailure, Encoder, Json, ObjectEncoder }

sealed trait SourceSettings
object SourceSettings {
  case class Cassandra(host: String,
                       port: Int,
                       credentials: Option[Credentials],
                       keyspace: String,
                       table: String,
                       splitCount: Option[Int],
                       connections: Option[Int],
                       fetchSize: Int,
                       preserveTimestamps: Boolean)
      extends SourceSettings
  case class Parquet(path: String, credentials: Option[AWSCredentials]) extends SourceSettings

  implicit val decoder: Decoder[SourceSettings] = Decoder.instance { cursor =>
    cursor.get[String]("type").flatMap {
      case "cassandra" | "scylla" =>
        Decoder
          .forProduct9(
            "host",
            "port",
            "credentials",
            "keyspace",
            "table",
            "splitCount",
            "connections",
            "fetchSize",
            "preserveTimestamps")(Cassandra.apply)
          .apply(cursor)
      case "parquet" =>
        Decoder
          .forProduct2("path", "credentials")(Parquet.apply)
          .apply(cursor)
      case otherwise =>
        Left(DecodingFailure(s"Unknown source type: ${otherwise}", cursor.history))
    }
  }

  implicit val encoder: Encoder[SourceSettings] = Encoder.instance {
    case s: Cassandra =>
      Encoder
        .forProduct9(
          "host",
          "port",
          "credentials",
          "keyspace",
          "table",
          "splitCount",
          "connections",
          "fetchSize",
          "preserveTimestamps")(Cassandra.unapply(_: Cassandra).get)
        .encodeObject(s)
        .add("type", Json.fromString("cassandra"))
        .asJson
    case s: Parquet =>
      Encoder
        .forProduct2("path", "credentials")(Parquet.unapply(_: Parquet).get)
        .encodeObject(s)
        .add("type", Json.fromString("parquet"))
        .asJson
  }
} 
Example 13
Source File: EnumerationDecoder.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras.decoding

import io.circe.{ Decoder, DecodingFailure, HCursor }
import io.circe.generic.extras.Configuration
import scala.annotation.implicitNotFound
import shapeless.{ :+:, CNil, Coproduct, HNil, Inl, Inr, LabelledGeneric, Witness }
import shapeless.labelled.{ FieldType, field }

@implicitNotFound(
  """Could not find EnumerationDecoder for type ${A}.
Some possible causes for this:
- ${A} isn't a case class or sealed trat
- some of ${A}'s members don't have codecs of their own
- missing implicit Configuration"""
)
abstract class EnumerationDecoder[A] extends Decoder[A]

object EnumerationDecoder {
  implicit val decodeEnumerationCNil: EnumerationDecoder[CNil] = new EnumerationDecoder[CNil] {
    def apply(c: HCursor): Decoder.Result[CNil] = Left(DecodingFailure("Enumeration", c.history))
  }

  implicit def decodeEnumerationCCons[K <: Symbol, V, R <: Coproduct](implicit
    witK: Witness.Aux[K],
    gen: LabelledGeneric.Aux[V, HNil],
    decodeR: EnumerationDecoder[R],
    config: Configuration = Configuration.default
  ): EnumerationDecoder[FieldType[K, V] :+: R] = new EnumerationDecoder[FieldType[K, V] :+: R] {
    def apply(c: HCursor): Decoder.Result[FieldType[K, V] :+: R] =
      c.as[String] match {
        case Right(s) if s == config.transformConstructorNames(witK.value.name) =>
          Right(Inl(field[K](gen.from(HNil))))
        case Right(_) =>
          decodeR.apply(c) match {
            case Right(v)  => Right(Inr(v))
            case Left(err) => Left(err)
          }
        case Left(err) => Left(DecodingFailure("Enumeration", c.history))
      }
  }

  implicit def decodeEnumeration[A, Repr <: Coproduct](implicit
    gen: LabelledGeneric.Aux[A, Repr],
    decodeR: EnumerationDecoder[Repr]
  ): EnumerationDecoder[A] =
    new EnumerationDecoder[A] {
      def apply(c: HCursor): Decoder.Result[A] = decodeR(c) match {
        case Right(v)  => Right(gen.from(v))
        case Left(err) => Left(err)
      }
    }
} 
Example 14
Source File: ReprAsObjectCodec.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras.codec

import cats.data.Validated
import io.circe.{ Decoder, DecodingFailure, HCursor, JsonObject }
import io.circe.generic.extras.ConfigurableDeriver
import io.circe.generic.extras.decoding.ReprDecoder
import io.circe.generic.extras.encoding.ReprAsObjectEncoder
import scala.annotation.implicitNotFound
import scala.collection.immutable.Map
import scala.language.experimental.macros
import shapeless.HNil


@implicitNotFound(
  """Could not find ReprAsObjectCodec for type ${A}.
Some possible causes for this:
- ${A} isn't a case class or sealed trat
- some of ${A}'s members don't have codecs of their own
- missing implicit Configuration"""
)
abstract class ReprAsObjectCodec[A] extends ReprDecoder[A] with ReprAsObjectEncoder[A]

object ReprAsObjectCodec {
  implicit def deriveReprAsObjectCodec[R]: ReprAsObjectCodec[R] = macro ConfigurableDeriver.deriveConfiguredCodec[R]

  val hnilReprCodec: ReprAsObjectCodec[HNil] = new ReprAsObjectCodec[HNil] {
    def configuredDecode(c: HCursor)(
      transformMemberNames: String => String,
      transformConstructorNames: String => String,
      defaults: Map[String, Any],
      discriminator: Option[String]
    ): Decoder.Result[HNil] =
      if (c.value.isObject) Right(HNil) else Left(DecodingFailure("HNil", c.history))

    def configuredDecodeAccumulating(c: HCursor)(
      transformMemberNames: String => String,
      transformConstructorNames: String => String,
      defaults: Map[String, Any],
      discriminator: Option[String]
    ): Decoder.AccumulatingResult[HNil] =
      if (c.value.isObject) Validated.valid(HNil) else Validated.invalidNel(DecodingFailure("HNil", c.history))

    def configuredEncodeObject(a: HNil)(
      transformMemberNames: String => String,
      transformDiscriminator: String => String,
      discriminator: Option[String]
    ): JsonObject = JsonObject.empty
  }
} 
Example 15
Source File: EnumerationCodec.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras.codec

import io.circe.{ Codec, Decoder, DecodingFailure, HCursor, Json }
import io.circe.generic.extras.Configuration
import scala.annotation.implicitNotFound
import shapeless.{ :+:, CNil, Coproduct, HNil, Inl, Inr, LabelledGeneric, Witness }
import shapeless.labelled.{ FieldType, field }

@implicitNotFound(
  """Could not find EnumerationCodec for type ${A}.
Some possible causes for this:
- ${A} isn't a case class or sealed trat
- some of ${A}'s members don't have codecs of their own
- missing implicit Configuration"""
)
abstract class EnumerationCodec[A] extends Codec[A]

object EnumerationCodec {
  implicit val codecForEnumerationCNil: EnumerationCodec[CNil] = new EnumerationCodec[CNil] {
    def apply(c: HCursor): Decoder.Result[CNil] = Left(DecodingFailure("Enumeration", c.history))
    def apply(a: CNil): Json = sys.error("Cannot encode CNil")
  }

  implicit def codecForEnumerationCCons[K <: Symbol, V, R <: Coproduct](implicit
    witK: Witness.Aux[K],
    gen: LabelledGeneric.Aux[V, HNil],
    codecForR: EnumerationCodec[R],
    config: Configuration = Configuration.default
  ): EnumerationCodec[FieldType[K, V] :+: R] = new EnumerationCodec[FieldType[K, V] :+: R] {
    def apply(c: HCursor): Decoder.Result[FieldType[K, V] :+: R] =
      c.as[String] match {
        case Right(s) if s == config.transformConstructorNames(witK.value.name) =>
          Right(Inl(field[K](gen.from(HNil))))
        case Right(_) =>
          codecForR.apply(c) match {
            case Right(v)  => Right(Inr(v))
            case Left(err) => Left(err)
          }
        case Left(err) => Left(DecodingFailure("Enumeration", c.history))
      }
    def apply(a: FieldType[K, V] :+: R): Json = a match {
      case Inl(l) => Json.fromString(config.transformConstructorNames(witK.value.name))
      case Inr(r) => codecForR(r)
    }
  }

  implicit def codecForEnumeration[A, R <: Coproduct](implicit
    gen: LabelledGeneric.Aux[A, R],
    codecForR: EnumerationCodec[R]
  ): EnumerationCodec[A] =
    new EnumerationCodec[A] {
      def apply(c: HCursor): Decoder.Result[A] = codecForR(c) match {
        case Right(v)  => Right(gen.from(v))
        case Left(err) => Left(err)
      }
      def apply(a: A): Json = codecForR(gen.to(a))
    }
} 
Example 16
Source File: PermissionsRoutes.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.routes

import akka.http.javadsl.server.Rejections._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.iam.config.AppConfig.HttpConfig
import ch.epfl.bluebrain.nexus.iam.directives.AuthDirectives.authenticator
import ch.epfl.bluebrain.nexus.iam.marshallers.instances._
import ch.epfl.bluebrain.nexus.iam.permissions.Permissions
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions
import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions.{Append, Replace, Subtract}
import ch.epfl.bluebrain.nexus.iam.types.ResourceF._
import ch.epfl.bluebrain.nexus.iam.types.{Caller, Permission}
import io.circe.{Decoder, DecodingFailure}
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global


class PermissionsRoutes(permissions: Permissions[Task], realms: Realms[Task])(implicit http: HttpConfig) {

  def routes: Route =
    (pathPrefix("permissions") & pathEndOrSingleSlash) {
      operationName(s"/${http.prefix}/permissions") {
        authenticateOAuth2Async("*", authenticator(realms)).withAnonymousUser(Caller.anonymous) { implicit caller =>
          concat(
            get {
              parameter("rev".as[Long].?) {
                case Some(rev) => complete(permissions.fetchAt(rev).runNotFound)
                case None      => complete(permissions.fetch.runToFuture)
              }
            },
            (put & parameter("rev" ? 0L)) { rev =>
              entity(as[PatchPermissions]) {
                case Replace(set) =>
                  complete(permissions.replace(set, rev).runToFuture)
                case _ => reject(validationRejection("Only @type 'Replace' is permitted when using 'put'."))
              }
            },
            delete {
              parameter("rev".as[Long]) { rev =>
                complete(permissions.delete(rev).runToFuture)
              }
            },
            (patch & parameter("rev" ? 0L)) { rev =>
              entity(as[PatchPermissions]) {
                case Append(set) =>
                  complete(permissions.append(set, rev).runToFuture)
                case Subtract(set) =>
                  complete(permissions.subtract(set, rev).runToFuture)
                case _ =>
                  reject(validationRejection("Only @type 'Append' or 'Subtract' is permitted when using 'patch'."))
              }
            }
          )
        }
      }
    }
}

object PermissionsRoutes {

  private[routes] sealed trait PatchPermissions extends Product with Serializable

  private[routes] object PatchPermissions {

    final case class Append(permissions: Set[Permission])   extends PatchPermissions
    final case class Subtract(permissions: Set[Permission]) extends PatchPermissions
    final case class Replace(permissions: Set[Permission])  extends PatchPermissions

    implicit val patchPermissionsDecoder: Decoder[PatchPermissions] =
      Decoder.instance { hc =>
        for {
          permissions <- hc.get[Set[Permission]]("permissions")
          tpe = hc.get[String]("@type").getOrElse("Replace")
          patch <- tpe match {
            case "Replace"  => Right(Replace(permissions))
            case "Append"   => Right(Append(permissions))
            case "Subtract" => Right(Subtract(permissions))
            case _          => Left(DecodingFailure("@type field must have Append or Subtract value", hc.history))
          }
        } yield patch
      }
  }

} 
Example 17
Source File: Caller.scala    From nexus-iam   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.client.types

import ch.epfl.bluebrain.nexus.iam.client.types.Identity._
import io.circe.{Decoder, DecodingFailure}


  val anonymous: Caller = Caller(Anonymous: Subject, Set[Identity](Anonymous))

  final implicit val callerDecoder: Decoder[Caller] =
    Decoder.instance { cursor =>
      cursor
        .get[Set[Identity]]("identities")
        .flatMap { identities =>
          identities.collectFirst { case u: User => u } orElse identities.collectFirst { case Anonymous => Anonymous } match {
            case Some(subject: Subject) => Right(Caller(subject, identities))
            case _ =>
              val pos = cursor.downField("identities").history
              Left(DecodingFailure("Unable to find a subject in the collection of identities", pos))
          }
        }
    }
} 
Example 18
Source File: MLFlowModelSpec.scala    From ForestFlow   with Apache License 2.0 5 votes vote down vote up
package ai.forestflow.serving.MLFlow

import ai.forestflow.serving.impl.{LocalFileArtifactReader, MLFlowH2OLoader, UnsupportedServableFlavor}
import ai.forestflow.serving.interfaces.{ArtifactReader, Loader}
import cats.syntax.either._
import ai.forestflow.serving.impl.{LocalFileArtifactReader, MLFlowH2OLoader, UnsupportedServableFlavor}
import ai.forestflow.serving.interfaces.ArtifactReader
import ai.forestflow.utils.SourceStorageProtocols
import io.circe.generic.extras._
import io.circe.generic.extras.semiauto.deriveDecoder
import io.circe.{CursorOp, Decoder, DecodingFailure}
import ai.forestflow.serving.interfaces.Loader
import ai.forestflow.utils.ThrowableImplicits._
import org.joda.time.{DateTimeZone, LocalDateTime}


case class MLFlowModelSpec(
  artifactReader: ArtifactReader,

  runId: Option[String],

  timeCreated: Long,

  flavors: Map[String, Loader]
) {
  def getServableFlavor: Option[(String, Loader)] = flavors.collectFirst { case (flavor, loader) if !loader.isInstanceOf[UnsupportedServableFlavor] => (flavor, loader) }
}

object MLFlowModelSpec {

  implicit val config: Configuration = {
    val baseConfig = Configuration.default.withSnakeCaseMemberNames
    baseConfig.copy(transformMemberNames = baseConfig.transformMemberNames andThen {
      // from snake_case in class to snake_case file
      case "artifact_reader" => "artifact_path"
      case "time_created" => "utc_time_created" // utc_time_created is a string!
      case other => other
    })
  }

  implicit val decodeTimeCreated: Decoder[Long] = Decoder.decodeString.emap{ tm: String =>
    Either.catchNonFatal[Long]({
      var ts = tm.replace(" ", "T")
      if (ts.takeRight(1) != "Z")
        ts = ts + "Z"
      val ll = LocalDateTime.parse(tm.replace(" ", "T")).toDateTime(DateTimeZone.UTC)
      ll.getMillis
    }
    ).leftMap(t => s"timeCreated Decoder Failed: ${t.printableStackTrace}")
  }.handleErrorWith(_ => Decoder.decodeLong)

  implicit val decodeMLFlowModel: Decoder[MLFlowModelSpec] = deriveDecoder[MLFlowModelSpec]

  implicit val decodeArtifactReaderString: Decoder[ArtifactReader] = Decoder.decodeOption[String].emap { artifactPath: Option[String] =>
    Either.catchNonFatal[ArtifactReader]({
      artifactPath match {
        case Some(path) => ArtifactReader.getArtifactReader(path)
        case _ => LocalFileArtifactReader("")
      }
    }
    ).leftMap(t => s"Artifact Reader Decoder Failed: ${t.printableStackTrace}")
  }

  implicit val decodeServableFlavor: Decoder[Map[String, Loader]] = Decoder.decodeMap[String, Map[String, String]].emap { flavors =>
    Either.catchNonFatal[Map[String, Loader]](
      flavors
        .map { case (flavor, props) => (flavor.toLowerCase, props) }
        .map {
          case (f@"h2o_mojo", props) => f -> MLFlowH2OLoader(dataPath = props.getOrElse("data", ""), version = props.get("h2o_version"))
          
          case (f, props) => f -> UnsupportedServableFlavor(props)
          case (f, props) => throw DecodingFailure(s"Unexpected or unsupported flavor type [$f] with props $props", List[CursorOp]())
          // TODO: Support POJO?
          // case (f, _) => p -> BasicSourceProvider()
        }
    ).leftMap(t => t.printableStackTrace)

  }

} 
Example 19
Source File: IamIdentitiesClient.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.storage

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.client.RequestBuilding.Get
import akka.http.scaladsl.model.HttpRequest
import akka.http.scaladsl.model.headers.OAuth2BearerToken
import akka.http.scaladsl.unmarshalling.FromEntityUnmarshaller
import akka.util.ByteString
import cats.effect.{ContextShift, Effect, IO}
import cats.implicits._
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.storage.IamIdentitiesClient.Identity._
import ch.epfl.bluebrain.nexus.storage.IamIdentitiesClient._
import ch.epfl.bluebrain.nexus.storage.IamIdentitiesClientError.IdentitiesSerializationError
import ch.epfl.bluebrain.nexus.storage.config.IamClientConfig
import de.heikoseeberger.akkahttpcirce.ErrorAccumulatingCirceSupport.{DecodingFailures => AccDecodingFailures}
import io.circe.Decoder.Result
import io.circe.{Decoder, DecodingFailure, HCursor}

import scala.concurrent.ExecutionContext

class IamIdentitiesClient[F[_]](config: IamClientConfig)(implicit F: Effect[F], as: ActorSystem)
    extends JsonLdCirceSupport {

  private val um: FromEntityUnmarshaller[Caller]      = unmarshaller[Caller]
  implicit private val ec: ExecutionContext           = as.dispatcher
  implicit private val contextShift: ContextShift[IO] = IO.contextShift(ec)

  def apply()(implicit credentials: Option[AccessToken]): F[Caller] =
    credentials match {
      case Some(token) => execute(Get(config.identitiesIri.asAkka).addCredentials(OAuth2BearerToken(token.value)))
      case None        => F.pure(Caller.anonymous)
    }

  private def execute(req: HttpRequest): F[Caller] = {
    IO.fromFuture(IO(Http().singleRequest(req))).to[F].flatMap { resp =>
      if (resp.status.isSuccess())
        IO.fromFuture(IO(um(resp.entity))).to[F].recoverWith {
          case err: AccDecodingFailures => F.raiseError(IdentitiesSerializationError(err.getMessage))
          case err: Error               => F.raiseError(IdentitiesSerializationError(err.getMessage))
        }
      else
        IO.fromFuture(IO(resp.entity.dataBytes.runFold(ByteString(""))(_ ++ _).map(_.utf8String)))
          .to[F]
          .flatMap { err => F.raiseError(IamIdentitiesClientError.unsafe(resp.status, err)) }
    }
  }

}

object IamIdentitiesClient {

  
    final case class Authenticated(realm: String) extends Identity

    private def decodeAnonymous(hc: HCursor): Result[Subject] =
      hc.get[String]("@type").flatMap {
        case "Anonymous" => Right(Anonymous)
        case _           => Left(DecodingFailure("Cannot decode Anonymous Identity", hc.history))
      }

    private def decodeUser(hc: HCursor): Result[Subject] =
      (hc.get[String]("subject"), hc.get[String]("realm")).mapN {
        case (subject, realm) => User(subject, realm)
      }

    private def decodeGroup(hc: HCursor): Result[Identity] =
      (hc.get[String]("group"), hc.get[String]("realm")).mapN {
        case (group, realm) => Group(group, realm)
      }

    private def decodeAuthenticated(hc: HCursor): Result[Identity] =
      hc.get[String]("realm").map(Authenticated)

    private val attempts =
      List[HCursor => Result[Identity]](decodeAnonymous, decodeUser, decodeGroup, decodeAuthenticated)

    implicit val identityDecoder: Decoder[Identity] =
      Decoder.instance { hc =>
        attempts.foldLeft(Left(DecodingFailure("Unexpected", hc.history)): Result[Identity]) {
          case (acc @ Right(_), _) => acc
          case (_, f)              => f(hc)
        }
      }
  }

} 
Example 20
Source File: PermissionsRoutes.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.iam.routes

import akka.http.javadsl.server.Rejections._
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.Route
import ch.epfl.bluebrain.nexus.iam.acls.Acls
import ch.epfl.bluebrain.nexus.iam.permissions.Permissions
import ch.epfl.bluebrain.nexus.iam.realms.Realms
import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions
import ch.epfl.bluebrain.nexus.iam.routes.PermissionsRoutes.PatchPermissions.{Append, Replace, Subtract}
import ch.epfl.bluebrain.nexus.iam.types.Permission
import ch.epfl.bluebrain.nexus.iam.types.ResourceF._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import ch.epfl.bluebrain.nexus.service.directives.AuthDirectives
import ch.epfl.bluebrain.nexus.service.marshallers.instances._
import io.circe.{Decoder, DecodingFailure}
import kamon.instrumentation.akka.http.TracingDirectives.operationName
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global


class PermissionsRoutes(permissions: Permissions[Task], acls: Acls[Task], realms: Realms[Task])(implicit
    http: HttpConfig
) extends AuthDirectives(acls, realms) {

  def routes: Route =
    (pathPrefix("permissions") & pathEndOrSingleSlash) {
      operationName(s"/${http.prefix}/permissions") {
        extractCaller { implicit caller =>
          concat(
            get {
              parameter("rev".as[Long].?) {
                case Some(rev) => complete(permissions.fetchAt(rev).runNotFound)
                case None      => complete(permissions.fetch.runToFuture)
              }
            },
            (put & parameter("rev" ? 0L)) { rev =>
              entity(as[PatchPermissions]) {
                case Replace(set) =>
                  complete(permissions.replace(set, rev).runToFuture)
                case _            => reject(validationRejection("Only @type 'Replace' is permitted when using 'put'."))
              }
            },
            delete {
              parameter("rev".as[Long]) { rev => complete(permissions.delete(rev).runToFuture) }
            },
            (patch & parameter("rev" ? 0L)) { rev =>
              entity(as[PatchPermissions]) {
                case Append(set)   =>
                  complete(permissions.append(set, rev).runToFuture)
                case Subtract(set) =>
                  complete(permissions.subtract(set, rev).runToFuture)
                case _             =>
                  reject(validationRejection("Only @type 'Append' or 'Subtract' is permitted when using 'patch'."))
              }
            }
          )
        }
      }
    }
}

object PermissionsRoutes {

  sealed private[routes] trait PatchPermissions extends Product with Serializable

  private[routes] object PatchPermissions {

    final case class Append(permissions: Set[Permission])   extends PatchPermissions
    final case class Subtract(permissions: Set[Permission]) extends PatchPermissions
    final case class Replace(permissions: Set[Permission])  extends PatchPermissions

    implicit val patchPermissionsDecoder: Decoder[PatchPermissions] =
      Decoder.instance { hc =>
        for {
          permissions <- hc.get[Set[Permission]]("permissions")
          tpe          = hc.get[String]("@type").getOrElse("Replace")
          patch       <- tpe match {
                           case "Replace"  => Right(Replace(permissions))
                           case "Append"   => Right(Append(permissions))
                           case "Subtract" => Right(Subtract(permissions))
                           case _          => Left(DecodingFailure("@type field must have Append or Subtract value", hc.history))
                         }
        } yield patch
      }
  }

} 
Example 21
Source File: ProjectDescription.scala    From nexus   with Apache License 2.0 5 votes vote down vote up
package ch.epfl.bluebrain.nexus.admin.projects

import ch.epfl.bluebrain.nexus.rdf.Iri
import ch.epfl.bluebrain.nexus.rdf.Iri.AbsoluteIri
import ch.epfl.bluebrain.nexus.rdf.implicits._
import ch.epfl.bluebrain.nexus.service.config.ServiceConfig.HttpConfig
import io.circe.{Decoder, DecodingFailure}


  def vocabOrGenerated(organization: String, label: String)(implicit http: HttpConfig): Option[AbsoluteIri] =
    vocab orElse Iri.absolute(s"${http.prefixIri.asString}/vocabs/$organization/$label/").toOption
}

object ProjectDescription {

  final case class Mapping(prefix: String, namespace: AbsoluteIri)

  implicit val mappingDecoder: Decoder[Mapping] = Decoder.instance { hc =>
    for {
      prefix    <- hc.downField("prefix").as[String]
      namespace <- hc.downField("namespace").as[String]
      iri       <- Iri.absolute(namespace).left.map(err => DecodingFailure(err, hc.history))
    } yield Mapping(prefix, iri)
  }

  implicit val descriptionDecoder: Decoder[ProjectDescription] = Decoder.instance { hc =>
    for {
      desc <- hc.downField("description").as[Option[String]]
      lam   = hc.downField("apiMappings").as[List[Mapping]].getOrElse(List.empty)
      map   = lam.map(am => am.prefix -> am.namespace).toMap
      base <- hc.downField("base").as[Option[AbsoluteIri]]
      voc  <- hc.downField("vocab").as[Option[AbsoluteIri]]
    } yield ProjectDescription(desc, map, base, voc)
  }
} 
Example 22
Source File: parser.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.buildtool.mill

import cats.implicits._
import io.circe.{Decoder, DecodingFailure}
import org.scalasteward.core.data.{ArtifactId, Dependency, GroupId, Resolver}

object parser {
  sealed trait ParseError extends RuntimeException {
    def message: String

    final override def getMessage: String = message
  }
  case class CirceParseError(message: String, cause: io.circe.Error) extends ParseError {
    final override def getCause: Throwable = cause
  }

  def parseModules[F[_]](
      input: String
  ): Either[ParseError, List[MillModule]] =
    for {
      json <-
        io.circe.parser
          .decode[Modules](input)
          .leftMap(CirceParseError("Failed to decode Modules", _): ParseError)
    } yield json.modules

}

case class Modules(modules: List[MillModule])
object Modules {
  implicit val decoder: Decoder[Modules] = Decoder.forProduct1("modules")(apply)
}

case class MillModule(name: String, repositories: List[Resolver], dependencies: List[Dependency])

object MillModule {
  val resolverDecoder: Decoder[Resolver] = Decoder.instance { c =>
    c.downField("type").as[String].flatMap {
      case "maven" =>
        for {
          url <- c.downField("url").as[String]
          creds <- c.downField("auth").as[Option[Resolver.Credentials]]
        } yield Resolver.MavenRepository(url, url, creds)
      case "ivy" =>
        for {
          url <- c.downField("pattern").as[String]
          creds <- c.downField("auth").as[Option[Resolver.Credentials]]
        } yield Resolver.IvyRepository(url, url, creds)
      case typ => Left(DecodingFailure(s"Not a matching resolver type, $typ", c.history))
    }
  }

  val dependencyDecoder: Decoder[Dependency] = Decoder.instance { c =>
    for {
      groupId <- c.downField("groupId").as[GroupId]
      artifactId <- c.downField("artifactId").as[String].map(aid => ArtifactId(aid, None))
      version <- c.downField("version").as[String]
    } yield Dependency(groupId, artifactId, version)
  }

  implicit val decoder: Decoder[MillModule] = Decoder.instance(c =>
    for {
      name <- c.downField("name").as[String]
      resolvers <- c.downField("repositories").as(Decoder.decodeList(resolverDecoder))
      dependencies <- c.downField("dependencies").as(Decoder.decodeList(dependencyDecoder))
    } yield MillModule(name, resolvers, dependencies)
  )
} 
Example 23
Source File: RepositoryResponse.scala    From scala-steward   with Apache License 2.0 5 votes vote down vote up
package org.scalasteward.core.bitbucket.http4s

import cats.implicits._
import io.circe.{ACursor, Decoder, DecodingFailure, Json}
import org.http4s.Uri
import org.scalasteward.core.git.Branch
import org.scalasteward.core.util.uri._
import org.scalasteward.core.vcs.data.{Repo, UserOut}
import scala.annotation.tailrec

final private[http4s] case class RepositoryResponse(
    name: String,
    mainBranch: Branch,
    owner: UserOut,
    httpsCloneUrl: Uri,
    parent: Option[Repo]
)

private[http4s] object RepositoryResponse {
  implicit private val repoDecoder: Decoder[Repo] = Decoder.instance { c =>
    c.as[String].map(_.split('/')).flatMap { parts =>
      parts match {
        case Array(owner, name) => Repo(owner, name).asRight
        case _                  => DecodingFailure("Repo", c.history).asLeft
      }
    }
  }

  implicit val decoder: Decoder[RepositoryResponse] = Decoder.instance { c =>
    for {
      name <- c.downField("name").as[String]
      owner <-
        c.downField("owner")
          .downField("username")
          .as[String]
          .orElse(c.downField("owner").downField("nickname").as[String])
      cloneUrl <-
        c.downField("links")
          .downField("clone")
          .downAt { p =>
            p.asObject
              .flatMap(o => o("name"))
              .flatMap(_.asString)
              .contains("https")
          }
          .downField("href")
          .as[Uri]
      defaultBranch <- c.downField("mainbranch").downField("name").as[Branch]
      maybeParent <- c.downField("parent").downField("full_name").as[Option[Repo]]
    } yield RepositoryResponse(name, defaultBranch, UserOut(owner), cloneUrl, maybeParent)
  }

  
    def downAt(p: Json => Boolean): ACursor = {
      @tailrec
      def find(c: ACursor): ACursor =
        if (c.succeeded)
          if (c.focus.exists(p)) c else find(c.right)
        else c

      find(cursor.downArray)
    }
  }
} 
Example 24
Source File: JWSSerializer.scala    From tsec   with MIT License 5 votes vote down vote up
package tsec.jws

import io.circe.{DecodingFailure, Error}
import org.apache.commons.codec.binary.Base64
import tsec.common.NonFatal

trait JWSSerializer[A] {
  def serializeToUtf8(body: A): Array[Byte]
  def fromUtf8Bytes(array: Array[Byte]): Either[Error, A]
  def toB64URL(elem: A): String = Base64.encodeBase64URLSafeString(serializeToUtf8(elem))
  def fromB64URL(encoded: String): Either[Error, A] =
    try {
      fromUtf8Bytes(Base64.decodeBase64(encoded))
    } catch {
      case t: Throwable if NonFatal(t) =>
        Left(DecodingFailure("Invalid encoding", Nil))
    }
} 
Example 25
Source File: package.scala    From kanadi   with MIT License 5 votes vote down vote up
package org.zalando

import java.net.URI
import cats.syntax.either._
import io.circe.Decoder.Result
import io.circe.syntax._
import io.circe.{Decoder, DecodingFailure, Encoder, HCursor}
import scala.util.control.NonFatal

package object kanadi {
  private[kanadi] implicit val uriEncoder: Encoder[URI] =
    Encoder.instance[URI](_.toString.asJson)

  private[kanadi] implicit val uriDecoder: Decoder[URI] = new Decoder[URI] {
    override def apply(c: HCursor): Result[URI] =
      c.as[String].flatMap { value =>
        try {
          Right(new URI(value))
        } catch {
          case NonFatal(_) => Left(DecodingFailure("Invalid Uri", c.history))
        }
      }
  }
} 
Example 26
Source File: Transaction.scala    From scarango   with MIT License 5 votes vote down vote up
package com.outr.arango.transaction

import com.outr.arango.Graph
import io.circe.Decoder.Result
import io.circe.{Decoder, DecodingFailure, HCursor}

import scala.concurrent.{ExecutionContext, Future}

case class Transaction(id: String, status: TransactionStatus) {
  private[arango] var graph: Option[Graph] = None

  def withGraph(option: Option[Graph]): Transaction = {
    graph = option
    this
  }

  def checkStatus()(implicit ec: ExecutionContext): Future[Transaction] = {
    val g = graph.getOrElse(throw new RuntimeException("Graph not included!"))
    g.arangoDatabase.transactionStatus(id).map(_.withGraph(graph))
  }

  def commit()(implicit ec: ExecutionContext): Future[Unit] = {
    val g = graph.getOrElse(throw new RuntimeException("Graph not included!"))
    g.arangoDatabase.transactionCommit(id).map { t =>
      t.status match {
        case TransactionStatus.Running => throw new RuntimeException("Commit failed, transaction still running!")
        case TransactionStatus.Committed => ()
        case TransactionStatus.Aborted => throw new RuntimeException("Commit failed, transaction aborted!")
      }
    }
  }

  def abort()(implicit ec: ExecutionContext): Future[Unit] = {
    val g = graph.getOrElse(throw new RuntimeException("Graph not included!"))
    g.arangoDatabase.transactionAbort(id).map { t =>
      t.status match {
        case TransactionStatus.Running => throw new RuntimeException("Abort failed, transaction still running!")
        case TransactionStatus.Committed => throw new RuntimeException("Abort failed, transaction committed!")
        case TransactionStatus.Aborted => ()
      }
    }
  }
} 
Example 27
Source File: TransactionStatus.scala    From scarango   with MIT License 5 votes vote down vote up
package com.outr.arango.transaction

import io.circe.Decoder.Result
import io.circe.{Decoder, DecodingFailure, HCursor}

sealed trait TransactionStatus

object TransactionStatus {
  case object Running extends TransactionStatus
  case object Committed extends TransactionStatus
  case object Aborted extends TransactionStatus

  implicit val decoder: Decoder[TransactionStatus] = new Decoder[TransactionStatus] {
    override def apply(c: HCursor): Result[TransactionStatus] = c.value.asString match {
      case Some(s) => Right(TransactionStatus(s))
      case None => Left(DecodingFailure(s"Failed to decode from ${c.value}", Nil))
    }
  }

  def apply(value: String): TransactionStatus = value match {
    case "running" => Running
    case "committed" => Committed
    case "aborted" => Aborted
  }
} 
Example 28
Source File: APIWalTail.scala    From scarango   with MIT License 5 votes vote down vote up
package com.outr.arango.api

import io.circe.Decoder.Result
import io.youi.client.HttpClient
import io.youi.http.{HeaderKey, HttpMethod}
import io.youi.net._
import io.circe.{Decoder, DecodingFailure, HCursor}
import profig.JsonUtil

import scala.concurrent.{ExecutionContext, Future}
      
object APIWalTail {
  private implicit def operationTypeDecoder: Decoder[OperationType] = new Decoder[OperationType] {
    override def apply(c: HCursor): Result[OperationType] = c.value.asNumber match {
      case Some(n) => Right(OperationType(n.toInt.get))
      case None => Left(DecodingFailure(s"OperationType not a number: ${c.value}", Nil))
    }
  }

  def get(client: HttpClient,
          global: Option[Boolean] = None,
          from: Option[Long] = None,
          to: Option[Long] = None,
          lastScanned: Long = 0L,
          chunkSize: Option[Long] = None,
          syncerId: Option[Long] = None,
          serverId: Option[Long] = None,
          clientId: Option[String] = None)(implicit ec: ExecutionContext): Future[WALOperations] = {
    client
      .method(HttpMethod.Get)
      .path(path"/_api/wal/tail", append = true)
      .param[Option[Long]]("from", from, None)
      .param[Option[Long]]("to", to, None)
      .param[Long]("lastScanned", lastScanned, 0L)
      .param[Option[Boolean]]("global", global, None)
      .param[Option[Long]]("chunkSize", chunkSize, None)
      .param[Option[Long]]("syncerId", syncerId, None)
      .param[Option[Long]]("serverId", serverId, None)
      .param[Option[String]]("clientId", clientId, None)
      .send()
      .map { response =>
        val lines = response.content.map(_.asString).getOrElse("").split('\n').toList
        val operations = lines.map(_.trim).collect {
          case line if line.nonEmpty => JsonUtil.fromJsonString[WALOperation](line)
        }
        val headers = response.headers
        WALOperations(
          client = client,
          global = global,
          chunkSize = chunkSize,
          syncerId = syncerId,
          serverId = serverId,
          clientId = clientId,
          checkMore = headers.first(HeaderKey("X-Arango-Replication-Checkmore")).exists(_.toBoolean),
          fromPresent = headers.first(HeaderKey("X-Arango-Replication-Frompresent")).exists(_.toBoolean),
          lastIncluded = headers.first(HeaderKey("X-Arango-Replication-Lastincluded")).map(_.toLong).getOrElse(-1L),
          lastScanned = headers.first(HeaderKey("X-Arango-Replication-Lastscanned")).map(_.toLong).getOrElse(-1L),
          lastTick = headers.first(HeaderKey("X-Arango-Replication-Lasttick")).map(_.toLong).getOrElse(-1L),
          operations = operations
        )
      }
  }
}