import scala.util.Try /** * Type-safe UUID wrapper that encodes the type it relates to. This class explicitly hides its * UUID value to prevent converting it between types. */ class UUID[A] private(private val uuid: UUID.Raw) { override def toString = uuid.toString } object UUID { type Raw = java.util.UUID def fromRaw[A](uuid: Raw): UUID[A] = new UUID(uuid) def gen[A](): UUID[A] = fromRaw(java.util.UUID.randomUUID()) def genRaw(): java.util.UUID = java.util.UUID.randomUUID() def fromString[A](s: String): Either[String, UUID[A]] = fromStringRaw(s).right.map(fromRaw) def fromStringRaw(s: String): Either[String, java.util.UUID] = { Try { java.util.UUID.fromString(s) }.toOption.toRight(s"Invalid UUID string: $s") } def unsafeFromString[A](s: String): UUID[A] = fromRaw(unsafeFromStringRaw(s)) def unsafeFromStringRaw(s: String): Raw = fromStringRaw(s).fold({ e => throw new RuntimeException(e) }, identity) }