uom
uom copied to clipboard
Dynamically choose unit for new/get/floor/ceil/... methods
Add a way to dynamically choose the unit when calling methods with a generic parameter where N: Unit
. What is the best way to do this? Add methods that accept dyn Unit
? Add an enum
for each quantity containing a member for each unit? Allow users to create enum
s on a per-quantity basis to only include the units they are interested in (this is useful at the UI level to provide a subset of units to a user)?
Review in more detail prior to v1.0.0. Can/should this be implemented now or pushed to v2.0.0?
Out of curiosity what is happening here? It certainly seems to be picking units dynamically in the from_str test. I'm a rust newbie at the moment, I was able to see that Quantity! macro is generating a match statement for the from_str implementations, and adding my own parse statements in that test using eg k::Length
works, but I found it impossible to use from_str
/ parse
in my own code, from si::Length
, the compiler needs the unit and value size type parameters for Length. I don't fully follow what is happening with the k::
namespace and the Q!
macro, but was scratching my head for quite a bit yesterday on why I couldn't use the .parse
workaround like I saw in the test.
You're right that the FromStr
impl is using a large match statement to convert the abbreviation, singular, or plural description for each of the quantity's units into an explicit call with a fixed generic parameter.
Rather than use the pre-built SI system, tests use a custom system that just includes length, mass, and thermodynamic temperature. The f
and k
submodules define separate sets of quantities that use different base units (meter, kilogram, kelvin) and (kilometer, kilogram, kelvin). This is done to test conversions between different base units (e.g. length stored as meters + length stored as kilometers).
Using FromStr
in your own code should look something like this following code block. You'll probably want to use uom::si::f32::*;
and handle the result instead of unwrapping. If you still can't get your code to compile can you share the code or a minimal example?
let l = "1 m".parse::<uom::si::f32::Length>().unwrap();
That works! The trick to getting the FromStr
workaround was using <uom::si::f32::Length>
rather than <uom::si::Length>
as you said. Your explanation also helped me understand what I was seeing a bit better as well.
Thanks
For what it's worth, I am practicing Rust by making a simple GUI for converting between units, and I ran into some of these limitations. I originally wanted to take every quantity and every unit from uom and make them available in the GUI to convert in both directions, but I realized I would have to manually list them all, so I made some compromises.
Based on this experience, here are a few things that I think would simplify the implementation for this use case:
- Move more methods from the quantities and units to traits, so we can use trait bounds in the generics and avoid rewriting them in macros. Things like
description()
,abbreviation()
,format_args()
and the methods mentioned in the items below. - Associate the
Units
enum and theunits()
iterator method with each quantity type, rather than leaving it in the module. - Add non-generic alternatives to
new()
,get()
, andformat_args()
, which take theUnits
enum and find the right generic method to call using a match statement, similar to theparse()
method. - Derive
PartialEq
for theUnits
enum.
I played with the uom source a little, and it seems that a lot of these changes would be relatively easy to implement by changing the quantity!
macro. If they are considered useful, I would be willing to implement them and submit a PR.
But I don't know how useful all this is for "real" use cases, as you would usually need to add some units that are not in the enum, so you would not be able to use all this functionality implemented for the enum. So I guess this dynamic unit selection would have to accept user-defined units to be truly helpful.
Really cool to see what you have done!
The addition of the Units
enum was really a stop-gap fix for being able to dynamically choose units and isn't very ergonomic to work with. I would definitely accept PRs to approve things. I just ask for a bit of patience as I have a big backlog of new quantity/unit PRs to work through.