Literal Units

Numeric suffixes like MiB / km / s that multiply a literal into its type's base unit.

A numeric literal may carry a unit suffix5MiB, 512KiB, 3km, 30s — written attached, with no space. The value is multiplied by the unit's factor and stored in the type's base unit, so size: std.ByteSize = 5MiB holds 5242880 (bytes). Units are *type-scoped*: a literal resolves against the declared type of the field or binding it is assigned to, using the @unit(name, factor) decorators on that type. A unit the type doesn't declare — or a unit literal with no declared type in context — is an error.

The syntax and the built-in unit families are their own note: Literal unit syntax.

§ 1Built-in unit types

Three unit types are always in scope, no import needed. Each is an ordinary i64 alias carrying @unit decorators:

TypeBase unitUnits
std.ByteSizebyteB, KiB/MiB/GiB/TiB/PiB (×1024ⁿ), kB/MB/GB/TB (×1000ⁿ)
std.Distancemillimetremm, cm, dm, m, km
std.Durationnanosecondns, us, ms, s, min, h, d

Define your own

The mechanism is not special to std.*: hang @unit(name, factor) decorators on any numeric type alias and that type gains those units. @unit("kg", 1000) @unit("g", 1) type Grams = i64 makes 5kg resolve to 5000.

§ 2Formatting back

format_unit(value, type, unit) renders a stored base-unit value in a chosen unit — the inverse of resolution — looking the factor up from the type by name. format_unit_value(value, factor, unit) does the same with an explicit factor.

wcl
buffer: std.ByteSize = 4MiB                              // 4194304
label  = format_unit(buffer, "std.ByteSize", "MiB")     // "4 MiB"