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

ciris.ConfigEntry.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017-2021 Viktor Lövgren
 *
 * SPDX-License-Identifier: MIT
 */

package ciris

import cats.{Applicative, Eq, Eval, Show, Traverse}
import cats.implicits._
import ciris.ConfigEntry._

private[ciris] sealed abstract class ConfigEntry[+A] {
  def error: ConfigError

  final def map[B](f: A => B): ConfigEntry[B] =
    this match {
      case Default(error, a)     => Default(error, f(a))
      case failed @ Failed(_)    => failed
      case Loaded(error, key, a) => Loaded(error, key, f(a))
    }

  final def mapError(f: ConfigError => ConfigError): ConfigEntry[A] =
    this match {
      case Default(error, a)     => Default(f(error), a)
      case Failed(error)         => Failed(f(error))
      case Loaded(error, key, a) => Loaded(f(error), key, a)
    }

  final def traverse[F[_], B](f: A => F[B])(implicit F: Applicative[F]): F[ConfigEntry[B]] =
    this match {
      case Default(error, a)     => f(a).map(Default(error, _))
      case failed @ Failed(_)    => F.pure(failed)
      case Loaded(error, key, a) => f(a).map(Loaded(error, key, _))
    }
}

private[ciris] object ConfigEntry {
  final def default[A](value: A): ConfigEntry[A] =
    Default(ConfigError.Empty, value)

  final def failed[A](error: ConfigError): ConfigEntry[A] =
    Failed(error)

  final def loaded[A](key: Option[ConfigKey], value: A): ConfigEntry[A] =
    Loaded(ConfigError.Loaded, key, value)

  final case class Default[A](error: ConfigError, value: A) extends ConfigEntry[A] {
    override final def hashCode: Int =
      (error, value).hashCode

    override final def equals(that: Any): Boolean =
      that match {
        case Default(thatError, thatValue) =>
          error == thatError && value == thatValue
        case _ =>
          false
      }

    override final def toString: String =
      s"Default($error, ${value})"
  }

  final case class Failed(error: ConfigError) extends ConfigEntry[Nothing] {
    override final def toString: String =
      s"Failed($error)"
  }

  final case class Loaded[A](error: ConfigError, key: Option[ConfigKey], value: A)
      extends ConfigEntry[A] {

    override final def toString: String =
      s"Loaded($error, $key, $value)"
  }

  implicit final def configEntryEq[A](implicit eq: Eq[A]): Eq[ConfigEntry[A]] =
    Eq.instance {
      case (Default(e1, v1), Default(e2, v2))       => e1 === e2 && eq.eqv(v1, v2)
      case (Default(_, _), _)                       => false
      case (Failed(e1), Failed(e2))                 => e1 === e2
      case (Failed(_), _)                           => false
      case (Loaded(e1, k1, v1), Loaded(e2, k2, v2)) => e1 === e2 && k1 === k2 && eq.eqv(v1, v2)
      case (Loaded(_, _, _), _)                     => false
    }

  implicit final def configEntryShow[A](implicit show: Show[A]): Show[ConfigEntry[A]] =
    Show.show {
      case Default(error, value)     => show"Default($error, ${value})"
      case Failed(error)             => show"Failed($error)"
      case Loaded(error, key, value) => show"Loaded($error, $key, $value)"
    }

  implicit final val configEntryTraverse: Traverse[ConfigEntry] =
    new Traverse[ConfigEntry] {
      override final def foldLeft[A, B](entry: ConfigEntry[A], b: B)(f: (B, A) => B): B =
        entry match {
          case Default(_, a)   => f(b, a)
          case Failed(_)       => b
          case Loaded(_, _, a) => f(b, a)
        }

      override final def foldRight[A, B](entry: ConfigEntry[A], eb: Eval[B])(
        f: (A, Eval[B]) => Eval[B]
      ): Eval[B] =
        entry match {
          case Default(_, a)   => f(a, eb)
          case Failed(_)       => eb
          case Loaded(_, _, a) => f(a, eb)
        }

      override final def map[A, B](entry: ConfigEntry[A])(f: A => B): ConfigEntry[B] =
        entry.map(f)

      override final def traverse[G[_]: Applicative, A, B](
        entry: ConfigEntry[A]
      )(f: A => G[B]): G[ConfigEntry[B]] =
        entry.traverse(f)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy