Skip to content

Commit

Permalink
ConfGet: turn getKey into tail-recursive
Browse files Browse the repository at this point in the history
  • Loading branch information
kitbellew committed Jun 6, 2021
1 parent 1460cad commit 9f3c857
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 29 deletions.
9 changes: 4 additions & 5 deletions metaconfig-core/shared/src/main/scala/metaconfig/Conf.scala
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ object Conf {
): Configured[Option[T]] =
ConfGet
.getKey(this, path +: extraNames)
.map(value => ev.read(value).map(Some(_)))
.map(ev.read(_).map(Some(_)))
.getOrElse(Configured.Ok(None))
}
object Obj {
Expand All @@ -118,10 +118,9 @@ object Conf {
def getEx[A](state: A, conf: Conf, path: Seq[String])(
implicit ev: ConfDecoderEx[A]
): Configured[A] =
ConfGet.getKey(conf, path) match {
case None => Configured.Ok(state)
case Some(subconf) => ev.read(Some(state), subconf)
}
ConfGet
.getKey(conf, path)
.fold(Configured.ok(state))(ev.read(Some(state), _))

def getSettingEx[A](state: A, conf: Conf, setting: Setting)(
implicit ev: ConfDecoderEx[A]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,46 +1,47 @@
package metaconfig.internal

import scala.annotation.tailrec
import scala.collection.mutable
import metaconfig.Conf
import metaconfig.ConfDecoder
import metaconfig.ConfError
import metaconfig.Configured

object ConfGet {
def getKey(obj: Conf, keys: Seq[String]): Option[Conf] =
def getKey(conf: Conf, keys: Seq[String]): Option[Conf] =
if (keys.isEmpty) None
else {
obj match {
case obj @ Conf.Obj(_) =>
obj.values
.collectFirst { case (key, value) if key == keys.head => value }
.orElse(getKey(obj, keys.tail))
else
conf match {
case obj: Conf.Obj => getKey(obj, keys)
case _ => None
}
}

@tailrec
private def getKey(obj: Conf.Obj, keys: Seq[String]): Option[Conf] =
if (keys.isEmpty) None
else
obj.values.collectFirst { case (key, value) if key == keys.head => value } match {
case x: Some[_] => x
case _ => getKey(obj, keys.tail)
}

def getOrElse[T](conf: Conf, default: T, path: String, extraNames: String*)(
implicit ev: ConfDecoder[T]
): Configured[T] = {
getKey(conf, path +: extraNames) match {
case Some(value) => ev.read(value)
case None => Configured.Ok(default)
}
}
): Configured[T] =
getKey(conf, path +: extraNames).fold(Configured.ok(default))(ev.read)

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

Expand Down

0 comments on commit 9f3c857

Please sign in to comment.