CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-jetbrains-kotlin--kotlin-stdlib-wasm-wasi

Kotlin Standard Library implementation for WebAssembly System Interface (WASI) platform providing essential I/O, time, random, UUID, and reflection capabilities.

Pending
Overview
Eval results
Files

uuid.mddocs/

UUID Generation

Overview

The UUID Generation capabilities provide cryptographically secure UUID creation using WASI's secure random number generation. This implementation creates Version 4 (random) UUIDs that are suitable for use as unique identifiers in distributed systems and security-sensitive applications.

API Reference

UUID Creation

/**
 * UUID companion object with WASI-specific random UUID generation.
 */
@ExperimentalUuidApi
object Uuid.Companion {
    /**
     * Generates a random UUID (Version 4) using cryptographically secure random data.
     * Uses WASI's random_get system call for entropy.
     * @return a new random UUID
     */
    @ExperimentalUuidApi
    fun random(): Uuid
}

UUID Class

/**
 * Represents a UUID (Universally Unique Identifier).
 */
class Uuid {
    /**
     * The most significant 64 bits of this UUID.
     */
    val mostSignificantBits: Long
    
    /**
     * The least significant 64 bits of this UUID.
     */
    val leastSignificantBits: Long
    
    /**
     * Returns the string representation of this UUID.
     * @return UUID string in standard format (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)
     */
    override fun toString(): String
    
    /**
     * Compares this UUID with the specified UUID.
     * @param other the UUID to compare with
     * @return true if the UUIDs are equal, false otherwise
     */
    override fun equals(other: Any?): Boolean
    
    /**
     * Returns the hash code for this UUID.
     * @return the hash code value
     */
    override fun hashCode(): Int
}

Usage Examples

Basic UUID Generation

// Generate random UUIDs
val uuid1 = Uuid.random()
val uuid2 = Uuid.random()
val uuid3 = Uuid.random()

println("UUID 1: $uuid1")
println("UUID 2: $uuid2") 
println("UUID 3: $uuid3")

// Example output:
// UUID 1: f47ac10b-58cc-4372-a567-0e02b2c3d479
// UUID 2: 6ba7b810-9dad-11d1-80b4-00c04fd430c8
// UUID 3: 886313e1-3b8a-5372-9b90-5c5fdffd6c6f

UUID Properties

val uuid = Uuid.random()

// Access internal bits
val msb = uuid.mostSignificantBits
val lsb = uuid.leastSignificantBits

println("Most significant bits: $msb")
println("Least significant bits: $lsb")
println("String representation: $uuid")

// UUID equality and hashing
val uuid1 = Uuid.random()
val uuid2 = Uuid.random()

println("UUIDs equal: ${uuid1 == uuid2}") // false (extremely unlikely)
println("UUID1 hash: ${uuid1.hashCode()}")
println("UUID2 hash: ${uuid2.hashCode()}")

Using UUIDs as Identifiers

// Entity identification
data class User(
    val id: Uuid = Uuid.random(),
    val name: String,
    val email: String
)

val user = User(name = "Alice", email = "alice@example.com")
println("User ID: ${user.id}")

// Session management
class SessionManager {
    private val sessions = mutableMapOf<Uuid, SessionData>()
    
    fun createSession(userId: String): Uuid {
        val sessionId = Uuid.random()
        sessions[sessionId] = SessionData(userId, System.currentTimeMillis())
        return sessionId
    }
    
    fun getSession(sessionId: Uuid): SessionData? {
        return sessions[sessionId]
    }
}

data class SessionData(val userId: String, val createdAt: Long)

UUID Collections

// UUIDs as map keys
val userProfiles = mutableMapOf<Uuid, UserProfile>()

val userId1 = Uuid.random()
val userId2 = Uuid.random()

userProfiles[userId1] = UserProfile("Alice", 30)
userProfiles[userId2] = UserProfile("Bob", 25)

// UUIDs in sets
val activeUserIds = mutableSetOf<Uuid>()
activeUserIds.add(userId1)
activeUserIds.add(userId2)

println("Active users: ${activeUserIds.size}")

// UUID lists for ordered collections
val eventIds = mutableListOf<Uuid>()
repeat(5) { eventIds.add(Uuid.random()) }

eventIds.forEach { id ->
    println("Event ID: $id")
}

Request Tracing

// Distributed tracing with UUIDs
class RequestTracer {
    private val traceId = Uuid.random()
    private val spans = mutableListOf<TraceSpan>()
    
    fun startSpan(operation: String): TraceSpan {
        val span = TraceSpan(
            spanId = Uuid.random(),
            traceId = traceId,
            operation = operation,
            startTime = System.currentTimeMillis()
        )
        spans.add(span)
        return span
    }
    
    fun getTrace(): TraceData {
        return TraceData(traceId, spans.toList())
    }
}

data class TraceSpan(
    val spanId: Uuid,
    val traceId: Uuid,
    val operation: String,
    val startTime: Long,
    var endTime: Long? = null
)

data class TraceData(val traceId: Uuid, val spans: List<TraceSpan>)

// Usage
val tracer = RequestTracer()
val dbSpan = tracer.startSpan("database_query")
// ... perform database operation ...
dbSpan.endTime = System.currentTimeMillis()

val serviceSpan = tracer.startSpan("external_service_call")
// ... call external service ...
serviceSpan.endTime = System.currentTimeMillis()

val trace = tracer.getTrace()
println("Trace ID: ${trace.traceId}")
trace.spans.forEach { span ->
    println("  Span: ${span.operation} (${span.spanId})")
}

Database Entity IDs

