Skip to content

Instantly share code, notes, and snippets.

@andersonsp
Created August 5, 2020 18:46
Show Gist options
  • Save andersonsp/b60ba52cb42fc21d2cf3f12c31efe8fe to your computer and use it in GitHub Desktop.
Save andersonsp/b60ba52cb42fc21d2cf3f12c31efe8fe to your computer and use it in GitHub Desktop.
Simple Binary ULID implementation in Scala
package io.andersonsp.ulid
import scala.util.{Failure, Success, Try}
import java.security.SecureRandom
// The components are encoded as 16 octets. Each component is encoded with the Most Significant Byte first (network byte order).
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | 32_bit_uint_time_high |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | 16_bit_uint_time_low | 16_bit_uint_random |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | 32_bit_uint_random |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | 32_bit_uint_random |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
class ULIDGenerator {
private val random = SecureRandom.getInstance("NativePRNGNonBlocking")
def generate: ULID = {
val time = System.currentTimeMillis()
ULID((time << 16) | (random.nextLong & 0xFFFF), random.nextLong)
}
}
case class ULID(msb: Long, lsb: Long) extends Ordered[ULID] {
def toBytes: Array[Byte] = java.nio.ByteBuffer.allocate(ULID.Length).putLong(msb).putLong(lsb).array()
def timestamp: Long = msb >>> 16
override def compare(that: ULID): Int = {
if (msb == that.msb) {
lsb.compareTo(that.lsb)
} else {
msb.compareTo(that.msb)
}
}
}
object ULID {
val Length = 16
def fromBytes(bytes: Array[Byte]): Try[ULID] = {
if (bytes.length != Length) {
Failure(new IllegalArgumentException("Binary ULID must be 16 bytes long"))
} else {
val buf = java.nio.ByteBuffer.wrap(bytes)
val msb = buf.getLong
val lsb = buf.getLong
Success(ULID(msb, lsb))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment