Skip to main content

cu29_units/
lib.rs

1//! Copper-native SI quantity wrappers.
2//!
3//! Feature flags:
4//! - `default` = `["std"]`
5//! - `std`: enables `uom/std`
6//! - `reflect`: enables `bevy_reflect` support on wrapper types
7//! - `textlogs`: compatibility no-op for downstream feature forwarding
8//!
9#![cfg_attr(not(feature = "std"), no_std)]
10
11extern crate alloc;
12
13pub use uom;
14
15macro_rules! define_storage_wrappers {
16    ($storage_mod:ident, $storage_ty:ty, [$(($unit_mod:ident, $quantity:ident),)+]) => {
17        pub mod $storage_mod {
18            use core::marker::PhantomData;
19            use serde::{Deserialize, Deserializer, Serialize, Serializer};
20
21            #[cfg(feature = "reflect")]
22            use bevy_reflect::Reflect;
23
24            macro_rules! define_quantity {
25                ($unit_mod_name:ident, $quantity_name:ident) => {
26                    #[repr(transparent)]
27                    #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
28                    #[cfg_attr(feature = "reflect", derive(Reflect))]
29                    #[cfg_attr(feature = "reflect", reflect(from_reflect = false))]
30                    pub struct $quantity_name {
31                        pub value: $storage_ty,
32                    }
33
34                    impl $quantity_name {
35                        #[inline]
36                        pub fn new<U>(value: $storage_ty) -> Self
37                        where
38                            U: uom::si::$unit_mod_name::Conversion<$storage_ty>,
39                        {
40                            Self::from_uom(uom::si::$storage_mod::$quantity_name::new::<U>(value))
41                        }
42
43                        #[inline]
44                        pub fn get<U>(&self) -> $storage_ty
45                        where
46                            U: uom::si::$unit_mod_name::Conversion<$storage_ty>,
47                        {
48                            (*self).to_uom().get::<U>()
49                        }
50
51                        #[inline]
52                        pub fn raw(&self) -> $storage_ty {
53                            self.value
54                        }
55
56                        #[inline]
57                        pub fn into_uom(self) -> uom::si::$storage_mod::$quantity_name {
58                            self.to_uom()
59                        }
60
61                        #[inline]
62                        pub fn as_uom(&self) -> uom::si::$storage_mod::$quantity_name {
63                            (*self).to_uom()
64                        }
65
66                        #[inline]
67                        pub fn from_uom(inner: uom::si::$storage_mod::$quantity_name) -> Self {
68                            Self::from_base_value(inner.value)
69                        }
70
71                        #[inline]
72                        fn to_uom(self) -> uom::si::$storage_mod::$quantity_name {
73                            uom::si::$storage_mod::$quantity_name {
74                                dimension: PhantomData,
75                                units: PhantomData,
76                                value: self.value,
77                            }
78                        }
79
80                        #[inline]
81                        fn from_base_value(value: $storage_ty) -> Self {
82                            Self { value }
83                        }
84                    }
85
86                    impl Default for $quantity_name {
87                        fn default() -> Self {
88                            Self::from_base_value(0.0 as $storage_ty)
89                        }
90                    }
91
92                    impl From<uom::si::$storage_mod::$quantity_name> for $quantity_name {
93                        fn from(value: uom::si::$storage_mod::$quantity_name) -> Self {
94                            Self::from_uom(value)
95                        }
96                    }
97
98                    impl From<$quantity_name> for uom::si::$storage_mod::$quantity_name {
99                        fn from(value: $quantity_name) -> Self {
100                            value.into_uom()
101                        }
102                    }
103
104                    impl core::ops::Add for $quantity_name {
105                        type Output = Self;
106
107                        fn add(self, rhs: Self) -> Self::Output {
108                            Self::from_base_value(self.raw() + rhs.raw())
109                        }
110                    }
111
112                    impl core::ops::AddAssign for $quantity_name {
113                        fn add_assign(&mut self, rhs: Self) {
114                            *self = *self + rhs;
115                        }
116                    }
117
118                    impl core::ops::Sub for $quantity_name {
119                        type Output = Self;
120
121                        fn sub(self, rhs: Self) -> Self::Output {
122                            Self::from_base_value(self.raw() - rhs.raw())
123                        }
124                    }
125
126                    impl core::ops::SubAssign for $quantity_name {
127                        fn sub_assign(&mut self, rhs: Self) {
128                            *self = *self - rhs;
129                        }
130                    }
131
132                    impl core::ops::Mul<$storage_ty> for $quantity_name {
133                        type Output = Self;
134
135                        fn mul(self, rhs: $storage_ty) -> Self::Output {
136                            Self::from_base_value(self.raw() * rhs)
137                        }
138                    }
139
140                    impl core::ops::MulAssign<$storage_ty> for $quantity_name {
141                        fn mul_assign(&mut self, rhs: $storage_ty) {
142                            *self = *self * rhs;
143                        }
144                    }
145
146                    impl core::ops::Div<$storage_ty> for $quantity_name {
147                        type Output = Self;
148
149                        fn div(self, rhs: $storage_ty) -> Self::Output {
150                            Self::from_base_value(self.raw() / rhs)
151                        }
152                    }
153
154                    impl core::ops::DivAssign<$storage_ty> for $quantity_name {
155                        fn div_assign(&mut self, rhs: $storage_ty) {
156                            *self = *self / rhs;
157                        }
158                    }
159
160                    impl core::ops::Neg for $quantity_name {
161                        type Output = Self;
162
163                        fn neg(self) -> Self::Output {
164                            Self::from_base_value(-self.raw())
165                        }
166                    }
167
168                    impl Serialize for $quantity_name {
169                        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
170                        where
171                            S: Serializer,
172                        {
173                            self.raw().serialize(serializer)
174                        }
175                    }
176
177                    impl<'de> Deserialize<'de> for $quantity_name {
178                        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
179                        where
180                            D: Deserializer<'de>,
181                        {
182                            let value = <$storage_ty>::deserialize(deserializer)?;
183                            Ok(Self::from_base_value(value))
184                        }
185                    }
186
187                    impl bincode::Encode for $quantity_name {
188                        fn encode<E: bincode::enc::Encoder>(
189                            &self,
190                            encoder: &mut E,
191                        ) -> Result<(), bincode::error::EncodeError> {
192                            bincode::Encode::encode(&self.raw(), encoder)
193                        }
194                    }
195
196                    impl<Context> bincode::Decode<Context> for $quantity_name {
197                        fn decode<D: bincode::de::Decoder<Context = Context>>(
198                            decoder: &mut D,
199                        ) -> Result<Self, bincode::error::DecodeError> {
200                            let value: $storage_ty = bincode::Decode::decode(decoder)?;
201                            Ok(Self::from_base_value(value))
202                        }
203                    }
204
205                    impl<'de, Context> bincode::BorrowDecode<'de, Context> for $quantity_name {
206                        fn borrow_decode<D: bincode::de::BorrowDecoder<'de, Context = Context>>(
207                            decoder: &mut D,
208                        ) -> Result<Self, bincode::error::DecodeError> {
209                            <Self as bincode::Decode<Context>>::decode(decoder)
210                        }
211                    }
212
213                    #[cfg(feature = "reflect")]
214                    impl bevy_reflect::FromReflect for $quantity_name {
215                        fn from_reflect(
216                            reflect: &dyn bevy_reflect::PartialReflect,
217                        ) -> Option<Self> {
218                            if let Some(existing) = reflect.try_downcast_ref::<Self>() {
219                                return Some(*existing);
220                            }
221
222                            reflect
223                                .try_downcast_ref::<$storage_ty>()
224                                .map(|value| Self::from_base_value(*value))
225                        }
226                    }
227                };
228            }
229
230            $(define_quantity!($unit_mod, $quantity);)+
231        }
232    };
233}
234
235pub mod si {
236    pub use uom::si::{
237        ISQ, SI, absement, acceleration, action, amount_of_substance, angle, angular_absement,
238        angular_acceleration, angular_jerk, angular_momentum, angular_velocity, area,
239        areal_density_of_states, areal_heat_capacity, areal_mass_density, areal_number_density,
240        areal_number_rate, available_energy, capacitance, catalytic_activity,
241        catalytic_activity_concentration, curvature, diffusion_coefficient, dynamic_viscosity,
242        electric_charge, electric_charge_areal_density, electric_charge_linear_density,
243        electric_charge_volumetric_density, electric_current, electric_current_density,
244        electric_dipole_moment, electric_displacement_field, electric_field, electric_flux,
245        electric_permittivity, electric_potential, electric_quadrupole_moment,
246        electrical_conductance, electrical_conductivity, electrical_mobility,
247        electrical_resistance, electrical_resistivity, energy, force, frequency, frequency_drift,
248        heat_capacity, heat_flux_density, heat_transfer, inductance, information, information_rate,
249        inverse_velocity, jerk, kinematic_viscosity, length, linear_density_of_states,
250        linear_mass_density, linear_number_density, linear_number_rate, linear_power_density,
251        luminance, luminous_intensity, magnetic_field_strength, magnetic_flux,
252        magnetic_flux_density, magnetic_moment, magnetic_permeability, mass, mass_concentration,
253        mass_density, mass_flux, mass_per_energy, mass_rate, molality, molar_concentration,
254        molar_energy, molar_flux, molar_heat_capacity, molar_mass, molar_radioactivity,
255        molar_volume, moment_of_inertia, momentum, power, power_rate, pressure, radiant_exposure,
256        radioactivity, ratio, reciprocal_length, solid_angle, specific_area,
257        specific_heat_capacity, specific_power, specific_radioactivity, specific_volume,
258        surface_electric_current_density, surface_tension, temperature_coefficient,
259        temperature_gradient, temperature_interval, thermal_conductance, thermal_conductivity,
260        thermal_resistance, thermodynamic_temperature, time, torque, velocity, volume, volume_rate,
261        volumetric_density_of_states, volumetric_heat_capacity, volumetric_number_density,
262        volumetric_number_rate, volumetric_power_density,
263    };
264
265    define_storage_wrappers! {
266        f32,
267        f32,
268        [
269            (absement, Absement),
270            (acceleration, Acceleration),
271            (action, Action),
272            (amount_of_substance, AmountOfSubstance),
273            (angle, Angle),
274            (angular_absement, AngularAbsement),
275            (angular_acceleration, AngularAcceleration),
276            (angular_jerk, AngularJerk),
277            (angular_momentum, AngularMomentum),
278            (angular_velocity, AngularVelocity),
279            (area, Area),
280            (areal_density_of_states, ArealDensityOfStates),
281            (areal_heat_capacity, ArealHeatCapacity),
282            (areal_mass_density, ArealMassDensity),
283            (areal_number_density, ArealNumberDensity),
284            (areal_number_rate, ArealNumberRate),
285            (available_energy, AvailableEnergy),
286            (capacitance, Capacitance),
287            (catalytic_activity, CatalyticActivity),
288            (catalytic_activity_concentration, CatalyticActivityConcentration),
289            (curvature, Curvature),
290            (diffusion_coefficient, DiffusionCoefficient),
291            (dynamic_viscosity, DynamicViscosity),
292            (electric_charge, ElectricCharge),
293            (electric_charge_areal_density, ElectricChargeArealDensity),
294            (electric_charge_linear_density, ElectricChargeLinearDensity),
295            (electric_charge_volumetric_density, ElectricChargeVolumetricDensity),
296            (electric_current, ElectricCurrent),
297            (electric_current_density, ElectricCurrentDensity),
298            (electric_dipole_moment, ElectricDipoleMoment),
299            (electric_displacement_field, ElectricDisplacementField),
300            (electric_field, ElectricField),
301            (electric_flux, ElectricFlux),
302            (electric_permittivity, ElectricPermittivity),
303            (electric_potential, ElectricPotential),
304            (electric_quadrupole_moment, ElectricQuadrupoleMoment),
305            (electrical_conductance, ElectricalConductance),
306            (electrical_conductivity, ElectricalConductivity),
307            (electrical_mobility, ElectricalMobility),
308            (electrical_resistance, ElectricalResistance),
309            (electrical_resistivity, ElectricalResistivity),
310            (energy, Energy),
311            (force, Force),
312            (frequency, Frequency),
313            (frequency_drift, FrequencyDrift),
314            (heat_capacity, HeatCapacity),
315            (heat_flux_density, HeatFluxDensity),
316            (heat_transfer, HeatTransfer),
317            (inductance, Inductance),
318            (information, Information),
319            (information_rate, InformationRate),
320            (inverse_velocity, InverseVelocity),
321            (jerk, Jerk),
322            (kinematic_viscosity, KinematicViscosity),
323            (length, Length),
324            (linear_density_of_states, LinearDensityOfStates),
325            (linear_mass_density, LinearMassDensity),
326            (linear_number_density, LinearNumberDensity),
327            (linear_number_rate, LinearNumberRate),
328            (linear_power_density, LinearPowerDensity),
329            (luminance, Luminance),
330            (luminous_intensity, LuminousIntensity),
331            (magnetic_field_strength, MagneticFieldStrength),
332            (magnetic_flux, MagneticFlux),
333            (magnetic_flux_density, MagneticFluxDensity),
334            (magnetic_moment, MagneticMoment),
335            (magnetic_permeability, MagneticPermeability),
336            (mass, Mass),
337            (mass_concentration, MassConcentration),
338            (mass_density, MassDensity),
339            (mass_flux, MassFlux),
340            (mass_per_energy, MassPerEnergy),
341            (mass_rate, MassRate),
342            (molality, Molality),
343            (molar_concentration, MolarConcentration),
344            (molar_energy, MolarEnergy),
345            (molar_flux, MolarFlux),
346            (molar_heat_capacity, MolarHeatCapacity),
347            (molar_mass, MolarMass),
348            (molar_radioactivity, MolarRadioactivity),
349            (molar_volume, MolarVolume),
350            (moment_of_inertia, MomentOfInertia),
351            (momentum, Momentum),
352            (power, Power),
353            (power_rate, PowerRate),
354            (pressure, Pressure),
355            (radiant_exposure, RadiantExposure),
356            (radioactivity, Radioactivity),
357            (ratio, Ratio),
358            (reciprocal_length, ReciprocalLength),
359            (solid_angle, SolidAngle),
360            (specific_area, SpecificArea),
361            (specific_heat_capacity, SpecificHeatCapacity),
362            (specific_power, SpecificPower),
363            (specific_radioactivity, SpecificRadioactivity),
364            (specific_volume, SpecificVolume),
365            (surface_electric_current_density, SurfaceElectricCurrentDensity),
366            (surface_tension, SurfaceTension),
367            (temperature_coefficient, TemperatureCoefficient),
368            (temperature_gradient, TemperatureGradient),
369            (temperature_interval, TemperatureInterval),
370            (thermal_conductance, ThermalConductance),
371            (thermal_conductivity, ThermalConductivity),
372            (thermal_resistance, ThermalResistance),
373            (thermodynamic_temperature, ThermodynamicTemperature),
374            (time, Time),
375            (torque, Torque),
376            (velocity, Velocity),
377            (volume, Volume),
378            (volume_rate, VolumeRate),
379            (volumetric_density_of_states, VolumetricDensityOfStates),
380            (volumetric_heat_capacity, VolumetricHeatCapacity),
381            (volumetric_number_density, VolumetricNumberDensity),
382            (volumetric_number_rate, VolumetricNumberRate),
383            (volumetric_power_density, VolumetricPowerDensity),
384        ]
385    }
386
387    define_storage_wrappers! {
388        f64,
389        f64,
390        [
391            (absement, Absement),
392            (acceleration, Acceleration),
393            (action, Action),
394            (amount_of_substance, AmountOfSubstance),
395            (angle, Angle),
396            (angular_absement, AngularAbsement),
397            (angular_acceleration, AngularAcceleration),
398            (angular_jerk, AngularJerk),
399            (angular_momentum, AngularMomentum),
400            (angular_velocity, AngularVelocity),
401            (area, Area),
402            (areal_density_of_states, ArealDensityOfStates),
403            (areal_heat_capacity, ArealHeatCapacity),
404            (areal_mass_density, ArealMassDensity),
405            (areal_number_density, ArealNumberDensity),
406            (areal_number_rate, ArealNumberRate),
407            (available_energy, AvailableEnergy),
408            (capacitance, Capacitance),
409            (catalytic_activity, CatalyticActivity),
410            (catalytic_activity_concentration, CatalyticActivityConcentration),
411            (curvature, Curvature),
412            (diffusion_coefficient, DiffusionCoefficient),
413            (dynamic_viscosity, DynamicViscosity),
414            (electric_charge, ElectricCharge),
415            (electric_charge_areal_density, ElectricChargeArealDensity),
416            (electric_charge_linear_density, ElectricChargeLinearDensity),
417            (electric_charge_volumetric_density, ElectricChargeVolumetricDensity),
418            (electric_current, ElectricCurrent),
419            (electric_current_density, ElectricCurrentDensity),
420            (electric_dipole_moment, ElectricDipoleMoment),
421            (electric_displacement_field, ElectricDisplacementField),
422            (electric_field, ElectricField),
423            (electric_flux, ElectricFlux),
424            (electric_permittivity, ElectricPermittivity),
425            (electric_potential, ElectricPotential),
426            (electric_quadrupole_moment, ElectricQuadrupoleMoment),
427            (electrical_conductance, ElectricalConductance),
428            (electrical_conductivity, ElectricalConductivity),
429            (electrical_mobility, ElectricalMobility),
430            (electrical_resistance, ElectricalResistance),
431            (electrical_resistivity, ElectricalResistivity),
432            (energy, Energy),
433            (force, Force),
434            (frequency, Frequency),
435            (frequency_drift, FrequencyDrift),
436            (heat_capacity, HeatCapacity),
437            (heat_flux_density, HeatFluxDensity),
438            (heat_transfer, HeatTransfer),
439            (inductance, Inductance),
440            (information, Information),
441            (information_rate, InformationRate),
442            (inverse_velocity, InverseVelocity),
443            (jerk, Jerk),
444            (kinematic_viscosity, KinematicViscosity),
445            (length, Length),
446            (linear_density_of_states, LinearDensityOfStates),
447            (linear_mass_density, LinearMassDensity),
448            (linear_number_density, LinearNumberDensity),
449            (linear_number_rate, LinearNumberRate),
450            (linear_power_density, LinearPowerDensity),
451            (luminance, Luminance),
452            (luminous_intensity, LuminousIntensity),
453            (magnetic_field_strength, MagneticFieldStrength),
454            (magnetic_flux, MagneticFlux),
455            (magnetic_flux_density, MagneticFluxDensity),
456            (magnetic_moment, MagneticMoment),
457            (magnetic_permeability, MagneticPermeability),
458            (mass, Mass),
459            (mass_concentration, MassConcentration),
460            (mass_density, MassDensity),
461            (mass_flux, MassFlux),
462            (mass_per_energy, MassPerEnergy),
463            (mass_rate, MassRate),
464            (molality, Molality),
465            (molar_concentration, MolarConcentration),
466            (molar_energy, MolarEnergy),
467            (molar_flux, MolarFlux),
468            (molar_heat_capacity, MolarHeatCapacity),
469            (molar_mass, MolarMass),
470            (molar_radioactivity, MolarRadioactivity),
471            (molar_volume, MolarVolume),
472            (moment_of_inertia, MomentOfInertia),
473            (momentum, Momentum),
474            (power, Power),
475            (power_rate, PowerRate),
476            (pressure, Pressure),
477            (radiant_exposure, RadiantExposure),
478            (radioactivity, Radioactivity),
479            (ratio, Ratio),
480            (reciprocal_length, ReciprocalLength),
481            (solid_angle, SolidAngle),
482            (specific_area, SpecificArea),
483            (specific_heat_capacity, SpecificHeatCapacity),
484            (specific_power, SpecificPower),
485            (specific_radioactivity, SpecificRadioactivity),
486            (specific_volume, SpecificVolume),
487            (surface_electric_current_density, SurfaceElectricCurrentDensity),
488            (surface_tension, SurfaceTension),
489            (temperature_coefficient, TemperatureCoefficient),
490            (temperature_gradient, TemperatureGradient),
491            (temperature_interval, TemperatureInterval),
492            (thermal_conductance, ThermalConductance),
493            (thermal_conductivity, ThermalConductivity),
494            (thermal_resistance, ThermalResistance),
495            (thermodynamic_temperature, ThermodynamicTemperature),
496            (time, Time),
497            (torque, Torque),
498            (velocity, Velocity),
499            (volume, Volume),
500            (volume_rate, VolumeRate),
501            (volumetric_density_of_states, VolumetricDensityOfStates),
502            (volumetric_heat_capacity, VolumetricHeatCapacity),
503            (volumetric_number_density, VolumetricNumberDensity),
504            (volumetric_number_rate, VolumetricNumberRate),
505            (volumetric_power_density, VolumetricPowerDensity),
506        ]
507    }
508}
509
510use alloc::string::ToString;
511use alloc::vec::Vec;
512use cu29_traits::{DebugFieldSemantics, DebugScalarRegistration, DebugScalarType};
513
514macro_rules! impl_debug_scalar_units {
515    ($(($unit_mod:ident, $quantity:ident, $base_unit:ident),)+) => {
516        macro_rules! impl_storage_debug_scalar_units {
517            ($storage_mod:ident, $storage_ty:ty) => {
518                $(
519                    impl DebugScalarType for si::$storage_mod::$quantity {
520                        fn debug_scalar_registration() -> DebugScalarRegistration {
521                            DebugScalarRegistration {
522                                type_path: core::any::type_name::<Self>(),
523                                field_type: if stringify!($storage_ty).starts_with('f') {
524                                    "number"
525                                } else {
526                                    "integer"
527                                },
528                                semantics: DebugFieldSemantics::Quantity {
529                                    quantity_name: stringify!($quantity).to_string(),
530                                    unit_symbol: <uom::si::$unit_mod::$base_unit as uom::si::Unit>::abbreviation()
531                                        .to_string(),
532                                },
533                            }
534                        }
535                    }
536                )+
537            };
538        }
539
540        impl_storage_debug_scalar_units!(f32, f32);
541        impl_storage_debug_scalar_units!(f64, f64);
542
543        pub fn debug_scalar_registrations() -> Vec<DebugScalarRegistration> {
544            alloc::vec![
545                $(
546                    <si::f32::$quantity as DebugScalarType>::debug_scalar_registration(),
547                    <si::f64::$quantity as DebugScalarType>::debug_scalar_registration(),
548                )+
549            ]
550        }
551    };
552}
553
554impl_debug_scalar_units! {
555    (absement, Absement, meter_second),
556    (acceleration, Acceleration, meter_per_second_squared),
557    (action, Action, joule_second),
558    (amount_of_substance, AmountOfSubstance, mole),
559    (angle, Angle, radian),
560    (angular_absement, AngularAbsement, radian_second),
561    (angular_acceleration, AngularAcceleration, radian_per_second_squared),
562    (angular_jerk, AngularJerk, radian_per_second_cubed),
563    (angular_momentum, AngularMomentum, newton_meter_second),
564    (angular_velocity, AngularVelocity, radian_per_second),
565    (area, Area, square_meter),
566    (areal_density_of_states, ArealDensityOfStates, state_per_square_meter_joule),
567    (areal_heat_capacity, ArealHeatCapacity, joule_per_square_meter_kelvin),
568    (areal_mass_density, ArealMassDensity, kilogram_per_square_meter),
569    (areal_number_density, ArealNumberDensity, per_square_kilometer),
570    (areal_number_rate, ArealNumberRate, per_square_meter_second),
571    (available_energy, AvailableEnergy, joule_per_kilogram),
572    (capacitance, Capacitance, farad),
573    (catalytic_activity, CatalyticActivity, katal),
574    (catalytic_activity_concentration, CatalyticActivityConcentration, katal_per_cubic_meter),
575    (curvature, Curvature, radian_per_meter),
576    (diffusion_coefficient, DiffusionCoefficient, square_meter_per_second),
577    (dynamic_viscosity, DynamicViscosity, pascal_second),
578    (electric_charge, ElectricCharge, coulomb),
579    (electric_charge_areal_density, ElectricChargeArealDensity, coulomb_per_square_meter),
580    (electric_charge_linear_density, ElectricChargeLinearDensity, coulomb_per_meter),
581    (electric_charge_volumetric_density, ElectricChargeVolumetricDensity, coulomb_per_cubic_meter),
582    (electric_current, ElectricCurrent, ampere),
583    (electric_current_density, ElectricCurrentDensity, ampere_per_square_meter),
584    (electric_dipole_moment, ElectricDipoleMoment, coulomb_meter),
585    (electric_displacement_field, ElectricDisplacementField, coulomb_per_square_meter),
586    (electric_field, ElectricField, volt_per_meter),
587    (electric_flux, ElectricFlux, volt_meter),
588    (electric_permittivity, ElectricPermittivity, farad_per_meter),
589    (electric_potential, ElectricPotential, volt),
590    (electric_quadrupole_moment, ElectricQuadrupoleMoment, coulomb_square_meter),
591    (electrical_conductance, ElectricalConductance, siemens),
592    (electrical_conductivity, ElectricalConductivity, siemens_per_meter),
593    (electrical_mobility, ElectricalMobility, square_meter_per_volt_second),
594    (electrical_resistance, ElectricalResistance, ohm),
595    (electrical_resistivity, ElectricalResistivity, ohm_meter),
596    (energy, Energy, joule),
597    (force, Force, newton),
598    (frequency, Frequency, hertz),
599    (frequency_drift, FrequencyDrift, hertz_per_second),
600    (heat_capacity, HeatCapacity, gram_square_meter_per_second_squared_kelvin),
601    (heat_flux_density, HeatFluxDensity, watt_per_square_meter),
602    (heat_transfer, HeatTransfer, gram_per_second_cubed_kelvin),
603    (inductance, Inductance, henry),
604    (information, Information, bit),
605    (information_rate, InformationRate, bit_per_second),
606    (inverse_velocity, InverseVelocity, second_per_meter),
607    (jerk, Jerk, meter_per_second_cubed),
608    (kinematic_viscosity, KinematicViscosity, square_meter_per_second),
609    (length, Length, meter),
610    (linear_density_of_states, LinearDensityOfStates, state_per_meter_joule),
611    (linear_mass_density, LinearMassDensity, kilogram_per_meter),
612    (linear_number_density, LinearNumberDensity, per_kilometer),
613    (linear_number_rate, LinearNumberRate, per_kilometer_second),
614    (linear_power_density, LinearPowerDensity, watt_per_meter),
615    (luminance, Luminance, candela_per_square_meter),
616    (luminous_intensity, LuminousIntensity, candela),
617    (magnetic_field_strength, MagneticFieldStrength, ampere_per_meter),
618    (magnetic_flux, MagneticFlux, weber),
619    (magnetic_flux_density, MagneticFluxDensity, tesla),
620    (magnetic_moment, MagneticMoment, ampere_square_meter),
621    (magnetic_permeability, MagneticPermeability, henry_per_meter),
622    (mass, Mass, gram),
623    (mass_concentration, MassConcentration, gram_per_cubic_meter),
624    (mass_density, MassDensity, gram_per_cubic_meter),
625    (mass_flux, MassFlux, kilogram_per_square_meter_second),
626    (mass_per_energy, MassPerEnergy, gram_per_joule),
627    (mass_rate, MassRate, gram_per_second),
628    (molality, Molality, mole_per_kilogram),
629    (molar_concentration, MolarConcentration, mole_per_cubic_meter),
630    (molar_energy, MolarEnergy, joule_per_mole),
631    (molar_flux, MolarFlux, mole_per_square_meter_second),
632    (molar_heat_capacity, MolarHeatCapacity, joule_per_kelvin_mole),
633    (molar_mass, MolarMass, gram_per_mole),
634    (molar_radioactivity, MolarRadioactivity, becquerel_per_mole),
635    (molar_volume, MolarVolume, cubic_meter_per_mole),
636    (moment_of_inertia, MomentOfInertia, kilogram_square_meter),
637    (momentum, Momentum, gram_meter_per_second),
638    (power, Power, watt),
639    (power_rate, PowerRate, watt_per_second),
640    (pressure, Pressure, pascal),
641    (radiant_exposure, RadiantExposure, joule_per_square_meter),
642    (radioactivity, Radioactivity, becquerel),
643    (ratio, Ratio, ratio),
644    (reciprocal_length, ReciprocalLength, reciprocal_kilometer),
645    (solid_angle, SolidAngle, steradian),
646    (specific_area, SpecificArea, square_meter_per_kilogram),
647    (specific_heat_capacity, SpecificHeatCapacity, square_meter_per_second_squared_kelvin),
648    (specific_power, SpecificPower, watt_per_kilogram),
649    (specific_radioactivity, SpecificRadioactivity, becquerel_per_kilogram),
650    (surface_electric_current_density, SurfaceElectricCurrentDensity, ampere_per_meter),
651    (surface_tension, SurfaceTension, newton_per_meter),
652    (temperature_coefficient, TemperatureCoefficient, per_kelvin),
653    (temperature_gradient, TemperatureGradient, kelvin_per_kilometer),
654    (temperature_interval, TemperatureInterval, kelvin),
655    (thermal_conductance, ThermalConductance, gram_meter_squared_per_second_cubed_kelvin),
656    (thermal_conductivity, ThermalConductivity, gram_meter_per_second_cubed_kelvin),
657    (thermal_resistance, ThermalResistance, kelvin_per_yottawatt),
658    (thermodynamic_temperature, ThermodynamicTemperature, kelvin),
659    (time, Time, second),
660    (torque, Torque, newton_meter),
661    (velocity, Velocity, meter_per_second),
662    (volume, Volume, cubic_meter),
663    (volume_rate, VolumeRate, cubic_meter_per_second),
664    (volumetric_density_of_states, VolumetricDensityOfStates, state_per_cubic_meter_joule),
665    (volumetric_heat_capacity, VolumetricHeatCapacity, joule_per_cubic_meter_kelvin),
666    (volumetric_number_density, VolumetricNumberDensity, per_cubic_kilometer),
667    (volumetric_number_rate, VolumetricNumberRate, per_cubic_meter_second),
668    (volumetric_power_density, VolumetricPowerDensity, watt_per_cubic_meter),
669}
670
671#[cfg(all(test, feature = "reflect"))]
672mod tests {
673    use super::si::f32::Velocity;
674    use super::si::velocity::{kilometer_per_hour, meter_per_second};
675    use bevy_reflect::{PartialReflect, Reflect, ReflectRef};
676
677    #[derive(Reflect)]
678    #[reflect(from_reflect = false)]
679    struct Msg {
680        speed: Velocity,
681    }
682
683    #[test]
684    fn reflect_velocity_exposes_value_field() {
685        let msg = Msg {
686            speed: Velocity::new::<kilometer_per_hour>(36.0),
687        };
688
689        assert!(matches!(
690            msg.speed.as_partial_reflect().reflect_ref(),
691            ReflectRef::Struct(_)
692        ));
693        assert_eq!(msg.speed.get::<meter_per_second>(), 10.0);
694
695        let speed_reflected = match msg.as_partial_reflect().reflect_ref() {
696            ReflectRef::Struct(s) => s.field("speed").expect("speed field should exist"),
697            _ => panic!("expected struct reflection"),
698        };
699
700        let speed = speed_reflected
701            .try_downcast_ref::<Velocity>()
702            .expect("speed should downcast to cu29_units::si::f32::Velocity");
703        assert_eq!(speed.raw(), 10.0);
704        assert_eq!(speed.value, 10.0);
705        assert_eq!(speed.get::<meter_per_second>(), 10.0);
706    }
707}