How to encode and decode any string into Base‑36 in Scala

1 Answer

0 votes
import java.nio.charset.StandardCharsets

object Base36Codec {

  /**
   * Encodes a plain text string into a Base-36 representation.
   * * Algorithm:
   * 1. Convert the string's underlying bytes into an arbitrary-precision BigInt.
   * 2. Leverage BigInt's built-in radix conversion `.toString(36)` to map to Base-36 digits.
   */
  def encodeToBase36(text: String): String = {
    if (text.isEmpty) return ""
    
    // Convert string to bytes (UTF-8 guarantees cross-platform safety)
    val bytes = text.getBytes(StandardCharsets.UTF_8)
    
    // Treat the byte array as a positive magnitude BigInt (using signum = 1)
    val bigInt = BigInt(1, bytes)
    
    // Scala's BigInt provides built-in radix formatting up to base 36
    bigInt.toString(36).toUpperCase
  }

  /**
   * Decodes a Base-36 string back into its original text.
   * * Algorithm:
   * 1. Initialize a BigInt with the base-36 string representation.
   * 2. Extract the underlying byte array and drop any leading zero bytes padding added by the sign bit.
   */
  def decodeFromBase36(encoded: String): String = {
    if (encoded.isEmpty) return ""
    
    // Parse the base-36 string back into a BigInt using the standard radix parameter
    val bigInt = BigInt(encoded.toLowerCase, 36)
    
    // toByteArray returns a signed big-endian complement array.
    val rawBytes = bigInt.toByteArray
    
    // If the leading byte is 0, it was an artificial sign padding added by BigInteger.
    // We clean it up so the original raw string bytes remain unaltered.
    val cleanBytes = if (rawBytes.headOption.contains(0) && rawBytes.length > 1) {
      rawBytes.tail
    } else {
      rawBytes
    }
    
    new String(cleanBytes, StandardCharsets.UTF_8)
  }

  def main(args: Array[String]): Unit = {
    val text = "Hello Universe!"
    val encoded = encodeToBase36(text)
    val decoded = decodeFromBase36(encoded)

    println(s"Original: $text")
    println(s"Base-36 encoded: $encoded")
    println(s"Decoded: $decoded")
  }
}


/*
run:

Original: Hello Universe!
Base-36 encoded: LP4N024HJ1YVBVD84Y8TYQP
Decoded: Hello Universe!

*/

 



answered 3 days ago by avibootz
...