add labels to units for display purposes
This commit is contained in:
parent
f44d51c219
commit
fa7aeb235a
1 changed files with 145 additions and 119 deletions
|
|
@ -92,6 +92,9 @@ pub const UnitCategory = enum {
|
|||
pub const UnitDef = struct {
|
||||
/// Canonical short name (e.g. "km").
|
||||
name: []const u8,
|
||||
/// What a person reads in a list: "Kilometer", "Meter per second". US spelling,
|
||||
/// singular, ASCII. Display only - the engine never resolves a name through it.
|
||||
label: []const u8,
|
||||
/// Alternative spellings, including long forms and plurals.
|
||||
aliases: []const []const u8 = &.{},
|
||||
category: UnitCategory,
|
||||
|
|
@ -140,6 +143,10 @@ pub const UnitDef = struct {
|
|||
/// source of truth and the exact conversion path is unaffected.
|
||||
const UnitSpec = struct {
|
||||
name: []const u8,
|
||||
/// Required, with no default: a unit cannot be added to a table without a name a
|
||||
/// frontend can show. These were guessed from the aliases before, which is how
|
||||
/// `m/s` came out as "Meterpersecond".
|
||||
label: []const u8,
|
||||
aliases: []const []const u8 = &.{},
|
||||
/// Exact factor as a decimal or `p/q`. Null means the factor is irrational
|
||||
/// (pi-based) and only `approx_factor` applies.
|
||||
|
|
@ -164,6 +171,7 @@ fn define(comptime category: UnitCategory, comptime specs: []const UnitSpec) [sp
|
|||
|
||||
out[i] = .{
|
||||
.name = spec.name,
|
||||
.label = spec.label,
|
||||
.aliases = spec.aliases,
|
||||
.category = category,
|
||||
.to_base_factor = factor,
|
||||
|
|
@ -213,56 +221,56 @@ pub const ConvertResult = struct {
|
|||
// Each table's base unit has factor "1" and no offset.
|
||||
|
||||
const length_units = define(.length, &.{
|
||||
.{ .name = "nm", .aliases = &.{ "nanometer", "nanometers", "nanometre", "nanometres" }, .factor = "1e-9" },
|
||||
.{ .name = "um", .aliases = &.{ "micrometer", "micrometers", "micron", "microns" }, .factor = "1e-6" },
|
||||
.{ .name = "mm", .aliases = &.{ "millimeter", "millimeters", "millimetre", "millimetres" }, .factor = "0.001" },
|
||||
.{ .name = "cm", .aliases = &.{ "centimeter", "centimeters", "centimetre", "centimetres" }, .factor = "0.01" },
|
||||
.{ .name = "m", .aliases = &.{ "meter", "meters", "metre", "metres" }, .factor = "1" },
|
||||
.{ .name = "km", .aliases = &.{ "kilometer", "kilometers", "kilometre", "kilometres" }, .factor = "1000" },
|
||||
.{ .name = "in", .aliases = &.{ "inch", "inches" }, .factor = "0.0254" },
|
||||
.{ .name = "ft", .aliases = &.{ "foot", "feet" }, .factor = "0.3048" },
|
||||
.{ .name = "yd", .aliases = &.{ "yard", "yards" }, .factor = "0.9144" },
|
||||
.{ .name = "mi", .aliases = &.{ "mile", "miles" }, .factor = "1609.344" },
|
||||
.{ .name = "nmi", .aliases = &.{ "nauticalmile", "nauticalmiles" }, .factor = "1852" },
|
||||
.{ .name = "ly", .aliases = &.{ "lightyear", "lightyears" }, .factor = "9460730472580800" },
|
||||
.{ .name = "au", .aliases = &.{ "astronomicalunit", "astronomicalunits" }, .factor = "149597870700" },
|
||||
.{ .name = "nm", .label = "Nanometer", .aliases = &.{ "nanometer", "nanometers", "nanometre", "nanometres" }, .factor = "1e-9" },
|
||||
.{ .name = "um", .label = "Micrometer", .aliases = &.{ "micrometer", "micrometers", "micron", "microns" }, .factor = "1e-6" },
|
||||
.{ .name = "mm", .label = "Millimeter", .aliases = &.{ "millimeter", "millimeters", "millimetre", "millimetres" }, .factor = "0.001" },
|
||||
.{ .name = "cm", .label = "Centimeter", .aliases = &.{ "centimeter", "centimeters", "centimetre", "centimetres" }, .factor = "0.01" },
|
||||
.{ .name = "m", .label = "Meter", .aliases = &.{ "meter", "meters", "metre", "metres" }, .factor = "1" },
|
||||
.{ .name = "km", .label = "Kilometer", .aliases = &.{ "kilometer", "kilometers", "kilometre", "kilometres" }, .factor = "1000" },
|
||||
.{ .name = "in", .label = "Inch", .aliases = &.{ "inch", "inches" }, .factor = "0.0254" },
|
||||
.{ .name = "ft", .label = "Foot", .aliases = &.{ "foot", "feet" }, .factor = "0.3048" },
|
||||
.{ .name = "yd", .label = "Yard", .aliases = &.{ "yard", "yards" }, .factor = "0.9144" },
|
||||
.{ .name = "mi", .label = "Mile", .aliases = &.{ "mile", "miles" }, .factor = "1609.344" },
|
||||
.{ .name = "nmi", .label = "Nautical mile", .aliases = &.{ "nauticalmile", "nauticalmiles" }, .factor = "1852" },
|
||||
.{ .name = "ly", .label = "Light-year", .aliases = &.{ "lightyear", "lightyears" }, .factor = "9460730472580800" },
|
||||
.{ .name = "au", .label = "Astronomical unit", .aliases = &.{ "astronomicalunit", "astronomicalunits" }, .factor = "149597870700" },
|
||||
// A parsec is exactly 648000/pi au, so it has no exact decimal form.
|
||||
.{ .name = "pc", .aliases = &.{ "parsec", "parsecs" }, .approx_factor = 3.0856775814913673e16 },
|
||||
.{ .name = "pc", .label = "Parsec", .aliases = &.{ "parsec", "parsecs" }, .approx_factor = 3.0856775814913673e16 },
|
||||
});
|
||||
|
||||
const mass_units = define(.mass, &.{
|
||||
.{ .name = "mg", .aliases = &.{ "milligram", "milligrams" }, .factor = "1e-6" },
|
||||
.{ .name = "g", .aliases = &.{ "gram", "grams" }, .factor = "0.001" },
|
||||
.{ .name = "kg", .aliases = &.{ "kilogram", "kilograms" }, .factor = "1" },
|
||||
.{ .name = "t", .aliases = &.{ "tonne", "tonnes", "metricton", "metrictons" }, .factor = "1000" },
|
||||
.{ .name = "oz", .aliases = &.{ "ounce", "ounces" }, .factor = "0.028349523125" },
|
||||
.{ .name = "lb", .aliases = &.{ "lbs", "pound", "pounds" }, .factor = "0.45359237" },
|
||||
.{ .name = "st", .aliases = &.{ "stone", "stones" }, .factor = "6.35029318" },
|
||||
.{ .name = "ton", .aliases = &.{ "shortton", "shorttons" }, .factor = "907.18474" },
|
||||
.{ .name = "lt", .aliases = &.{ "longton", "longtons" }, .factor = "1016.0469088" },
|
||||
.{ .name = "mg", .label = "Milligram", .aliases = &.{ "milligram", "milligrams" }, .factor = "1e-6" },
|
||||
.{ .name = "g", .label = "Gram", .aliases = &.{ "gram", "grams" }, .factor = "0.001" },
|
||||
.{ .name = "kg", .label = "Kilogram", .aliases = &.{ "kilogram", "kilograms" }, .factor = "1" },
|
||||
.{ .name = "t", .label = "Metric ton", .aliases = &.{ "tonne", "tonnes", "metricton", "metrictons" }, .factor = "1000" },
|
||||
.{ .name = "oz", .label = "Ounce", .aliases = &.{ "ounce", "ounces" }, .factor = "0.028349523125" },
|
||||
.{ .name = "lb", .label = "Pound", .aliases = &.{ "lbs", "pound", "pounds" }, .factor = "0.45359237" },
|
||||
.{ .name = "st", .label = "Stone", .aliases = &.{ "stone", "stones" }, .factor = "6.35029318" },
|
||||
.{ .name = "ton", .label = "Short ton", .aliases = &.{ "shortton", "shorttons" }, .factor = "907.18474" },
|
||||
.{ .name = "lt", .label = "Long ton", .aliases = &.{ "longton", "longtons" }, .factor = "1016.0469088" },
|
||||
});
|
||||
|
||||
// Base: Celsius. These are the only units in the engine that need an offset.
|
||||
// Fahrenheit and Rankine scale by exactly 5/9, which has no terminating decimal
|
||||
// form, hence the fraction notation.
|
||||
const temperature_units = define(.temperature, &.{
|
||||
.{ .name = "C", .aliases = &.{ "celsius", "centigrade" }, .factor = "1" },
|
||||
.{ .name = "F", .aliases = &.{"fahrenheit"}, .factor = "5/9", .offset = "-160/9" },
|
||||
.{ .name = "K", .aliases = &.{"kelvin"}, .factor = "1", .offset = "-273.15" },
|
||||
.{ .name = "R", .aliases = &.{ "rankine", "Ra" }, .factor = "5/9", .offset = "-273.15" },
|
||||
.{ .name = "C", .label = "Celsius", .aliases = &.{ "celsius", "centigrade" }, .factor = "1" },
|
||||
.{ .name = "F", .label = "Fahrenheit", .aliases = &.{"fahrenheit"}, .factor = "5/9", .offset = "-160/9" },
|
||||
.{ .name = "K", .label = "Kelvin", .aliases = &.{"kelvin"}, .factor = "1", .offset = "-273.15" },
|
||||
.{ .name = "R", .label = "Rankine", .aliases = &.{ "rankine", "Ra" }, .factor = "5/9", .offset = "-273.15" },
|
||||
});
|
||||
|
||||
const time_units = define(.time, &.{
|
||||
.{ .name = "ns", .aliases = &.{ "nanosecond", "nanoseconds" }, .factor = "1e-9" },
|
||||
.{ .name = "us", .aliases = &.{ "microsecond", "microseconds" }, .factor = "1e-6" },
|
||||
.{ .name = "ms", .aliases = &.{ "millisecond", "milliseconds" }, .factor = "0.001" },
|
||||
.{ .name = "s", .aliases = &.{ "sec", "secs", "second", "seconds" }, .factor = "1" },
|
||||
.{ .name = "min", .aliases = &.{ "minute", "minutes" }, .factor = "60" },
|
||||
.{ .name = "h", .aliases = &.{ "hr", "hrs", "hour", "hours" }, .factor = "3600" },
|
||||
.{ .name = "d", .aliases = &.{ "day", "days" }, .factor = "86400" },
|
||||
.{ .name = "wk", .aliases = &.{ "week", "weeks" }, .factor = "604800" },
|
||||
.{ .name = "ns", .label = "Nanosecond", .aliases = &.{ "nanosecond", "nanoseconds" }, .factor = "1e-9" },
|
||||
.{ .name = "us", .label = "Microsecond", .aliases = &.{ "microsecond", "microseconds" }, .factor = "1e-6" },
|
||||
.{ .name = "ms", .label = "Millisecond", .aliases = &.{ "millisecond", "milliseconds" }, .factor = "0.001" },
|
||||
.{ .name = "s", .label = "Second", .aliases = &.{ "sec", "secs", "second", "seconds" }, .factor = "1" },
|
||||
.{ .name = "min", .label = "Minute", .aliases = &.{ "minute", "minutes" }, .factor = "60" },
|
||||
.{ .name = "h", .label = "Hour", .aliases = &.{ "hr", "hrs", "hour", "hours" }, .factor = "3600" },
|
||||
.{ .name = "d", .label = "Day", .aliases = &.{ "day", "days" }, .factor = "86400" },
|
||||
.{ .name = "wk", .label = "Week", .aliases = &.{ "week", "weeks" }, .factor = "604800" },
|
||||
// Julian year, the usual convention for "a year" in unit conversion.
|
||||
.{ .name = "yr", .aliases = &.{ "year", "years" }, .factor = "31557600" },
|
||||
.{ .name = "yr", .label = "Year (Julian)", .aliases = &.{ "year", "years" }, .factor = "31557600" },
|
||||
});
|
||||
|
||||
// Base: byte. Decimal (kB) and binary (KiB) prefixes are both provided, and bits
|
||||
|
|
@ -274,103 +282,103 @@ const time_units = define(.time, &.{
|
|||
//
|
||||
// A bit is an eighth of a byte, so every factor here is exact.
|
||||
const digital_storage_units = define(.digital_storage, &.{
|
||||
.{ .name = "b", .aliases = &.{ "bit", "bits" }, .factor = "0.125" },
|
||||
.{ .name = "kb", .aliases = &.{ "kilobit", "kilobits" }, .factor = "125" },
|
||||
.{ .name = "Mb", .aliases = &.{ "megabit", "megabits" }, .factor = "1.25e5" },
|
||||
.{ .name = "Gb", .aliases = &.{ "gigabit", "gigabits" }, .factor = "1.25e8" },
|
||||
.{ .name = "Tb", .aliases = &.{ "terabit", "terabits" }, .factor = "1.25e11" },
|
||||
.{ .name = "Pb", .aliases = &.{ "petabit", "petabits" }, .factor = "1.25e14" },
|
||||
.{ .name = "B", .aliases = &.{ "byte", "bytes" }, .factor = "1" },
|
||||
.{ .name = "kB", .aliases = &.{ "kilobyte", "kilobytes" }, .factor = "1e3" },
|
||||
.{ .name = "MB", .aliases = &.{ "megabyte", "megabytes" }, .factor = "1e6" },
|
||||
.{ .name = "GB", .aliases = &.{ "gigabyte", "gigabytes" }, .factor = "1e9" },
|
||||
.{ .name = "TB", .aliases = &.{ "terabyte", "terabytes" }, .factor = "1e12" },
|
||||
.{ .name = "PB", .aliases = &.{ "petabyte", "petabytes" }, .factor = "1e15" },
|
||||
.{ .name = "KiB", .aliases = &.{ "kibibyte", "kibibytes" }, .factor = "1024" },
|
||||
.{ .name = "MiB", .aliases = &.{ "mebibyte", "mebibytes" }, .factor = "1048576" },
|
||||
.{ .name = "GiB", .aliases = &.{ "gibibyte", "gibibytes" }, .factor = "1073741824" },
|
||||
.{ .name = "TiB", .aliases = &.{ "tebibyte", "tebibytes" }, .factor = "1099511627776" },
|
||||
.{ .name = "PiB", .aliases = &.{ "pebibyte", "pebibytes" }, .factor = "1125899906842624" },
|
||||
.{ .name = "b", .label = "Bit", .aliases = &.{ "bit", "bits" }, .factor = "0.125" },
|
||||
.{ .name = "kb", .label = "Kilobit", .aliases = &.{ "kilobit", "kilobits" }, .factor = "125" },
|
||||
.{ .name = "Mb", .label = "Megabit", .aliases = &.{ "megabit", "megabits" }, .factor = "1.25e5" },
|
||||
.{ .name = "Gb", .label = "Gigabit", .aliases = &.{ "gigabit", "gigabits" }, .factor = "1.25e8" },
|
||||
.{ .name = "Tb", .label = "Terabit", .aliases = &.{ "terabit", "terabits" }, .factor = "1.25e11" },
|
||||
.{ .name = "Pb", .label = "Petabit", .aliases = &.{ "petabit", "petabits" }, .factor = "1.25e14" },
|
||||
.{ .name = "B", .label = "Byte", .aliases = &.{ "byte", "bytes" }, .factor = "1" },
|
||||
.{ .name = "kB", .label = "Kilobyte", .aliases = &.{ "kilobyte", "kilobytes" }, .factor = "1e3" },
|
||||
.{ .name = "MB", .label = "Megabyte", .aliases = &.{ "megabyte", "megabytes" }, .factor = "1e6" },
|
||||
.{ .name = "GB", .label = "Gigabyte", .aliases = &.{ "gigabyte", "gigabytes" }, .factor = "1e9" },
|
||||
.{ .name = "TB", .label = "Terabyte", .aliases = &.{ "terabyte", "terabytes" }, .factor = "1e12" },
|
||||
.{ .name = "PB", .label = "Petabyte", .aliases = &.{ "petabyte", "petabytes" }, .factor = "1e15" },
|
||||
.{ .name = "KiB", .label = "Kibibyte", .aliases = &.{ "kibibyte", "kibibytes" }, .factor = "1024" },
|
||||
.{ .name = "MiB", .label = "Mebibyte", .aliases = &.{ "mebibyte", "mebibytes" }, .factor = "1048576" },
|
||||
.{ .name = "GiB", .label = "Gibibyte", .aliases = &.{ "gibibyte", "gibibytes" }, .factor = "1073741824" },
|
||||
.{ .name = "TiB", .label = "Tebibyte", .aliases = &.{ "tebibyte", "tebibytes" }, .factor = "1099511627776" },
|
||||
.{ .name = "PiB", .label = "Pebibyte", .aliases = &.{ "pebibyte", "pebibytes" }, .factor = "1125899906842624" },
|
||||
});
|
||||
|
||||
// km/h is exactly 5/18 m/s and a knot exactly 463/900 m/s.
|
||||
const speed_units = define(.speed, &.{
|
||||
.{ .name = "m/s", .aliases = &.{ "mps", "meterpersecond", "meterspersecond" }, .factor = "1" },
|
||||
.{ .name = "km/h", .aliases = &.{ "kph", "kmh", "kilometerperhour", "kilometersperhour" }, .factor = "1000/3600" },
|
||||
.{ .name = "mph", .aliases = &.{ "mileperhour", "milesperhour" }, .factor = "0.44704" },
|
||||
.{ .name = "ft/s", .aliases = &.{ "fps", "footpersecond", "feetpersecond" }, .factor = "0.3048" },
|
||||
.{ .name = "kn", .aliases = &.{ "knot", "knots" }, .factor = "1852/3600" },
|
||||
.{ .name = "c", .aliases = &.{ "lightspeed", "speedoflight" }, .factor = "299792458" },
|
||||
.{ .name = "m/s", .label = "Meter per second", .aliases = &.{ "mps", "meterpersecond", "meterspersecond" }, .factor = "1" },
|
||||
.{ .name = "km/h", .label = "Kilometer per hour", .aliases = &.{ "kph", "kmh", "kilometerperhour", "kilometersperhour" }, .factor = "1000/3600" },
|
||||
.{ .name = "mph", .label = "Mile per hour", .aliases = &.{ "mileperhour", "milesperhour" }, .factor = "0.44704" },
|
||||
.{ .name = "ft/s", .label = "Foot per second", .aliases = &.{ "fps", "footpersecond", "feetpersecond" }, .factor = "0.3048" },
|
||||
.{ .name = "kn", .label = "Knot", .aliases = &.{ "knot", "knots" }, .factor = "1852/3600" },
|
||||
.{ .name = "c", .label = "Speed of light", .aliases = &.{ "lightspeed", "speedoflight" }, .factor = "299792458" },
|
||||
});
|
||||
|
||||
const area_units = define(.area, &.{
|
||||
.{ .name = "mm2", .aliases = &.{ "mm^2", "squaremillimeter", "squaremillimeters" }, .factor = "1e-6" },
|
||||
.{ .name = "cm2", .aliases = &.{ "cm^2", "squarecentimeter", "squarecentimeters" }, .factor = "1e-4" },
|
||||
.{ .name = "m2", .aliases = &.{ "m^2", "squaremeter", "squaremeters" }, .factor = "1" },
|
||||
.{ .name = "km2", .aliases = &.{ "km^2", "squarekilometer", "squarekilometers" }, .factor = "1e6" },
|
||||
.{ .name = "in2", .aliases = &.{ "in^2", "squareinch", "squareinches" }, .factor = "0.00064516" },
|
||||
.{ .name = "ft2", .aliases = &.{ "ft^2", "squarefoot", "squarefeet" }, .factor = "0.09290304" },
|
||||
.{ .name = "yd2", .aliases = &.{ "yd^2", "squareyard", "squareyards" }, .factor = "0.83612736" },
|
||||
.{ .name = "mi2", .aliases = &.{ "mi^2", "squaremile", "squaremiles" }, .factor = "2589988.110336" },
|
||||
.{ .name = "ha", .aliases = &.{ "hectare", "hectares" }, .factor = "10000" },
|
||||
.{ .name = "acre", .aliases = &.{"acres"}, .factor = "4046.8564224" },
|
||||
.{ .name = "mm2", .label = "Square millimeter", .aliases = &.{ "mm^2", "squaremillimeter", "squaremillimeters" }, .factor = "1e-6" },
|
||||
.{ .name = "cm2", .label = "Square centimeter", .aliases = &.{ "cm^2", "squarecentimeter", "squarecentimeters" }, .factor = "1e-4" },
|
||||
.{ .name = "m2", .label = "Square meter", .aliases = &.{ "m^2", "squaremeter", "squaremeters" }, .factor = "1" },
|
||||
.{ .name = "km2", .label = "Square kilometer", .aliases = &.{ "km^2", "squarekilometer", "squarekilometers" }, .factor = "1e6" },
|
||||
.{ .name = "in2", .label = "Square inch", .aliases = &.{ "in^2", "squareinch", "squareinches" }, .factor = "0.00064516" },
|
||||
.{ .name = "ft2", .label = "Square foot", .aliases = &.{ "ft^2", "squarefoot", "squarefeet" }, .factor = "0.09290304" },
|
||||
.{ .name = "yd2", .label = "Square yard", .aliases = &.{ "yd^2", "squareyard", "squareyards" }, .factor = "0.83612736" },
|
||||
.{ .name = "mi2", .label = "Square mile", .aliases = &.{ "mi^2", "squaremile", "squaremiles" }, .factor = "2589988.110336" },
|
||||
.{ .name = "ha", .label = "Hectare", .aliases = &.{ "hectare", "hectares" }, .factor = "10000" },
|
||||
.{ .name = "acre", .label = "Acre", .aliases = &.{"acres"}, .factor = "4046.8564224" },
|
||||
});
|
||||
|
||||
// Base: liter.
|
||||
const volume_units = define(.volume, &.{
|
||||
.{ .name = "mL", .aliases = &.{ "ml", "milliliter", "milliliters" }, .factor = "0.001" },
|
||||
.{ .name = "L", .aliases = &.{ "l", "liter", "liters", "litre", "litres" }, .factor = "1" },
|
||||
.{ .name = "m3", .aliases = &.{ "m^3", "cubicmeter", "cubicmeters" }, .factor = "1000" },
|
||||
.{ .name = "cm3", .aliases = &.{ "cm^3", "cc", "cubiccentimeter", "cubiccentimeters" }, .factor = "0.001" },
|
||||
.{ .name = "in3", .aliases = &.{ "in^3", "cubicinch", "cubicinches" }, .factor = "0.016387064" },
|
||||
.{ .name = "ft3", .aliases = &.{ "ft^3", "cubicfoot", "cubicfeet" }, .factor = "28.316846592" },
|
||||
.{ .name = "gal", .aliases = &.{ "gallon", "gallons" }, .factor = "3.785411784" },
|
||||
.{ .name = "qt", .aliases = &.{ "quart", "quarts" }, .factor = "0.946352946" },
|
||||
.{ .name = "pt", .aliases = &.{ "pint", "pints" }, .factor = "0.473176473" },
|
||||
.{ .name = "cup", .aliases = &.{"cups"}, .factor = "0.2365882365" },
|
||||
.{ .name = "floz", .aliases = &.{ "fluidounce", "fluidounces" }, .factor = "0.0295735295625" },
|
||||
.{ .name = "tbsp", .aliases = &.{ "tablespoon", "tablespoons" }, .factor = "0.01478676478125" },
|
||||
.{ .name = "tsp", .aliases = &.{ "teaspoon", "teaspoons" }, .factor = "0.00492892159375" },
|
||||
.{ .name = "bbl", .aliases = &.{ "barrel", "barrels" }, .factor = "158.987294928" },
|
||||
.{ .name = "mL", .label = "Milliliter", .aliases = &.{ "ml", "milliliter", "milliliters" }, .factor = "0.001" },
|
||||
.{ .name = "L", .label = "Liter", .aliases = &.{ "l", "liter", "liters", "litre", "litres" }, .factor = "1" },
|
||||
.{ .name = "m3", .label = "Cubic meter", .aliases = &.{ "m^3", "cubicmeter", "cubicmeters" }, .factor = "1000" },
|
||||
.{ .name = "cm3", .label = "Cubic centimeter", .aliases = &.{ "cm^3", "cc", "cubiccentimeter", "cubiccentimeters" }, .factor = "0.001" },
|
||||
.{ .name = "in3", .label = "Cubic inch", .aliases = &.{ "in^3", "cubicinch", "cubicinches" }, .factor = "0.016387064" },
|
||||
.{ .name = "ft3", .label = "Cubic foot", .aliases = &.{ "ft^3", "cubicfoot", "cubicfeet" }, .factor = "28.316846592" },
|
||||
.{ .name = "gal", .label = "Gallon (US)", .aliases = &.{ "gallon", "gallons" }, .factor = "3.785411784" },
|
||||
.{ .name = "qt", .label = "Quart (US)", .aliases = &.{ "quart", "quarts" }, .factor = "0.946352946" },
|
||||
.{ .name = "pt", .label = "Pint (US)", .aliases = &.{ "pint", "pints" }, .factor = "0.473176473" },
|
||||
.{ .name = "cup", .label = "Cup (US)", .aliases = &.{"cups"}, .factor = "0.2365882365" },
|
||||
.{ .name = "floz", .label = "Fluid ounce (US)", .aliases = &.{ "fluidounce", "fluidounces" }, .factor = "0.0295735295625" },
|
||||
.{ .name = "tbsp", .label = "Tablespoon (US)", .aliases = &.{ "tablespoon", "tablespoons" }, .factor = "0.01478676478125" },
|
||||
.{ .name = "tsp", .label = "Teaspoon (US)", .aliases = &.{ "teaspoon", "teaspoons" }, .factor = "0.00492892159375" },
|
||||
.{ .name = "bbl", .label = "Barrel (oil)", .aliases = &.{ "barrel", "barrels" }, .factor = "158.987294928" },
|
||||
});
|
||||
|
||||
const energy_units = define(.energy, &.{
|
||||
.{ .name = "J", .aliases = &.{ "joule", "joules" }, .factor = "1" },
|
||||
.{ .name = "kJ", .aliases = &.{ "kilojoule", "kilojoules" }, .factor = "1000" },
|
||||
.{ .name = "cal", .aliases = &.{ "calorie", "calories" }, .factor = "4.184" },
|
||||
.{ .name = "kcal", .aliases = &.{ "kilocalorie", "kilocalories" }, .factor = "4184" },
|
||||
.{ .name = "Wh", .aliases = &.{ "watthour", "watthours" }, .factor = "3600" },
|
||||
.{ .name = "kWh", .aliases = &.{ "kilowatthour", "kilowatthours" }, .factor = "3600000" },
|
||||
.{ .name = "BTU", .aliases = &.{ "btu", "britishthermalunit" }, .factor = "1055.05585262" },
|
||||
.{ .name = "eV", .aliases = &.{ "electronvolt", "electronvolts" }, .factor = "1.602176634e-19" },
|
||||
.{ .name = "erg", .aliases = &.{"ergs"}, .factor = "1e-7" },
|
||||
.{ .name = "J", .label = "Joule", .aliases = &.{ "joule", "joules" }, .factor = "1" },
|
||||
.{ .name = "kJ", .label = "Kilojoule", .aliases = &.{ "kilojoule", "kilojoules" }, .factor = "1000" },
|
||||
.{ .name = "cal", .label = "Calorie", .aliases = &.{ "calorie", "calories" }, .factor = "4.184" },
|
||||
.{ .name = "kcal", .label = "Kilocalorie", .aliases = &.{ "kilocalorie", "kilocalories" }, .factor = "4184" },
|
||||
.{ .name = "Wh", .label = "Watt-hour", .aliases = &.{ "watthour", "watthours" }, .factor = "3600" },
|
||||
.{ .name = "kWh", .label = "Kilowatt-hour", .aliases = &.{ "kilowatthour", "kilowatthours" }, .factor = "3600000" },
|
||||
.{ .name = "BTU", .label = "British thermal unit", .aliases = &.{ "btu", "britishthermalunit" }, .factor = "1055.05585262" },
|
||||
.{ .name = "eV", .label = "Electronvolt", .aliases = &.{ "electronvolt", "electronvolts" }, .factor = "1.602176634e-19" },
|
||||
.{ .name = "erg", .label = "Erg", .aliases = &.{"ergs"}, .factor = "1e-7" },
|
||||
});
|
||||
|
||||
const pressure_units = define(.pressure, &.{
|
||||
.{ .name = "Pa", .aliases = &.{ "pascal", "pascals" }, .factor = "1" },
|
||||
.{ .name = "kPa", .aliases = &.{ "kilopascal", "kilopascals" }, .factor = "1000" },
|
||||
.{ .name = "MPa", .aliases = &.{ "megapascal", "megapascals" }, .factor = "1e6" },
|
||||
.{ .name = "bar", .aliases = &.{"bars"}, .factor = "100000" },
|
||||
.{ .name = "mbar", .aliases = &.{ "millibar", "millibars" }, .factor = "100" },
|
||||
.{ .name = "atm", .aliases = &.{ "atmosphere", "atmospheres" }, .factor = "101325" },
|
||||
.{ .name = "Pa", .label = "Pascal", .aliases = &.{ "pascal", "pascals" }, .factor = "1" },
|
||||
.{ .name = "kPa", .label = "Kilopascal", .aliases = &.{ "kilopascal", "kilopascals" }, .factor = "1000" },
|
||||
.{ .name = "MPa", .label = "Megapascal", .aliases = &.{ "megapascal", "megapascals" }, .factor = "1e6" },
|
||||
.{ .name = "bar", .label = "Bar", .aliases = &.{"bars"}, .factor = "100000" },
|
||||
.{ .name = "mbar", .label = "Millibar", .aliases = &.{ "millibar", "millibars" }, .factor = "100" },
|
||||
.{ .name = "atm", .label = "Atmosphere", .aliases = &.{ "atmosphere", "atmospheres" }, .factor = "101325" },
|
||||
// psi is exactly 4.4482216152605 N over 0.00064516 m2.
|
||||
.{ .name = "psi", .aliases = &.{"poundpersquareinch"}, .factor = "4.4482216152605/0.00064516" },
|
||||
.{ .name = "torr", .aliases = &.{"torrs"}, .factor = "101325/760" },
|
||||
.{ .name = "mmHg", .aliases = &.{"mmhg"}, .factor = "133.322387415" },
|
||||
.{ .name = "inHg", .aliases = &.{"inhg"}, .factor = "3386.388640341" },
|
||||
.{ .name = "psi", .label = "Pound per square inch", .aliases = &.{"poundpersquareinch"}, .factor = "4.4482216152605/0.00064516" },
|
||||
.{ .name = "torr", .label = "Torr", .aliases = &.{"torrs"}, .factor = "101325/760" },
|
||||
.{ .name = "mmHg", .label = "Millimeter of mercury", .aliases = &.{"mmhg"}, .factor = "133.322387415" },
|
||||
.{ .name = "inHg", .label = "Inch of mercury", .aliases = &.{"inhg"}, .factor = "3386.388640341" },
|
||||
});
|
||||
|
||||
// Base: bits per second.
|
||||
const data_rate_units = define(.data_rate, &.{
|
||||
.{ .name = "bps", .aliases = &.{ "bitpersecond", "bitspersecond" }, .factor = "1" },
|
||||
.{ .name = "kbps", .aliases = &.{"kilobitpersecond"}, .factor = "1e3" },
|
||||
.{ .name = "Mbps", .aliases = &.{"megabitpersecond"}, .factor = "1e6" },
|
||||
.{ .name = "Gbps", .aliases = &.{"gigabitpersecond"}, .factor = "1e9" },
|
||||
.{ .name = "Tbps", .aliases = &.{"terabitpersecond"}, .factor = "1e12" },
|
||||
.{ .name = "Bps", .aliases = &.{ "bytepersecond", "bytespersecond" }, .factor = "8" },
|
||||
.{ .name = "kBps", .aliases = &.{"kilobytepersecond"}, .factor = "8e3" },
|
||||
.{ .name = "MBps", .aliases = &.{"megabytepersecond"}, .factor = "8e6" },
|
||||
.{ .name = "GBps", .aliases = &.{"gigabytepersecond"}, .factor = "8e9" },
|
||||
.{ .name = "bps", .label = "Bit per second", .aliases = &.{ "bitpersecond", "bitspersecond" }, .factor = "1" },
|
||||
.{ .name = "kbps", .label = "Kilobit per second", .aliases = &.{"kilobitpersecond"}, .factor = "1e3" },
|
||||
.{ .name = "Mbps", .label = "Megabit per second", .aliases = &.{"megabitpersecond"}, .factor = "1e6" },
|
||||
.{ .name = "Gbps", .label = "Gigabit per second", .aliases = &.{"gigabitpersecond"}, .factor = "1e9" },
|
||||
.{ .name = "Tbps", .label = "Terabit per second", .aliases = &.{"terabitpersecond"}, .factor = "1e12" },
|
||||
.{ .name = "Bps", .label = "Byte per second", .aliases = &.{ "bytepersecond", "bytespersecond" }, .factor = "8" },
|
||||
.{ .name = "kBps", .label = "Kilobyte per second", .aliases = &.{"kilobytepersecond"}, .factor = "8e3" },
|
||||
.{ .name = "MBps", .label = "Megabyte per second", .aliases = &.{"megabytepersecond"}, .factor = "8e6" },
|
||||
.{ .name = "GBps", .label = "Gigabyte per second", .aliases = &.{"gigabytepersecond"}, .factor = "8e9" },
|
||||
});
|
||||
|
||||
// Base: radian. Every unit here except mrad is defined as a fraction of a turn,
|
||||
|
|
@ -378,13 +386,13 @@ const data_rate_units = define(.data_rate, &.{
|
|||
// radians is inherently inexact. Only these units and the parsec are marked
|
||||
// approximate.
|
||||
const angle_units = define(.angle, &.{
|
||||
.{ .name = "rad", .aliases = &.{ "radian", "radians" }, .factor = "1" },
|
||||
.{ .name = "mrad", .aliases = &.{ "milliradian", "milliradians" }, .factor = "0.001" },
|
||||
.{ .name = "deg", .aliases = &.{ "degree", "degrees" }, .approx_factor = std.math.pi / 180.0 },
|
||||
.{ .name = "grad", .aliases = &.{ "gradian", "gradians", "gon" }, .approx_factor = std.math.pi / 200.0 },
|
||||
.{ .name = "turn", .aliases = &.{ "turns", "rev", "revolution", "revolutions" }, .approx_factor = std.math.tau },
|
||||
.{ .name = "arcmin", .aliases = &.{ "arcminute", "arcminutes" }, .approx_factor = std.math.pi / 10800.0 },
|
||||
.{ .name = "arcsec", .aliases = &.{ "arcsecond", "arcseconds" }, .approx_factor = std.math.pi / 648000.0 },
|
||||
.{ .name = "rad", .label = "Radian", .aliases = &.{ "radian", "radians" }, .factor = "1" },
|
||||
.{ .name = "mrad", .label = "Milliradian", .aliases = &.{ "milliradian", "milliradians" }, .factor = "0.001" },
|
||||
.{ .name = "deg", .label = "Degree", .aliases = &.{ "degree", "degrees" }, .approx_factor = std.math.pi / 180.0 },
|
||||
.{ .name = "grad", .label = "Gradian", .aliases = &.{ "gradian", "gradians", "gon" }, .approx_factor = std.math.pi / 200.0 },
|
||||
.{ .name = "turn", .label = "Turn", .aliases = &.{ "turns", "rev", "revolution", "revolutions" }, .approx_factor = std.math.tau },
|
||||
.{ .name = "arcmin", .label = "Arcminute", .aliases = &.{ "arcminute", "arcminutes" }, .approx_factor = std.math.pi / 10800.0 },
|
||||
.{ .name = "arcsec", .label = "Arcsecond", .aliases = &.{ "arcsecond", "arcseconds" }, .approx_factor = std.math.pi / 648000.0 },
|
||||
});
|
||||
|
||||
/// All unit tables, indexed in the same order as `UnitCategory`.
|
||||
|
|
@ -541,7 +549,7 @@ pub fn convert(value: f64, from_name: []const u8, to_name: []const u8) Error!Con
|
|||
///
|
||||
/// `value_text` is the part before the unit and is left unevaluated: it may be a
|
||||
/// plain number or a whole expression ("2*3 km to ft"). Keeping evaluation out of
|
||||
/// this module avoids a dependency on the evaluator, so callers evaluate it with
|
||||
/// this file avoids a dependency on the evaluator, so callers evaluate it with
|
||||
/// whatever environment they already have.
|
||||
pub const ConversionRequest = struct {
|
||||
value_text: []const u8,
|
||||
|
|
@ -1591,3 +1599,21 @@ test "OOM safety: exact conversion releases everything at any failure point" {
|
|||
}
|
||||
return error.OomSweepNeverCompleted;
|
||||
}
|
||||
|
||||
test "every unit has a display name a list can show" {
|
||||
// The field is required, so a unit without one does not compile. This holds the
|
||||
// names to the form a frontend relies on: present, capitalised, printable ASCII,
|
||||
// and distinct within a category, so a list never shows two rows alike.
|
||||
for (categories) |table| {
|
||||
for (table, 0..) |unit, i| {
|
||||
try std.testing.expect(unit.label.len > 0);
|
||||
try std.testing.expect(std.ascii.isUpper(unit.label[0]));
|
||||
for (unit.label) |c| try std.testing.expect(c >= 0x20 and c < 0x7f);
|
||||
for (table[i + 1 ..]) |other| {
|
||||
try std.testing.expect(!std.mem.eql(u8, unit.label, other.label));
|
||||
}
|
||||
}
|
||||
}
|
||||
try std.testing.expectEqualStrings("Meter per second", findUnit("m/s").?.label);
|
||||
try std.testing.expectEqualStrings("Celsius", findUnit("C").?.label);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue