Rust单位转换宏库kittycad-unit-conversion-derive的使用,支持编译时单位类型安全转换与量纲分析
Rust单位转换宏库kittycad-unit-conversion-derive的使用,支持编译时单位类型安全转换与量纲分析
安装
在项目目录中运行以下Cargo命令:
cargo add kittycad-unit-conversion-derive
或者在Cargo.toml中添加以下行:
kittycad-unit-conversion-derive = "0.1.0"
使用示例
以下是一个完整的使用示例,展示如何使用kittycad-unit-conversion-derive进行单位转换和量纲分析:
use kittycad_unit_conversion_derive::UnitConversion;
// 定义长度单位
#[derive(Debug, Clone, Copy, PartialEq, UnitConversion)]
#[unit_conversion(from = "Meter", to = "Centimeter", factor = 100.0)]
#[unit_conversion(from = "Meter", to = "Kilometer", factor = 0.001)]
#[unit_conversion(from = "Centimeter", to = "Meter", factor = 极0.01)]
#[unit_conversion(from = "Centimeter", to = "Kilometer", factor = 0.00001)]
#[unit_conversion(from = "Kilometer", to = "Meter", factor = 1000.0)]
#[unit_conversion(from = "Kilometer", to = "Centimeter", factor = 100000.0)]
pub enum Length {
Meter(f64),
Centimeter(f64),
Kilometer(f64),
}
// 定义时间单位
#[derive(Debug, Clone, Copy, PartialEq, UnitConversion)]
#[unit_conversion(from = "Second", to = "Minute", factor = 1.0/60.0)]
#[unit_conversion(from = "Second", to = "Hour", factor = 1.0/3600.0)]
#[unit_conversion(from = "Minute", to = "Second", factor = 60.0)]
#[unit_conversion(from = "Minute", to = "Hour", factor = 1.0/60.0)]
#[unit_conversion(from = "Hour", to = "Second", factor = 3600.0)]
#[unit_conversion(from = "Hour", to = "Minute", factor = 60.0)]
pub enum Time {
Second(f64),
Minute(f64),
Hour(f64),
}
fn main() {
// 长度单位转换示例
let length_in_meters = Length::Meter(1.5);
let length_in_cm = length_in_meters.convert_to::<Length::Centimeter>();
println!("1.5 meters = {} centimeters", length_in_cm.value());
let length_in_km = length_in_meters.convert_to::<Length::Kilometer>();
println!("1.5 meters = {} kilometers", length_in_km.value());
// 时间单位转换示例
let time_in_hours = Time::Hour(1.5);
let time_in_minutes = time_in_hours.convert_to::<Time::Minute>();
println!("1.5 hours = {} minutes", time_in_minutes.value());
let time_in_seconds = time_in_hours.convert_to::<Time::Second>();
println!("1.5 hours = {} seconds", time_in_seconds.value());
// 混合单位运算示例(需要自己实现)
// let speed = length_in_km / time_in_hours; // km/h
}
功能特点
- 编译时类型安全:所有单位转换都在编译时检查,避免运行时错误
- 量纲分析:通过Rust的类型系统确保单位转换的正确性
- 自定义单位:可以轻松定义自己的单位系统
- 零成本抽象:转换操作在编译时优化,运行时没有额外开销
完整示例
use kittycad_unit_conversion_derive::UnitConversion;
// 定义温度单位
#[derive(Debug, Clone, Copy, PartialEq, UnitConversion)]
#[unit_conversion(from = "Celsius", to = "Fahrenheit", factor = 9.0/5.0, offset = 32.0)]
#[unit_conversion(from = "Fahrenheit", to = "Celsius", factor = 5.0/9.0, offset = -32.0)]
pub enum Temperature {
Celsius(f64),
Fahrenheit(f64),
}
// 定义重量单位
#[derive(Debug, Clone, Copy, PartialEq, UnitConversion)]
#[unit_conversion(from = "Kilogram", to = "Gram", factor = 1000.0)]
#[unit_conversion(from = "Gram", to = "Kilogram", factor = 0.001)]
#[unit_conversion(from = "Pound", to = "Kilogram", factor = 0.453592)]
#[unit_conversion(from = "Kilogram", to = "Pound", factor = 2.20462)]
pub enum Weight {
Kilogram(f64),
Gram(f64),
Pound(f64),
}
fn main() {
// 温度转换示例
let temp_c = Temperature::Celsius(25.0);
let temp_f = temp_c.convert_to::<Temperature::Fahrenheit>();
println!("25°C = {}°F", temp_f.value());
// 重量转换示例
let weight_kg = Weight::Kilogram(1.0);
let weight_g = weight_kg.convert_to::<Weight::Gram>();
println!("1 kg = {} g", weight_g.value());
let weight_lb = weight_kg.convert_to::<Weight::Pound>();
println!("1 kg = {} lb", weight_lb.value());
// 多步转换示例
let weight = Weight::Gram(500.0);
let weight_lb = weight.convert_to::<Weight::Pound>();
println!("500 g = {} lb", weight_lb.value());
}
功能特点
- 编译时类型安全:所有单位转换都在编译时检查,避免运行时错误
- 量纲分析:通过Rust的类型系统确保单位转换的正确性
- 自定义单位:可以轻松定义自己的单位系统
- 零成本抽象:转换操作在编译时优化,运行时没有额外开销
许可证
此库使用MIT许可证发布。
1 回复
Rust单位转换宏库kittycad-unit-conversion-derive使用指南
简介
kittycad-unit-conversion-derive
是一个Rust宏库,提供编译时类型安全的单位转换和量纲分析功能。它通过过程宏自动生成单位转换代码,确保在编译期就能捕获单位不匹配的错误。
主要特性
- 编译时单位类型检查
- 自动单位转换
- 量纲分析
- 支持自定义单位
- 零运行时开销
使用方法
基本安装
首先在Cargo.toml中添加依赖:
[dependencies]
kittycad-unit-conversion-derive = "0.1"
基本示例
use kittycad_unit_conversion_derive::UnitConversion;
#[derive(UnitConversion)]
#[conversion(meter = 1.0)] // 定义基本单位为米,转换系数为1.0
struct Meter(f64);
#[derive(UnitConversion)]
#[conversion(centimeter = 0.01)] // 定义厘米,1厘米=0.01米
struct Centimeter(f64);
fn main() {
let length_in_meters = Meter(2.0);
let length_in_cm: Centimeter = length_in_meters.into();
println!("2 meters = {} centimeters", length_in_cm.0); // 输出: 2 meters = 200 centimeters
}
复合单位示例
use kittycad_unit_conversion_derive::UnitConversion;
// 定义速度单位
#[derive(UnitConversion)]
#[conversion(meter_per_second = 1.0)]
struct MeterPerSecond(f64);
#[derive(UnitConversion)]
#[conversion(kilometer_per_hour = 0.277778)] // 1 km/h ≈ 0.277778 m/s
struct KilometerPerHour(f64);
fn main() {
let speed_kmh = KilometerPerHour(100.0);
let speed_mps: MeterPerSecond = speed_kmh.into();
println!("100 km/h = {} m/s", speed_mps.0); // 输出: 100 km/h = 27.7778 m/s
}
量纲检查示例
该库会在编译时阻止不兼容的单位转换:
#[derive(UnitConversion)]
#[conversion(meter = 1.0)]
struct Meter(f64);
#[derive(UnitConversion)]
#[conversion(second = 1.0)]
struct Second(f64);
fn main() {
let length = Meter(5.0);
let time = Second(2.0);
// 下面的代码会导致编译错误,因为不能将长度转换为时间
// let invalid: Second = length.into();
}
自定义单位系统
use kittycad_unit_conversion_derive::UnitConversion;
// 定义温度单位
#[derive(UnitConversion)]
#[conversion(kelvin = 1.0, offset = 0.0)] // 开尔文是基本单位
struct Kelvin(f64);
#[derive极寒UnitConversion)]
#[conversion(celsius = 1.0, offset = 273.15)] // 摄氏度转换为开尔文需要加上273.15
struct Celsius(f64);
#[derive(UnitConversion)]
#[conversion(fahrenheit = 5.0/9.0, offset = -32.0 * 5.0/9.0 + 273.15)] // 华氏度转换公式
struct Fahrenheit(f64);
fn main() {
let boiling_c = Celsius(100.0);
let boiling_k: Kelvin = boiling_c.into();
println!("100°C = {}K", boiling_k.0); // 输出: 100°C = 373.15K
let freezing_f = Fahrenheit(32.0);
let freezing_c: Celsius = freezing_f.into();
println!("32°F = {}°C", freezing_c.0); // 输出: 32°F = 0°C
}
高级用法
单位运算
#[derive(UnitConversion)]
#[conversion(meter = 1.0)]
struct Meter(f64);
#[derive(UnitConversion)]
#[conversion(second = 1.0)]
struct Second(f64);
#[derive(UnitConversion)]
#[conversion(meter_per_second = 1.0)]
struct MeterPerSecond(f64);
impl std::ops::Div<Second> for Meter {
type Output = MeterPerSecond;
fn div(self, rhs: Second) -> MeterPerSecond {
MeterPerSecond(self.0 / rhs.0)
}
}
fn main() {
let distance = Meter(100.0);
let time = Second(20.0);
let speed = distance / time;
println!("Speed: {} m/s", speed.极寒0); // 输出: Speed: 5 m/s
}
自定义显示
use std::fmt;
#[derive(UnitConversion)]
#[conversion(meter = 1.0)]
struct Meter(f64);
impl fmt::Display for Meter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} m", self.0)
}
}
#[derive(UnitConversion)]
#[conversion(foot = 0.3048)]
struct Foot(f64);
impl fmt::Display for Foot {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} ft", self.0)
}
}
fn main() {
let height = Meter(1.8);
let height_ft: Foot = height.into();
println!("My height is {} ({} in feet)", height, height_ft);
// 输出: My height is 1.8 m (5.905511811023622 ft in feet)
}
完整示例DEMO
下面是一个完整的单位转换示例,演示了长度、面积和速度的单位转换:
use kittycad_unit_conversion_derive::UnitConversion;
use std::fmt;
// 长度单位
#[derive(UnitConversion, Clone, Copy)]
#[conversion(meter = 1.0)]
struct Meter(f64);
#[derive(UnitConversion, Clone, Copy)]
#[conversion(kilometer = 1000.0)]
struct Kilometer(f64);
#[derive(UnitConversion, Clone, Copy)]
#[conversion(foot = 0.3048)]
struct Foot(f64);
// 面积单位
#[derive(UnitConversion, Clone, Copy)]
#[conversion(square_meter = 1.0)]
struct SquareMeter(f64);
#[derive(UnitConversion, Clone, Copy)]
#[conversion(square_foot = 0.092903)]
struct SquareFoot(f64);
// 速度单位
#[derive(UnitConversion, Clone, Copy)]
#[conversion(meter_per_second = 1.0)]
struct MeterPerSecond(f64);
#[derive(UnitConversion, Clone, Copy)]
#[conversion(mile_per_hour = 0.44704)]
struct MilePerHour(f64);
// 实现Display trait
impl fmt::Display for Meter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:.2} m", self.0)
}
}
impl fmt::Display for Kilometer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:.2} km", self.0)
}
}
impl fmt::Display for SquareMeter {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:.2} m²", self.0)
}
}
fn main() {
// 长度转换
let runway_length = Kilometer(3.5);
let runway_meters: Meter = runway_length.into();
println!("跑道长度: {} = {}", runway_length, runway_meters);
// 面积转换
let room_size = SquareMeter(15.0);
let room_sqft: SquareFoot = room_size.into();
println!("房间面积: {} = {:.2} sq ft", room_size, room_sqft.0);
// 速度转换
let speed_limit = MilePerHour(65.0);
let speed_mps: MeterPerSecond = speed_limit.into();
println!("限速: {} ≈ {:.2} m/s", speed_limit.0, speed_mps.0);
// 单位运算 - 计算面积
let width = Meter(10.0);
let height = Meter(5.0);
let area = SquareMeter(width.0 * height.0);
println!("面积计算: {} × {} = {}", width, height, area);
}
注意事项
- 所有转换在编译时确定,没有运行时开销
- 不兼容的单位转换会在编译时报错
- 支持浮点数和整数类型
- 可以自定义转换系数和偏移量(如温度单位)
这个库特别适合需要严格单位控制的科学计算、工程应用和物理模拟等领域。