1 个不稳定版本

0.1.0 2024 年 3 月 2 日

#1127 in Rust 模式

MIT/Apache

66KB
1K SLoC

ucsi

ucsi 库提供基于 SI 的单位类型系统和值的零成本单位包装。

您可以使用这些包的值进行正常算术(因为它们重载了运算符),然后 Rust 的泛型引擎和 ucsi 将帮助您推导它们的类型。

感谢 Rust 强大的类型系统和静态评估器,ucsi 允许您在编译时知道您的算术违反了什么,并且提供了对常量算术的完美支持。

同时,您可以轻松创建自己的类型(请参阅 unit! 宏和 macros 模块),这些类型可以与 ucsi 的类型系统无缝协作。

快速入门

use ucsi::units::base::{kg, m, s};
use ucsi::unit;
use ucsi::Value;

// create your new unit
// see the `unit` macro or `ucsi::core::ops` for more information.
type Newton = unit!((kg * m) / (s ** { 2 }));

// build some value
// `Value<value_type, value_unit>`
let speed: Value<f64, unit!(m / s)> = Value::new(10.0);
let time: Value<f64, s> = Value::new(1.0);
let acc = speed / time;
let mass: Value<f64, kg> = Value::new(1.0);
// this is `newton` in SI,
// but not now because it's currently typed as `((m / s) / s) * kg`
let force = acc * mass;
// lets cast it to newton
let checked_force: Value<_, Newton> =
    // note the `cast_const` here. `f64` is copy, so this cast is const-able.
    // If your value is not copy-able, use `cast` instead.
    force.cast_const();

由于 Rust 的常量评估,类型转换是 编译时检查 的!

为了阐明类型转换检查,考虑以下示例

let s_can_never_be_newton: Value<_, s> = force.cast_const();

上面的示例无法编译,并会抛出一些错误,例如

error[E0080]: evaluation of `<Second as CastFrom<ucsi::ops::Mul<ucsi::ops::Div<ucsi::ops::Div<Meter, Second>, Second>, 
Kilogram>>>::CAN_CAST_FROM` failed
--> D:\WBH\rust\ucsi\ucsi\src\core\units\any.rs:25:9
   |
25 |         panic!("cannot cast si type")
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'cannot cast si type', D:\WBH\rust\ucsi\ucsi\src\core\units\any.rs:25:9
   |
note: inside `is_same_type_or_panic::<ucsi::ops::Mul<ucsi::ops::Div<ucsi::ops::Div<Meter, Second>, Second>, Kilogram>, 
Second>`
--> D:\WBH\rust\ucsi\ucsi\src\core\units\any.rs:25:9
   |
25 |         panic!("cannot cast si type")
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: inside `<Second as CastFrom<ucsi::ops::Mul<ucsi::ops::Div<ucsi::ops::Div<Meter, Second>, Second>, Kilogram>>>::CAN_CAST_FROM`
--> D:\WBH\rust\ucsi\ucsi\src\core\units\any.rs:36:9
   |
36 |         is_same_type_or_panic::<T, B>();
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)

note: the above error was encountered while instantiating `fn ucsi::Value::<f64, ucsi::ops::Mul<ucsi::ops::Div<ucsi::ops::Div<ucsi::units::base::Meter, ucsi::units::base::Second>, ucsi::units::base::Second>, ucsi::units::base::Kilogram>>::cast_const::<ucsi::units::base::Second>`
--> ucsi-test\tests\test_ops.rs:26:25
   |
26 |     let s_can_never_be_newton: Value<_, s> = force.cast_const();
   |                                              ^^^^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0080`.

好吧,报告的信息可能有点多。由于 Rust 的常量评估和泛型系统仍在快速发展中,这可能会在将来得到改进。

无论如何,我们至少可以在编译时检查单位。

深入了解库

您可以在 units 模块中找到所有提供的内置类型。

如果您想创建自己的良好定义的特殊类型或相关单位,请参阅 macros 模块中的代码生成器。

特性

no_std / no_alloc

此库提供无 std 支持和无分配支持。

如果启用 no_std 功能,则 Stringformat! 将从 ::alloc 导出。

如果启用 no_alloc 功能,则无法使用基于字符串的 API,例如 try_castformat_si

外部crate功能

const_soft_float

默认情况下禁用,包含在 full 功能中。

此库重新导出 const_soft_float crate 的常数浮点数学运算,并提供了库的标准关联单位,为这些类型提供常数转换方法。

许可证

本项目受 MIT 许可证Apache 2.0 许可证 许可。

贡献

该项目仍处于早期开发阶段,因此没有严格的贡献流程,您可以随意打开问题或拉取请求!

依赖关系

~56KB