Skip to content

Instantly share code, notes, and snippets.

@afiore
Created December 10, 2016 16:31
Show Gist options
  • Save afiore/d7689fa3c7bfa4f0266814de6b43f1d4 to your computer and use it in GitHub Desktop.
Save afiore/d7689fa3c7bfa4f0266814de6b43f1d4 to your computer and use it in GitHub Desktop.
FromConfig.scala
package swag
import com.typesafe.config.Config
import shapeless._
import shapeless.labelled._
object FromConfig {
sealed trait Error
//case class FieldMissing(fieldName: String) extends Error
//case class WrongType(fieldName: String) extends Error
def instance[A](f: String => Config => A) = new FromConfig[A] {
override def read(path: String)(implicit conf: Config): A = f(path)(conf)
}
implicit val strConfig: FromConfig[String] = instance(path => conf => conf.getString(path) )
implicit val intConfig: FromConfig[Int] = instance(path => conf => conf.getInt(path) )
implicit val fromConfigHNil: FromConfig[HNil] = instance(path => conf => HNil)
implicit def fromConfigHlist[K <: Symbol, H, T <: HList](implicit witness: Witness.Aux[K],
hDec: FromConfig[H],
tDec: FromConfig[T])
: FromConfig[FieldType[K, H] :: T] = instance { path => implicit conf =>
val hName = witness.value.name
val h = field[K](hDec.read(path + "." + hName))
val t = tDec.read(path)
h :: t
}
implicit def fromConfigGen[A,B](implicit gen: LabelledGeneric.Aux[A, B],
bDec: FromConfig[B]): FromConfig[A] = instance { path => implicit conf =>
gen.from(bDec.read(path))
}
def read[A: FromConfig](root: String, conf: Config): A =
implicitly[FromConfig[A]].read(root)(conf)
}
trait FromConfig[A] {
def read(path: String)(implicit conf: Config): A
}
package swag
import com.typesafe.config.ConfigFactory
case class ServerConf(host: String, port: Int)
object Main extends App {
val conf = ConfigFactory.parseString(
"""
server {
port = 8080
host = example.com
}
""".stripMargin)
val sc = FromConfig.read[ServerConf]("server", conf)
println(sc)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment