Skip to content

Instantly share code, notes, and snippets.

@tixxit
Last active August 29, 2015 14:07
Show Gist options
  • Save tixxit/aa92ea6a3eea7f600f10 to your computer and use it in GitHub Desktop.
Save tixxit/aa92ea6a3eea7f600f10 to your computer and use it in GitHub Desktop.
{
a = "abc"
xyz {
x = 1
y = "xyz"
z = 2.3
}
}
case class Abc(a: String, xyz: Xyz)
case class Xyz(x: Int, y: String, z: Double)
val abc: Option[Abc] = Configurator.validate[Abc](ConfigFactory.load().getConfig("abc"))
package snippets.cfg
import com.typesafe.config._
import shapeless._
import shapeless.labelled._
trait ConfigValue[A] {
def validate(config: Config, path: String): Option[A]
}
object ConfigValue {
def apply[A](f: (Config, String) => Option[A]): ConfigValue[A] =
new ConfigValue[A] {
def validate(config: Config, path: String): Option[A] = f(config, path)
}
def fromTryCatch[A](f: (Config, String) => A): ConfigValue[A] =
ConfigValue { (cfg, path) =>
try {
Some(f(cfg, path))
} catch {
case (_: ConfigException) => None
}
}
implicit val IntConfigValue = ConfigValue.fromTryCatch(_ getInt _)
implicit val LongConfigValue = ConfigValue.fromTryCatch(_ getLong _)
implicit val DoubleConfigValue = ConfigValue.fromTryCatch(_ getDouble _)
implicit val StringConfigValue = ConfigValue.fromTryCatch(_ getString _)
implicit def configuratorConfigValue[A: Configurator]: ConfigValue[A] =
ConfigValue((cfg, path) => Configurator.validate(cfg.getConfig(path)))
}
trait Configurator[A] {
def validate(config: Config): Option[A]
}
trait ConfiguratorLow {
implicit def genericConfigurator[A, L <: HList](implicit
gen: LabelledGeneric.Aux[A, L],
configurator: Configurator[L]): Configurator[A] =
new Configurator[A] {
def validate(config: Config): Option[A] =
configurator.validate(config).map(gen.from)
}
}
object Configurator extends ConfiguratorLow {
def apply[A](implicit cfg: Configurator[A]): Configurator[A] = cfg
def validate[A](config: Config)(implicit c: Configurator[A]): Option[A] =
c.validate(config)
implicit val hnilConfigurator: Configurator[HNil] =
new Configurator[HNil] {
def validate(config: Config): Option[HNil] = Some(HNil)
}
implicit def hlistConfigurator[T <: HList, K <: Symbol, H](implicit
tailConfigurator: Configurator[T],
witness: Witness.Aux[K],
configValue: ConfigValue[H]): Configurator[FieldType[K, H] :: T] =
new Configurator[FieldType[K, H] :: T] {
def validate(config: Config): Option[FieldType[K, H] :: T] = for {
head <- configValue.validate(config, witness.value.name)
tail <- tailConfigurator.validate(config)
} yield {
field[K](head) :: tail
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment