1#![cfg_attr(not(feature = "std"), no_std)]
10
11pub use uom;
12
13macro_rules! define_storage_wrappers {
14 ($storage_mod:ident, $storage_ty:ty, [$(($unit_mod:ident, $quantity:ident),)+]) => {
15 pub mod $storage_mod {
16 use core::marker::PhantomData;
17 use serde::{Deserialize, Deserializer, Serialize, Serializer};
18
19 #[cfg(feature = "reflect")]
20 use bevy_reflect::Reflect;
21
22 macro_rules! define_quantity {
23 ($unit_mod_name:ident, $quantity_name:ident) => {
24 #[repr(transparent)]
25 #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
26 #[cfg_attr(feature = "reflect", derive(Reflect))]
27 #[cfg_attr(feature = "reflect", reflect(from_reflect = false))]
28 pub struct $quantity_name {
29 pub value: $storage_ty,
30 }
31
32 impl $quantity_name {
33 #[inline]
34 pub fn new<U>(value: $storage_ty) -> Self
35 where
36 U: uom::si::$unit_mod_name::Conversion<$storage_ty>,
37 {
38 Self::from_uom(uom::si::$storage_mod::$quantity_name::new::<U>(value))
39 }
40
41 #[inline]
42 pub fn get<U>(&self) -> $storage_ty
43 where
44 U: uom::si::$unit_mod_name::Conversion<$storage_ty>,
45 {
46 (*self).to_uom().get::<U>()
47 }
48
49 #[inline]
50 pub fn raw(&self) -> $storage_ty {
51 self.value
52 }
53
54 #[inline]
55 pub fn into_uom(self) -> uom::si::$storage_mod::$quantity_name {
56 self.to_uom()
57 }
58
59 #[inline]
60 pub fn as_uom(&self) -> uom::si::$storage_mod::$quantity_name {
61 (*self).to_uom()
62 }
63
64 #[inline]
65 pub fn from_uom(inner: uom::si::$storage_mod::$quantity_name) -> Self {
66 Self::from_base_value(inner.value)
67 }
68
69 #[inline]
70 fn to_uom(self) -> uom::si::$storage_mod::$quantity_name {
71 uom::si::$storage_mod::$quantity_name {
72 dimension: PhantomData,
73 units: PhantomData,
74 value: self.value,
75 }
76 }
77
78 #[inline]
79 fn from_base_value(value: $storage_ty) -> Self {
80 Self { value }
81 }
82 }
83
84 impl Default for $quantity_name {
85 fn default() -> Self {
86 Self::from_base_value(0.0 as $storage_ty)
87 }
88 }
89
90 impl From<uom::si::$storage_mod::$quantity_name> for $quantity_name {
91 fn from(value: uom::si::$storage_mod::$quantity_name) -> Self {
92 Self::from_uom(value)
93 }
94 }
95
96 impl From<$quantity_name> for uom::si::$storage_mod::$quantity_name {
97 fn from(value: $quantity_name) -> Self {
98 value.into_uom()
99 }
100 }
101
102 impl core::ops::Add for $quantity_name {
103 type Output = Self;
104
105 fn add(self, rhs: Self) -> Self::Output {
106 Self::from_base_value(self.raw() + rhs.raw())
107 }
108 }
109
110 impl core::ops::AddAssign for $quantity_name {
111 fn add_assign(&mut self, rhs: Self) {
112 *self = *self + rhs;
113 }
114 }
115
116 impl core::ops::Sub for $quantity_name {
117 type Output = Self;
118
119 fn sub(self, rhs: Self) -> Self::Output {
120 Self::from_base_value(self.raw() - rhs.raw())
121 }
122 }
123
124 impl core::ops::SubAssign for $quantity_name {
125 fn sub_assign(&mut self, rhs: Self) {
126 *self = *self - rhs;
127 }
128 }
129
130 impl core::ops::Mul<$storage_ty> for $quantity_name {
131 type Output = Self;
132
133 fn mul(self, rhs: $storage_ty) -> Self::Output {
134 Self::from_base_value(self.raw() * rhs)
135 }
136 }
137
138 impl core::ops::MulAssign<$storage_ty> for $quantity_name {
139 fn mul_assign(&mut self, rhs: $storage_ty) {
140 *self = *self * rhs;
141 }
142 }
143
144 impl core::ops::Div<$storage_ty> for $quantity_name {
145 type Output = Self;
146
147 fn div(self, rhs: $storage_ty) -> Self::Output {
148 Self::from_base_value(self.raw() / rhs)
149 }
150 }
151
152 impl core::ops::DivAssign<$storage_ty> for $quantity_name {
153 fn div_assign(&mut self, rhs: $storage_ty) {
154 *self = *self / rhs;
155 }
156 }
157
158 impl core::ops::Neg for $quantity_name {
159 type Output = Self;
160
161 fn neg(self) -> Self::Output {
162 Self::from_base_value(-self.raw())
163 }
164 }
165
166 impl Serialize for $quantity_name {
167 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
168 where
169 S: Serializer,
170 {
171 self.raw().serialize(serializer)
172 }
173 }
174
175 impl<'de> Deserialize<'de> for $quantity_name {
176 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
177 where
178 D: Deserializer<'de>,
179 {
180 let value = <$storage_ty>::deserialize(deserializer)?;
181 Ok(Self::from_base_value(value))
182 }
183 }
184
185 impl bincode::Encode for $quantity_name {
186 fn encode<E: bincode::enc::Encoder>(
187 &self,
188 encoder: &mut E,
189 ) -> Result<(), bincode::error::EncodeError> {
190 bincode::Encode::encode(&self.raw(), encoder)
191 }
192 }
193
194 impl<Context> bincode::Decode<Context> for $quantity_name {
195 fn decode<D: bincode::de::Decoder<Context = Context>>(
196 decoder: &mut D,
197 ) -> Result<Self, bincode::error::DecodeError> {
198 let value: $storage_ty = bincode::Decode::decode(decoder)?;
199 Ok(Self::from_base_value(value))
200 }
201 }
202
203 impl<'de, Context> bincode::BorrowDecode<'de, Context> for $quantity_name {
204 fn borrow_decode<D: bincode::de::BorrowDecoder<'de, Context = Context>>(
205 decoder: &mut D,
206 ) -> Result<Self, bincode::error::DecodeError> {
207 <Self as bincode::Decode<Context>>::decode(decoder)
208 }
209 }
210
211 #[cfg(feature = "reflect")]
212 impl bevy_reflect::FromReflect for $quantity_name {
213 fn from_reflect(
214 reflect: &dyn bevy_reflect::PartialReflect,
215 ) -> Option<Self> {
216 if let Some(existing) = reflect.try_downcast_ref::<Self>() {
217 return Some(*existing);
218 }
219
220 reflect
221 .try_downcast_ref::<$storage_ty>()
222 .map(|value| Self::from_base_value(*value))
223 }
224 }
225 };
226 }
227
228 $(define_quantity!($unit_mod, $quantity);)+
229 }
230 };
231}
232
233pub mod si {
234 pub use uom::si::{
235 ISQ, SI, absement, acceleration, action, amount_of_substance, angle, angular_absement,
236 angular_acceleration, angular_jerk, angular_momentum, angular_velocity, area,
237 areal_density_of_states, areal_heat_capacity, areal_mass_density, areal_number_density,
238 areal_number_rate, available_energy, capacitance, catalytic_activity,
239 catalytic_activity_concentration, curvature, diffusion_coefficient, dynamic_viscosity,
240 electric_charge, electric_charge_areal_density, electric_charge_linear_density,
241 electric_charge_volumetric_density, electric_current, electric_current_density,
242 electric_dipole_moment, electric_displacement_field, electric_field, electric_flux,
243 electric_permittivity, electric_potential, electric_quadrupole_moment,
244 electrical_conductance, electrical_conductivity, electrical_mobility,
245 electrical_resistance, electrical_resistivity, energy, force, frequency, frequency_drift,
246 heat_capacity, heat_flux_density, heat_transfer, inductance, information, information_rate,
247 inverse_velocity, jerk, kinematic_viscosity, length, linear_density_of_states,
248 linear_mass_density, linear_number_density, linear_number_rate, linear_power_density,
249 luminance, luminous_intensity, magnetic_field_strength, magnetic_flux,
250 magnetic_flux_density, magnetic_moment, magnetic_permeability, mass, mass_concentration,
251 mass_density, mass_flux, mass_per_energy, mass_rate, molality, molar_concentration,
252 molar_energy, molar_flux, molar_heat_capacity, molar_mass, molar_radioactivity,
253 molar_volume, moment_of_inertia, momentum, power, power_rate, pressure, radiant_exposure,
254 radioactivity, ratio, reciprocal_length, solid_angle, specific_area,
255 specific_heat_capacity, specific_power, specific_radioactivity, specific_volume,
256 surface_electric_current_density, surface_tension, temperature_coefficient,
257 temperature_gradient, temperature_interval, thermal_conductance, thermal_conductivity,
258 thermal_resistance, thermodynamic_temperature, time, torque, velocity, volume, volume_rate,
259 volumetric_density_of_states, volumetric_heat_capacity, volumetric_number_density,
260 volumetric_number_rate, volumetric_power_density,
261 };
262
263 define_storage_wrappers! {
264 f32,
265 f32,
266 [
267 (absement, Absement),
268 (acceleration, Acceleration),
269 (action, Action),
270 (amount_of_substance, AmountOfSubstance),
271 (angle, Angle),
272 (angular_absement, AngularAbsement),
273 (angular_acceleration, AngularAcceleration),
274 (angular_jerk, AngularJerk),
275 (angular_momentum, AngularMomentum),
276 (angular_velocity, AngularVelocity),
277 (area, Area),
278 (areal_density_of_states, ArealDensityOfStates),
279 (areal_heat_capacity, ArealHeatCapacity),
280 (areal_mass_density, ArealMassDensity),
281 (areal_number_density, ArealNumberDensity),
282 (areal_number_rate, ArealNumberRate),
283 (available_energy, AvailableEnergy),
284 (capacitance, Capacitance),
285 (catalytic_activity, CatalyticActivity),
286 (catalytic_activity_concentration, CatalyticActivityConcentration),
287 (curvature, Curvature),
288 (diffusion_coefficient, DiffusionCoefficient),
289 (dynamic_viscosity, DynamicViscosity),
290 (electric_charge, ElectricCharge),
291 (electric_charge_areal_density, ElectricChargeArealDensity),
292 (electric_charge_linear_density, ElectricChargeLinearDensity),
293 (electric_charge_volumetric_density, ElectricChargeVolumetricDensity),
294 (electric_current, ElectricCurrent),
295 (electric_current_density, ElectricCurrentDensity),
296 (electric_dipole_moment, ElectricDipoleMoment),
297 (electric_displacement_field, ElectricDisplacementField),
298 (electric_field, ElectricField),
299 (electric_flux, ElectricFlux),
300 (electric_permittivity, ElectricPermittivity),
301 (electric_potential, ElectricPotential),
302 (electric_quadrupole_moment, ElectricQuadrupoleMoment),
303 (electrical_conductance, ElectricalConductance),
304 (electrical_conductivity, ElectricalConductivity),
305 (electrical_mobility, ElectricalMobility),
306 (electrical_resistance, ElectricalResistance),
307 (electrical_resistivity, ElectricalResistivity),
308 (energy, Energy),
309 (force, Force),
310 (frequency, Frequency),
311 (frequency_drift, FrequencyDrift),
312 (heat_capacity, HeatCapacity),
313 (heat_flux_density, HeatFluxDensity),
314 (heat_transfer, HeatTransfer),
315 (inductance, Inductance),
316 (information, Information),
317 (information_rate, InformationRate),
318 (inverse_velocity, InverseVelocity),
319 (jerk, Jerk),
320 (kinematic_viscosity, KinematicViscosity),
321 (length, Length),
322 (linear_density_of_states, LinearDensityOfStates),
323 (linear_mass_density, LinearMassDensity),
324 (linear_number_density, LinearNumberDensity),
325 (linear_number_rate, LinearNumberRate),
326 (linear_power_density, LinearPowerDensity),
327 (luminance, Luminance),
328 (luminous_intensity, LuminousIntensity),
329 (magnetic_field_strength, MagneticFieldStrength),
330 (magnetic_flux, MagneticFlux),
331 (magnetic_flux_density, MagneticFluxDensity),
332 (magnetic_moment, MagneticMoment),
333 (magnetic_permeability, MagneticPermeability),
334 (mass, Mass),
335 (mass_concentration, MassConcentration),
336 (mass_density, MassDensity),
337 (mass_flux, MassFlux),
338 (mass_per_energy, MassPerEnergy),
339 (mass_rate, MassRate),
340 (molality, Molality),
341 (molar_concentration, MolarConcentration),
342 (molar_energy, MolarEnergy),
343 (molar_flux, MolarFlux),
344 (molar_heat_capacity, MolarHeatCapacity),
345 (molar_mass, MolarMass),
346 (molar_radioactivity, MolarRadioactivity),
347 (molar_volume, MolarVolume),
348 (moment_of_inertia, MomentOfInertia),
349 (momentum, Momentum),
350 (power, Power),
351 (power_rate, PowerRate),
352 (pressure, Pressure),
353 (radiant_exposure, RadiantExposure),
354 (radioactivity, Radioactivity),
355 (ratio, Ratio),
356 (reciprocal_length, ReciprocalLength),
357 (solid_angle, SolidAngle),
358 (specific_area, SpecificArea),
359 (specific_heat_capacity, SpecificHeatCapacity),
360 (specific_power, SpecificPower),
361 (specific_radioactivity, SpecificRadioactivity),
362 (specific_volume, SpecificVolume),
363 (surface_electric_current_density, SurfaceElectricCurrentDensity),
364 (surface_tension, SurfaceTension),
365 (temperature_coefficient, TemperatureCoefficient),
366 (temperature_gradient, TemperatureGradient),
367 (temperature_interval, TemperatureInterval),
368 (thermal_conductance, ThermalConductance),
369 (thermal_conductivity, ThermalConductivity),
370 (thermal_resistance, ThermalResistance),
371 (thermodynamic_temperature, ThermodynamicTemperature),
372 (time, Time),
373 (torque, Torque),
374 (velocity, Velocity),
375 (volume, Volume),
376 (volume_rate, VolumeRate),
377 (volumetric_density_of_states, VolumetricDensityOfStates),
378 (volumetric_heat_capacity, VolumetricHeatCapacity),
379 (volumetric_number_density, VolumetricNumberDensity),
380 (volumetric_number_rate, VolumetricNumberRate),
381 (volumetric_power_density, VolumetricPowerDensity),
382 ]
383 }
384
385 define_storage_wrappers! {
386 f64,
387 f64,
388 [
389 (absement, Absement),
390 (acceleration, Acceleration),
391 (action, Action),
392 (amount_of_substance, AmountOfSubstance),
393 (angle, Angle),
394 (angular_absement, AngularAbsement),
395 (angular_acceleration, AngularAcceleration),
396 (angular_jerk, AngularJerk),
397 (angular_momentum, AngularMomentum),
398 (angular_velocity, AngularVelocity),
399 (area, Area),
400 (areal_density_of_states, ArealDensityOfStates),
401 (areal_heat_capacity, ArealHeatCapacity),
402 (areal_mass_density, ArealMassDensity),
403 (areal_number_density, ArealNumberDensity),
404 (areal_number_rate, ArealNumberRate),
405 (available_energy, AvailableEnergy),
406 (capacitance, Capacitance),
407 (catalytic_activity, CatalyticActivity),
408 (catalytic_activity_concentration, CatalyticActivityConcentration),
409 (curvature, Curvature),
410 (diffusion_coefficient, DiffusionCoefficient),
411 (dynamic_viscosity, DynamicViscosity),
412 (electric_charge, ElectricCharge),
413 (electric_charge_areal_density, ElectricChargeArealDensity),
414 (electric_charge_linear_density, ElectricChargeLinearDensity),
415 (electric_charge_volumetric_density, ElectricChargeVolumetricDensity),
416 (electric_current, ElectricCurrent),
417 (electric_current_density, ElectricCurrentDensity),
418 (electric_dipole_moment, ElectricDipoleMoment),
419 (electric_displacement_field, ElectricDisplacementField),
420 (electric_field, ElectricField),
421 (electric_flux, ElectricFlux),
422 (electric_permittivity, ElectricPermittivity),
423 (electric_potential, ElectricPotential),
424 (electric_quadrupole_moment, ElectricQuadrupoleMoment),
425 (electrical_conductance, ElectricalConductance),
426 (electrical_conductivity, ElectricalConductivity),
427 (electrical_mobility, ElectricalMobility),
428 (electrical_resistance, ElectricalResistance),
429 (electrical_resistivity, ElectricalResistivity),
430 (energy, Energy),
431 (force, Force),
432 (frequency, Frequency),
433 (frequency_drift, FrequencyDrift),
434 (heat_capacity, HeatCapacity),
435 (heat_flux_density, HeatFluxDensity),
436 (heat_transfer, HeatTransfer),
437 (inductance, Inductance),
438 (information, Information),
439 (information_rate, InformationRate),
440 (inverse_velocity, InverseVelocity),
441 (jerk, Jerk),
442 (kinematic_viscosity, KinematicViscosity),
443 (length, Length),
444 (linear_density_of_states, LinearDensityOfStates),
445 (linear_mass_density, LinearMassDensity),
446 (linear_number_density, LinearNumberDensity),
447 (linear_number_rate, LinearNumberRate),
448 (linear_power_density, LinearPowerDensity),
449 (luminance, Luminance),
450 (luminous_intensity, LuminousIntensity),
451 (magnetic_field_strength, MagneticFieldStrength),
452 (magnetic_flux, MagneticFlux),
453 (magnetic_flux_density, MagneticFluxDensity),
454 (magnetic_moment, MagneticMoment),
455 (magnetic_permeability, MagneticPermeability),
456 (mass, Mass),
457 (mass_concentration, MassConcentration),
458 (mass_density, MassDensity),
459 (mass_flux, MassFlux),
460 (mass_per_energy, MassPerEnergy),
461 (mass_rate, MassRate),
462 (molality, Molality),
463 (molar_concentration, MolarConcentration),
464 (molar_energy, MolarEnergy),
465 (molar_flux, MolarFlux),
466 (molar_heat_capacity, MolarHeatCapacity),
467 (molar_mass, MolarMass),
468 (molar_radioactivity, MolarRadioactivity),
469 (molar_volume, MolarVolume),
470 (moment_of_inertia, MomentOfInertia),
471 (momentum, Momentum),
472 (power, Power),
473 (power_rate, PowerRate),
474 (pressure, Pressure),
475 (radiant_exposure, RadiantExposure),
476 (radioactivity, Radioactivity),
477 (ratio, Ratio),
478 (reciprocal_length, ReciprocalLength),
479 (solid_angle, SolidAngle),
480 (specific_area, SpecificArea),
481 (specific_heat_capacity, SpecificHeatCapacity),
482 (specific_power, SpecificPower),
483 (specific_radioactivity, SpecificRadioactivity),
484 (specific_volume, SpecificVolume),
485 (surface_electric_current_density, SurfaceElectricCurrentDensity),
486 (surface_tension, SurfaceTension),
487 (temperature_coefficient, TemperatureCoefficient),
488 (temperature_gradient, TemperatureGradient),
489 (temperature_interval, TemperatureInterval),
490 (thermal_conductance, ThermalConductance),
491 (thermal_conductivity, ThermalConductivity),
492 (thermal_resistance, ThermalResistance),
493 (thermodynamic_temperature, ThermodynamicTemperature),
494 (time, Time),
495 (torque, Torque),
496 (velocity, Velocity),
497 (volume, Volume),
498 (volume_rate, VolumeRate),
499 (volumetric_density_of_states, VolumetricDensityOfStates),
500 (volumetric_heat_capacity, VolumetricHeatCapacity),
501 (volumetric_number_density, VolumetricNumberDensity),
502 (volumetric_number_rate, VolumetricNumberRate),
503 (volumetric_power_density, VolumetricPowerDensity),
504 ]
505 }
506}
507
508#[cfg(all(test, feature = "reflect"))]
509mod tests {
510 use super::si::f32::Velocity;
511 use super::si::velocity::{kilometer_per_hour, meter_per_second};
512 use bevy_reflect::{PartialReflect, Reflect, ReflectRef};
513
514 #[derive(Reflect)]
515 #[reflect(from_reflect = false)]
516 struct Msg {
517 speed: Velocity,
518 }
519
520 #[test]
521 fn reflect_velocity_exposes_value_field() {
522 let msg = Msg {
523 speed: Velocity::new::<kilometer_per_hour>(36.0),
524 };
525
526 assert!(matches!(
527 msg.speed.as_partial_reflect().reflect_ref(),
528 ReflectRef::Struct(_)
529 ));
530 assert_eq!(msg.speed.get::<meter_per_second>(), 10.0);
531
532 let speed_reflected = match msg.as_partial_reflect().reflect_ref() {
533 ReflectRef::Struct(s) => s.field("speed").expect("speed field should exist"),
534 _ => panic!("expected struct reflection"),
535 };
536
537 let speed = speed_reflected
538 .try_downcast_ref::<Velocity>()
539 .expect("speed should downcast to cu29_units::si::f32::Velocity");
540 assert_eq!(speed.raw(), 10.0);
541 assert_eq!(speed.value, 10.0);
542 assert_eq!(speed.get::<meter_per_second>(), 10.0);
543 }
544}