// Database entity with UUID primary key
data class Product(
    val id: Uuid = Uuid.random(),
    val name: String,
    val price: Double,
    val categoryId: Uuid
) {
    fun toMap(): Map<String, Any> = mapOf(
        "id" to id.toString(),
        "name" to name,
        "price" to price,
        "category_id" to categoryId.toString()
    )
}

// Repository pattern with UUIDs
class ProductRepository {
    private val products = mutableMapOf<Uuid, Product>()
    
    fun save(product: Product): Product {
        products[product.id] = product
        return product
    }
    
    fun findById(id: Uuid): Product? {
        return products[id]
    }
    
    fun findAll(): List<Product> {
        return products.values.toList()
    }
    
    fun deleteById(id: Uuid): Boolean {
        return products.remove(id) != null
    }
}

// Usage
val repository = ProductRepository()
val categoryId = Uuid.random()

val product = Product(
    name = "Laptop",
    price = 999.99,
    categoryId = categoryId
)

repository.save(product)
val retrieved = repository.findById(product.id)
println("Retrieved product: $retrieved")

Implementation Details

UUID Version 4 Specification

The WASI implementation generates Version 4 (random) UUIDs according to RFC 4122:

  • 122 random bits: 122 bits are randomly generated
  • Version bits: 4 bits set to version 4 (0100)
  • Variant bits: 2 bits set to variant 10
  • Format: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx where y is 8, 9, A, or B

Cryptographic Security

UUID generation uses WASI's cryptographically secure random number generator:

// Internal implementation uses secure random bytes
val randomBytes = ByteArray(16)
wasiRawRandomGet(randomBytes) // Cryptographically secure

// Set version and variant bits according to RFC 4122
randomBytes[6] = (randomBytes[6].toInt() and 0x0F or 0x40).toByte() // Version 4
randomBytes[8] = (randomBytes[8].toInt() and 0x3F or 0x80).toByte() // Variant 10

Uniqueness Guarantees

Version 4 UUIDs provide strong uniqueness guarantees:

  • Collision Probability: Approximately 1 in 2^122 for random UUIDs
  • Practical Uniqueness: Suitable for distributed systems without coordination
  • Timeline Independence: No dependency on system clocks or MAC addresses

String Representation

UUIDs are formatted according to the standard representation:

  • 36 characters: 32 hexadecimal digits plus 4 hyphens
  • Lowercase: Hexadecimal digits are lowercase (a-f)
  • Fixed positions: Hyphens at positions 8, 13, 18, and 23

Performance Considerations

Generation Performance

// Efficient: Batch generation when possible
val uuids = mutableListOf<Uuid>()
repeat(1000) {
    uuids.add(Uuid.random()) // Each call may use cached random data
}

// Consider pre-generating UUIDs for high-frequency use
class UuidPool {
    private val pool = mutableListOf<Uuid>()
    
    init {
        refill()
    }
    
    fun get(): Uuid {
        if (pool.isEmpty()) refill()
        return pool.removeAt(pool.size - 1)
    }
    
    private fun refill() {
        repeat(100) { pool.add(Uuid.random()) }
    }
}

Memory Efficiency

  • Fixed Size: Each UUID instance uses 16 bytes for storage
  • Immutable: UUID instances are immutable, reducing memory management overhead
  • String Caching: String representation may be cached internally

Comparison Performance

// UUID equality is fast (compares two longs)
val uuid1 = Uuid.random()
val uuid2 = Uuid.random()
val equal = uuid1 == uuid2 // Fast bit comparison

// Hash code computation is efficient
val hashCode = uuid1.hashCode() // XOR of high and low bits

Best Practices

When to Use UUIDs

UUIDs are ideal for:

  • Distributed Systems: No central authority needed for ID generation
  • Database Primary Keys: Especially in sharded or replicated databases
  • API Identifiers: Public-facing resource identifiers
  • Security Tokens: Session IDs, API keys, temporary tokens
  • Event Tracking: Correlation IDs for logging and tracing

Security Considerations

// DO: Use random UUIDs for security-sensitive applications
val sessionId = Uuid.random() // Cryptographically secure

// DON'T: Use predictable patterns for security tokens
// val badId = "user_${System.currentTimeMillis()}" // Predictable

// DO: Treat UUIDs as opaque identifiers
val resourceId = Uuid.random()
// Use only for identification, not for encoding information

// DON'T: Store sensitive information in UUID format
// Uuid.fromString("secret_${password}_data") // Not actually supported

Performance Optimization

// For high-throughput applications, consider pooling
class OptimizedIdGenerator {
    companion object {
        private val pool = ThreadLocal.withInitial { UuidPool() }
        
        fun nextId(): Uuid = pool.get().get()
    }
}

// Use string representation efficiently
val uuid = Uuid.random()
val idString = uuid.toString() // Cache if used frequently

Database Integration

// Store UUIDs as strings in databases for broad compatibility
fun saveUser(user: User) {
    val query = "INSERT INTO users (id, name, email) VALUES (?, ?, ?)"
    // Convert UUID to string for database storage
    executeQuery(query, user.id.toString(), user.name, user.email)
}

// Parse UUIDs from database strings
fun loadUser(idString: String): User? {
    val uuid = Uuid.fromString(idString) // If supported by implementation
    // Or parse manually if needed
    return findUserById(uuid)
}

Install with Tessl CLI

npx tessl i tessl/maven-org-jetbrains-kotlin--kotlin-stdlib-wasm-wasi

docs

console-io.md

exceptions.md

index.md

random.md

reflection.md

time.md

uuid.md

tile.json