aboutsummaryrefslogtreecommitdiff
path: root/core-types/src
diff options
context:
space:
mode:
Diffstat (limited to 'core-types/src')
-rw-r--r--core-types/src/main/scala/xyz/driver/core/core.scala52
-rw-r--r--core-types/src/test/scala/xyz/driver/core/CoreTest.scala77
2 files changed, 128 insertions, 1 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
index 67ac5ee..d88bf09 100644
--- a/core-types/src/main/scala/xyz/driver/core/core.scala
+++ b/core-types/src/main/scala/xyz/driver/core/core.scala
@@ -54,7 +54,15 @@ package object core {
package core {
- final case class Id[+Tag](value: String) extends AnyVal {
+ import java.util.UUID
+
+ sealed trait GenericId[+Tag, IdType] extends Any {
+ def value: IdType
+ def length: Int
+ def toString: String
+ }
+
+ final case class Id[+Tag](value: String) extends AnyVal with GenericId[Tag, String] {
@inline def length: Int = value.length
override def toString: String = value
}
@@ -75,6 +83,48 @@ package core {
implicit def convertER[E, R](id: Id[E])(implicit mapper: Mapper[E, R]): Id[R] = mapper[R](id)
}
+ final case class UuidId[+Tag](value: UUID) extends AnyVal with GenericId[Tag, UUID] {
+ @inline def length: Int = value.toString.length
+ override def toString: String = value.toString
+ }
+
+ @SuppressWarnings(Array("org.wartremover.warts.ImplicitConversion"))
+ object UuidId {
+ implicit def idEqual[T]: Equal[UuidId[T]] = Equal.equal[UuidId[T]](_ == _)
+ implicit def idOrdering[T]: Ordering[UuidId[T]] = Ordering.by[UuidId[T], UUID](_.value)
+
+ sealed class Mapper[E, R] {
+ def apply[T >: E](id: UuidId[R]): UuidId[T] = UuidId[E](id.value)
+ def apply[T >: R](id: UuidId[E])(implicit dummy: DummyImplicit): UuidId[T] = UuidId[R](id.value)
+ }
+ object Mapper {
+ def apply[E, R] = new Mapper[E, R]
+ }
+ implicit def convertRE[R, E](id: UuidId[R])(implicit mapper: Mapper[E, R]): UuidId[E] = mapper[E](id)
+ implicit def convertER[E, R](id: UuidId[E])(implicit mapper: Mapper[E, R]): UuidId[R] = mapper[R](id)
+ }
+
+ final case class NumericId[+Tag](value: Long) extends AnyVal with GenericId[Tag, Long] {
+ @inline def length: Int = value.toString.length
+ override def toString: String = value.toString
+ }
+
+ @SuppressWarnings(Array("org.wartremover.warts.ImplicitConversion"))
+ object NumericId {
+ implicit def idEqual[T]: Equal[NumericId[T]] = Equal.equal[NumericId[T]](_ == _)
+ implicit def idOrdering[T]: Ordering[NumericId[T]] = Ordering.by[NumericId[T], Long](_.value)
+
+ sealed class Mapper[E, R] {
+ def apply[T >: E](id: NumericId[R]): NumericId[T] = NumericId[E](id.value)
+ def apply[T >: R](id: NumericId[E])(implicit dummy: DummyImplicit): NumericId[T] = NumericId[R](id.value)
+ }
+ object Mapper {
+ def apply[E, R] = new Mapper[E, R]
+ }
+ implicit def convertRE[R, E](id: NumericId[R])(implicit mapper: Mapper[E, R]): NumericId[E] = mapper[E](id)
+ implicit def convertER[E, R](id: NumericId[E])(implicit mapper: Mapper[E, R]): NumericId[R] = mapper[R](id)
+ }
+
final case class Name[+Tag](value: String) extends AnyVal {
@inline def length: Int = value.length
override def toString: String = value
diff --git a/core-types/src/test/scala/xyz/driver/core/CoreTest.scala b/core-types/src/test/scala/xyz/driver/core/CoreTest.scala
index f448d24..1cd7a7c 100644
--- a/core-types/src/test/scala/xyz/driver/core/CoreTest.scala
+++ b/core-types/src/test/scala/xyz/driver/core/CoreTest.scala
@@ -1,6 +1,7 @@
package xyz.driver.core
import java.io.ByteArrayOutputStream
+import java.util.UUID
import org.mockito.Mockito._
import org.scalatest.mockito.MockitoSugar
@@ -64,6 +65,82 @@ class CoreTest extends FlatSpec with Matchers with MockitoSugar {
(xid: Id[X]) should be(zid: Id[Z])
}
+ "UuidId" should "have equality and ordering working correctly" in {
+ val uuidId1 = UuidId[String](UUID.fromString("ceec8358-cfa4-4e62-b601-1ba1f615f22f"))
+ val uuidId2 = UuidId[String](UUID.fromString("1e761cbe-a5e0-4570-a503-818d14a2b322"))
+ val uuidId3 = UuidId[String](UUID.fromString("326b2342-78b3-4ad4-8cbc-115e74019c39"))
+ val uuidId4 = UuidId[String](UUID.fromString("46e38513-2117-45d9-a5df-1d899052fbb6"))
+
+ (uuidId1 === UuidId[String](UUID.fromString("ceec8358-cfa4-4e62-b601-1ba1f615f22f"))) should be(true)
+ (uuidId1 === uuidId2) should be(false)
+ (uuidId2 === uuidId1) should be(false)
+
+ val ids = Seq(uuidId1, uuidId4, uuidId3, uuidId2)
+ val sorted = Seq(uuidId1, uuidId2, uuidId3, uuidId4)
+
+ ids.sorted should contain theSameElementsInOrderAs sorted
+ }
+
+ it should "have type-safe conversions" in {
+ final case class X(id: UuidId[X])
+ final case class Y(id: UuidId[Y])
+ final case class Z(id: UuidId[Z])
+
+ implicit val xy = UuidId.Mapper[X, Y]
+ implicit val yz = UuidId.Mapper[Y, Z]
+
+ // Test that implicit conversions work correctly
+ val x = X(UuidId(UUID.fromString("00000000-0000-0000-0000-00000000")))
+ val y = Y(x.id)
+ val z = Z(y.id)
+ val y2 = Y(z.id)
+ val x2 = X(y2.id)
+ (x2 === x) should be(true)
+ (y2 === y) should be(true)
+
+ // Test that type inferrence for explicit conversions work correctly
+ val yid = y.id
+ val xid = xy(yid)
+ val zid = yz(yid)
+ (xid: UuidId[X]) should be(zid: UuidId[Z])
+ }
+
+ "NumericId" should "have equality and ordering working correctly" in {
+
+ (NumericId[Long](1234213) === NumericId[Long](1234213)) should be(true)
+ (NumericId[Long](1234213) === NumericId[Long](213414)) should be(false)
+ (NumericId[Long](213414) === NumericId[Long](1234213)) should be(false)
+
+ val ids = Seq(NumericId[Long](4), NumericId[Long](3), NumericId[Long](2), NumericId[Long](1))
+ val sorted = Seq(NumericId[Long](1), NumericId[Long](2), NumericId[Long](3), NumericId[Long](4))
+
+ ids.sorted should contain theSameElementsInOrderAs sorted
+ }
+
+ it should "have type-safe conversions" in {
+ final case class X(id: NumericId[X])
+ final case class Y(id: NumericId[Y])
+ final case class Z(id: NumericId[Z])
+
+ implicit val xy = NumericId.Mapper[X, Y]
+ implicit val yz = NumericId.Mapper[Y, Z]
+
+ // Test that implicit conversions work correctly
+ val x = X(NumericId(0))
+ val y = Y(x.id)
+ val z = Z(y.id)
+ val y2 = Y(z.id)
+ val x2 = X(y2.id)
+ (x2 === x) should be(true)
+ (y2 === y) should be(true)
+
+ // Test that type inferrence for explicit conversions work correctly
+ val yid = y.id
+ val xid = xy(yid)
+ val zid = yz(yid)
+ (xid: NumericId[X]) should be(zid: NumericId[Z])
+ }
+
"Name" should "have equality and ordering working correctly" in {
(Name[String]("foo") === Name[String]("foo")) should be(true)