diff options
author | Jakob Odersky <jakob@driver.xyz> | 2018-09-12 15:56:41 -0700 |
---|---|---|
committer | Jakob Odersky <jakob@odersky.com> | 2018-10-09 16:19:39 -0700 |
commit | 7a793ffa068fda8f2146f84fa785328d928dba03 (patch) | |
tree | d489b0b9ebf30ca61e2b6ef1c9906b704bc1fa1e /core-types/src/main/scala/xyz/driver/core/core.scala | |
parent | 2cef01adfe3ebd3a0fa1e0bbbba7f6388198ba10 (diff) | |
download | driver-core-7a793ffa068fda8f2146f84fa785328d928dba03.tar.gz driver-core-7a793ffa068fda8f2146f84fa785328d928dba03.tar.bz2 driver-core-7a793ffa068fda8f2146f84fa785328d928dba03.zip |
Move core types into core-types project
Note that xyz.driver.core.FutureExtensions was moved to
xyz.driver.core.rest as it (only) contained logic that dealt with
service exceptions, something that belongs into core-rest and must not
be depended upon by core-types.
This is a breaking change.
Diffstat (limited to 'core-types/src/main/scala/xyz/driver/core/core.scala')
-rw-r--r-- | core-types/src/main/scala/xyz/driver/core/core.scala | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/core-types/src/main/scala/xyz/driver/core/core.scala b/core-types/src/main/scala/xyz/driver/core/core.scala new file mode 100644 index 0000000..67ac5ee --- /dev/null +++ b/core-types/src/main/scala/xyz/driver/core/core.scala @@ -0,0 +1,114 @@ +package xyz.driver + +import eu.timepit.refined.api.{Refined, Validate} +import eu.timepit.refined.collection.NonEmpty +import scalaz.{Equal, Monad, OptionT} +import xyz.driver.core.tagging.Tagged + +// TODO: this package seems too complex, look at all the features we need! +import scala.language.{higherKinds, implicitConversions, reflectiveCalls} + +package object core { + + def make[T](v: => T)(f: T => Unit): T = { + val value = v + f(value) + value + } + + def using[R <: { def close() }, P](r: => R)(f: R => P): P = { + val resource = r + try { + f(resource) + } finally { + resource.close() + } + } + + type @@[+V, +Tag] = V with Tagged[V, Tag] + + implicit class OptionTExtensions[H[_]: Monad, T](optionTValue: OptionT[H, T]) { + + def returnUnit: H[Unit] = optionTValue.fold[Unit](_ => (), ()) + + def continueIgnoringNone: OptionT[H, Unit] = + optionTValue.map(_ => ()).orElse(OptionT.some[H, Unit](())) + + def subflatMap[B](f: T => Option[B]): OptionT[H, B] = + OptionT.optionT[H](implicitly[Monad[H]].map(optionTValue.run)(_.flatMap(f))) + } + + implicit class MonadicExtensions[H[_]: Monad, T](monadicValue: H[T]) { + private implicit val monadT = implicitly[Monad[H]] + + def returnUnit: H[Unit] = monadT(monadicValue)(_ => ()) + + def toOptionT: OptionT[H, T] = + OptionT.optionT[H](monadT(monadicValue)(value => Option(value))) + + def toUnitOptionT: OptionT[H, Unit] = + OptionT.optionT[H](monadT(monadicValue)(_ => Option(()))) + } + +} + +package core { + + final case class Id[+Tag](value: String) extends AnyVal { + @inline def length: Int = value.length + override def toString: String = value + } + + @SuppressWarnings(Array("org.wartremover.warts.ImplicitConversion")) + object Id { + implicit def idEqual[T]: Equal[Id[T]] = Equal.equal[Id[T]](_ == _) + implicit def idOrdering[T]: Ordering[Id[T]] = Ordering.by[Id[T], String](_.value) + + sealed class Mapper[E, R] { + def apply[T >: E](id: Id[R]): Id[T] = Id[E](id.value) + def apply[T >: R](id: Id[E])(implicit dummy: DummyImplicit): Id[T] = Id[R](id.value) + } + object Mapper { + def apply[E, R] = new Mapper[E, R] + } + implicit def convertRE[R, E](id: Id[R])(implicit mapper: Mapper[E, R]): Id[E] = mapper[E](id) + implicit def convertER[E, R](id: Id[E])(implicit mapper: Mapper[E, R]): Id[R] = mapper[R](id) + } + + final case class Name[+Tag](value: String) extends AnyVal { + @inline def length: Int = value.length + override def toString: String = value + } + + object Name { + implicit def nameEqual[T]: Equal[Name[T]] = Equal.equal[Name[T]](_ == _) + implicit def nameOrdering[T]: Ordering[Name[T]] = Ordering.by(_.value) + + implicit def nameValidator[T, P](implicit stringValidate: Validate[String, P]): Validate[Name[T], P] = { + Validate.instance[Name[T], P, stringValidate.R]( + name => stringValidate.validate(name.value), + name => stringValidate.showExpr(name.value)) + } + } + + final case class NonEmptyName[+Tag](value: String Refined NonEmpty) { + @inline def length: Int = value.value.length + override def toString: String = value.value + } + + object NonEmptyName { + implicit def nonEmptyNameEqual[T]: Equal[NonEmptyName[T]] = + Equal.equal[NonEmptyName[T]](_.value.value == _.value.value) + + implicit def nonEmptyNameOrdering[T]: Ordering[NonEmptyName[T]] = Ordering.by(_.value.value) + } + + final case class Revision[T](id: String) + + object Revision { + implicit def revisionEqual[T]: Equal[Revision[T]] = Equal.equal[Revision[T]](_.id == _.id) + } + + final case class Base64(value: String) + +} |