Android Code Snippet [B4X] GenerateULID (+ LongToBytes48 + EncodeBase32)

ULID (Universally Unique Lexicographically Sortable Identifier)

A ULID is a 128‑bit globally unique identifier designed to be both universally unique and lexicographically sortable

It consists of a 48‑bit timestamp (in milliseconds) followed by 80 bits of randomness. Because the timestamp is encoded first, ULIDs naturally sort in chronological order when compared as strings. This makes them ideal for distributed systems, databases, synchronization logic, and any scenario where both uniqueness and temporal ordering are importan

ULIDs are more readable than UUIDs and avoid collisions even when generated on multiple devices.

B4X:
'Return an ULID = 48-bit timestamp + 80-bit randomness
' (Timestamp = ms since 01/01/1970 (48-bit))
Public Sub GenerateULID As String
'USES: LongToBytes48 and EncodeBase32.

    Dim ts As Long = DateTime.Now
    Dim tsBytes() As Byte = LongToBytes48(ts)
   
    ' Randomness = 10 bytes (80-bit)
    Dim rndBytes(10) As Byte
    For i = 0 To 9
        rndBytes(i) = Rnd(0, 256)
    Next
   
    ' Concatenate timestamp + randomness
    Dim all(16) As Byte
    For i = 0 To 5
        all(i) = tsBytes(i)
    Next
    For i = 0 To 9
        all(6 + i) = rndBytes(i)
    Next
   
    ' Encode using Crockford Base32 (unambiguous)
    Return EncodeBase32(all)
End Sub


' ============================
'   Convert Long → 48-bit
' ============================
Private Sub LongToBytes48(l As Long) As Byte()
    Dim b(6) As Byte
    For i = 5 To 0 Step -1
        b(i) = Bit.And(l, 0xFF)
        l = Bit.UnsignedShiftRight(l, 8)
    Next
    Return b
End Sub


' ============================
'   Crockford Base32
' ============================
Private Sub EncodeBase32(data() As Byte) As String
    Dim alphabet As String = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
    Dim bits As Long = 0
    Dim bitCount As Int = 0
    Dim out As StringBuilder
    out.Initialize
   
    For Each b As Byte In data
        bits = Bit.Or(Bit.ShiftLeft(bits, 8), Bit.And(b, 0xFF))
        bitCount = bitCount + 8
       
        Do While bitCount >= 5
            bitCount = bitCount - 5
            Dim index As Int = Bit.And(Bit.UnsignedShiftRight(bits, bitCount), 31)
            out.Append(alphabet.CharAt(index))
        Loop
    Next
   
    If bitCount > 0 Then
        Dim index As Int = Bit.And(Bit.ShiftLeft(bits, (5 - bitCount)), 31)
        out.Append(alphabet.CharAt(index))
    End If
   
    Return out.ToString
End Sub
 
Last edited:
Top