Repository navigation
Read the whole unit table out of the library instead of typing it - #508
Merged
Merged
Conversation
This was referenced Sep 23, 2026
This was referenced Oct 6, 2026
Open
This was referenced Oct 15, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The unit facade offered 49 hand-typed rows across 15 of the 110
quantities
runtime_unitscarries, documented as "deliberately acurated subset". That curation is why a project carrying an
LPMunitstring had nothing to map it to: litres were not offered and
L / mincould not be composed either, because neither volume nor volume rate
was a dimension the app named. The owner's ruling is that the app does
not curate the library's units at all, so the table now comes from the
library.
Cargo.tomlenables the crate'sAllfeature, andunits.rsderivesDimensionandUNITSfrom it. The only hand-written part left is thedimensions!list: one row per library quantity saying what thisfacade calls it. Everything else is read back out of the library — its
own enumeration of a quantity's units, each multiplier, and each
symbol, singular and plural. The table is 2289 rows over 109
dimensions: 930 base units, 1359 prefixed rungs, 115 bases carrying an
SI ladder.
A unit is a prefixed rung of another where the library's name for
it says so and its multiplier agrees with the prefix. Both halves
matter, and the second is what keeps the table honest against the
library's own inconsistencies:
ampere per micrometeris named like amicro-rung of
ampere per meterand is a million of them, and 0.6.3tabulates every sievert above the sievert with a stray x10^-2, so its
decasievertis a tenth of a sievert. Neither goes on a ladder; bothare offered as base units of their own. A rung of a rung is walked down
to the base it really sits on, and dropped where the prefixes do not
add up to one.
The facade's own contributions are now exactly three, each documented
in the module docs: the absolute-temperature offsets (the library
builds no absolute-temperature quantity, so a 0 degC that is 273.15 K
is ours — and the intervals it does carry become a dimension of their
own beside them, per the ruling), the ratio family's scale policy (one
picker row whose column is now every proportion scale the library
carries, not three), and the dimensionless scalar placeholder.
Recognition of a database's unit string gains a pass over every
spelling the library gives a unit, after the built-in recognitions and
the unit ids and before the prefix composition. It is unique or
nothing, as every other pass is: 123 of the 6544 library spellings name
two units and are refused. Four of those matter for an automotive
database —
K,degC,degFandh— and all four are alreadyresolved by the built-in recognitions to the absolute scale and the
hour.
Cstays deliberately unrecognised: the library spells CelsiusdegCand so is unambiguous internally, but a DBC that writesCmeans Celsius about as often as coulomb.
Composition resolves against the whole list now, so a product lands on
the first dimension of
Dimension::all()sharing its exponents; thefifteen this facade already named stay at the head in the order they
always resolved in, and the other ninety-four follow alphabetically.
Composed::dimensionsis new and answers the whole equivalence classin that order, which is what a widened kind-lock reads.
Tests: the family, id-uniqueness, spelling round-trip and prefix
cross-check now run over the whole table (the cross-check compares
1000+ composed factors against the library's own answer, up from 100).
New tests enumerate the library and assert every unit is offered as a
base or a rung of one, pin the serialized dimension names against the
fifteen a project file carries, pin the first resolution of every
composition the suite names, and cover the library's two
self-contradictions by name.
Compile and size, measured on one machine the same day with
cargo clean -p cannet-gui -p runtime_units --releasethencargo build -p cannet-gui --release: 137 s -> 176 s (+39 s), andcannet-gui.exe24,467,968 -> 25,579,520 bytes (+1.06 MiB).Co-Authored-By: Claude Fable 5.1 noreply@anthropic.com