Skip to content

Data Unit Converter — Kotlin source

Convert between digital data units - B, KB/KiB, MB/MiB, GB/GiB, TB/TiB. Switch between decimal (1000) and binary (1024) bases, runs entirely in your browser.

This is the Kotlin implementation — the same logic the interactive tool runs, in a shareable, citable form.

// =============================================================================
//  DataUnits.kt — CosmoDev polyglot showcase port of the
//  `data-unit-converter` tool
//  -----------------------------------------------------------------------------
//  Language : Kotlin (1.9, standard library only)
//  Source:   ported from src/lib/dataUnits.ts (the canonical, live TypeScript
//             lib); mirrors src/tool-sources/data-unit-converter/{python.py,rust.rs}
//  License  : display source — part of CosmoDev's polyglot tool pages
//             (dev.cosmolabs.org). Shown verbatim alongside the JS/TS/Go/Rust/
//             Python ports and the other language ports.
//  -----------------------------------------------------------------------------
//  Pure digital-data unit conversion. Convert between B, KB/KiB, MB/MiB,
//  GB/GiB, TB/TiB: the decimal base 1000 pairs with KB/MB/GB/TB (SI) and the
//  binary base 1024 with KiB/MiB/GiB/TiB (IEC). Deterministic and
//  side-effect free; convertData returns Double.NaN for non-finite input,
//  unknown unit symbols, or an invalid base — never throws.
// =============================================================================

package org.cosmolabs.cosmodev

import kotlin.math.pow

/**
 * Pure digital-data unit conversion for the Data Unit Converter tool on
 * CosmoDev (dev.cosmolabs.org). Exposed as an `object` — a stateless
 * namespace of pure functions, the idiomatic Kotlin replacement for a static
 * utility class.
 */
object DataUnits {

    /**
     * Units available under each base, ordered smallest (B) to largest. The
     * UI uses this to populate the per-base unit pickers. Read-only maps and
     * lists throughout — nothing here is mutable.
     */
    val units: Map<Int, List<String>> = mapOf(
        1000 to listOf("B", "KB", "MB", "GB", "TB"),
        1024 to listOf("B", "KiB", "MiB", "GiB", "TiB"),
    )

    /**
     * Power-of-base rank for each unit symbol: "B" is rank 0 and each prefix
     * step adds 1. KB and KiB are both rank 1 — the unit picks the rank, the
     * base decides whether a rank means ×1000 or ×1024.
     */
    private val exponents: Map<String, Int> = mapOf(
        "B" to 0,
        "KB" to 1, "MB" to 2, "GB" to 3, "TB" to 4,
        "KiB" to 1, "MiB" to 2, "GiB" to 3, "TiB" to 4,
    )

    /**
     * Converts a value between two digital-data units under the given base.
     *
     * Strategy: reduce to bytes via `value × base^fromExp`, then divide by
     * `base^toExp`. Returns [Double.NaN] for non-finite input (Inf/NaN),
     * unknown unit symbols, or a base other than 1000/1024 — never throws
     * (mirrors the TypeScript contract).
     *
     * @param value    the magnitude to convert, in [fromUnit]
     * @param fromUnit source unit symbol, e.g. "MB"
     * @param toUnit   target unit symbol, e.g. "GiB"
     * @param base     conversion radix: 1000 (decimal/SI) or 1024 (binary/IEC)
     * @return the converted magnitude, or [Double.NaN] on invalid input
     */
    fun convertData(value: Double, fromUnit: String, toUnit: String, base: Int): Double {
        // Reject Inf/NaN early so they don't propagate through the multiplication.
        if (value.isNaN() || value.isInfinite()) return Double.NaN
        // Only the two canonical bases are valid; anything else is a caller bug.
        if (base != 1000 && base != 1024) return Double.NaN
        // Unknown unit symbols miss the map (null) — treat as invalid.
        val fromExp = exponents[fromUnit] ?: return Double.NaN
        val toExp = exponents[toUnit] ?: return Double.NaN

        val radix = base.toDouble()
        return (value * radix.pow(fromExp)) / radix.pow(toExp)
    }
}

Also available in 13 other languages

Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →