Last active
August 29, 2015 14:07
-
-
Save tixxit/aa92ea6a3eea7f600f10 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
a = "abc" | |
xyz { | |
x = 1 | |
y = "xyz" | |
z = 2.3 | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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")) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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