Skip to content

Commit

Permalink
ConfGet: define generic getOrElse method
Browse files Browse the repository at this point in the history
  • Loading branch information
kitbellew committed Nov 29, 2024
1 parent 8346986 commit 8369af9
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 11 deletions.
7 changes: 3 additions & 4 deletions metaconfig-core/shared/src/main/scala/metaconfig/Conf.scala
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ object Conf {
})
def getOption[T](path: String, extraNames: String*)(implicit
ev: ConfDecoder[T],
): Configured[Option[T]] = ConfGet.getKey(this, path +: extraNames)
.map(ev.read(_).map(Some(_))).getOrElse(Configured.Ok(None))
): Configured[Option[T]] = ConfGet
.getOrOK(this, path +: extraNames, ev.read(_).map(Some.apply), None)
}
object Obj {
type Elem = (String, Conf)
Expand All @@ -112,8 +112,7 @@ object Conf {

def getEx[A](state: A, conf: Conf, path: Seq[String])(implicit
ev: ConfDecoderEx[A],
): Configured[A] = ConfGet.getKey(conf, path)
.fold(Configured.ok(state))(ev.read(Some(state), _))
): Configured[A] = ConfGet.getOrOK(conf, path, ev.read(Some(state), _), state)

def getSettingEx[A: ConfDecoderEx](
state: A,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package metaconfig

import scala.language.implicitConversions
import scala.util.Failure
import scala.util.Success

Expand Down Expand Up @@ -94,6 +95,9 @@ object Configured extends ConfiguredLowPriorityImplicits {
def combine(other: NotOk): NotOk = combine(other.error)
}

implicit def errorToNotOK(error: ConfError): Configured.NotOk = Configured
.NotOk(error)

implicit class ConfiguredImplicit[A](value: Configured[A]) {

def getOrRecover(fa: ConfError => A): A = fold(fa)(identity)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,21 @@ import scala.annotation.tailrec
import scala.collection.mutable

object ConfGet {
def getKey(conf: Conf, keys: Seq[String]): Option[Conf] = conf match {
case obj: Conf.Obj => getKey(obj, keys)
case _ => None
def getOrElse[A](
some: Conf => Configured[A],
none: => Configured[A],
)(conf: Conf, keys: Seq[String]): Configured[A] = conf match {
case obj: Conf.Obj => getKey(obj, keys).fold(none)(some)
case _ => none
}

def getOrOK[A](
conf: Conf,
keys: Seq[String],
some: Conf => Configured[A],
none: => A,
): Configured[A] = getOrElse(some, Configured.ok(none))(conf, keys)

@tailrec
private def getKey(obj: Conf.Obj, keys: Seq[String]): Option[Conf] =
keys.headOption match {
Expand All @@ -27,15 +37,16 @@ object ConfGet {

def getOrElse[T](conf: Conf, default: T, keys: Seq[String])(implicit
ev: ConfDecoder[T],
): Configured[T] = getKey(conf, keys).fold(Configured.ok(default))(ev.read)
): Configured[T] = getOrOK(conf, keys, ev.read, default)

def get[T](conf: Conf, path: String, extraNames: String*)(implicit
ev: ConfDecoder[T],
): Configured[T] = conf match {
case obj: Conf.Obj => getKey(obj, path +: extraNames).map(ev.read)
.getOrElse(ConfError.missingField(obj, path).notOk)
case obj: Conf.Obj => getOrElse(ev.read, ConfError.missingField(obj, path))(
obj,
path +: extraNames,
)
case _ => ConfError.typeMismatch(s"Conf.Obj with field $path", conf, path)
.notOk
}

def getNested[T](conf: Conf, keys: String*)(implicit
Expand Down

0 comments on commit 8369af9

Please sign in to comment.