1#![no_std]
6
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10#[repr(u32)]
11pub enum Scalar {
12 Bool = 0,
14 U8 = 1,
16 U16 = 2,
18 U32 = 3,
20 U64 = 4,
22 U128 = 5,
24 I8 = 6,
26 I16 = 7,
28 I32 = 8,
30 I64 = 9,
32 I128 = 10,
34 F32 = 11,
36 F64 = 12,
38 Char = 13,
40}
41
42#[derive(Clone, Copy, Debug, PartialEq, Eq)]
44#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
45#[repr(u32)]
46pub enum RecordShape {
47 Unit = 0,
49 Tuple = 1,
51 Newtype = 2,
53 Struct = 3,
55}
56
57#[doc(hidden)]
59#[macro_export]
60macro_rules! __quantity_catalogue {
61 ($callback:ident $(, $argument:ident)*) => {
62 $callback! {
63 $($argument,)*
64 [
65 (1, absement, Absement, "m·s"),
66 (2, acceleration, Acceleration, "m·s⁻²"),
67 (3, action, Action, "J·s"),
68 (4, amount_of_substance, AmountOfSubstance, "mol"),
69 (5, angle, Angle, "rad"),
70 (6, angular_absement, AngularAbsement, "rad·s"),
71 (7, angular_acceleration, AngularAcceleration, "rad·s⁻²"),
72 (8, angular_jerk, AngularJerk, "rad·s⁻³"),
73 (9, angular_momentum, AngularMomentum, "N·m·s"),
74 (10, angular_velocity, AngularVelocity, "rad·s⁻¹"),
75 (11, area, Area, "m²"),
76 (12, areal_density_of_states, ArealDensityOfStates, "m⁻²·J⁻¹"),
77 (13, areal_heat_capacity, ArealHeatCapacity, "J·m⁻²·K⁻¹"),
78 (14, areal_mass_density, ArealMassDensity, "kg·m⁻²"),
79 (15, areal_number_density, ArealNumberDensity, "m⁻²"),
80 (16, areal_number_rate, ArealNumberRate, "m⁻²·s⁻¹"),
81 (17, available_energy, AvailableEnergy, "J·kg⁻¹"),
82 (18, capacitance, Capacitance, "F"),
83 (19, catalytic_activity, CatalyticActivity, "kat"),
84 (20, catalytic_activity_concentration, CatalyticActivityConcentration, "kat·m⁻³"),
85 (21, curvature, Curvature, "rad·m⁻¹"),
86 (22, diffusion_coefficient, DiffusionCoefficient, "m²·s⁻¹"),
87 (23, dynamic_viscosity, DynamicViscosity, "Pa·s"),
88 (24, electric_charge, ElectricCharge, "C"),
89 (25, electric_charge_areal_density, ElectricChargeArealDensity, "C·m⁻²"),
90 (26, electric_charge_linear_density, ElectricChargeLinearDensity, "C·m⁻¹"),
91 (27, electric_charge_volumetric_density, ElectricChargeVolumetricDensity, "C·m⁻³"),
92 (28, electric_current, ElectricCurrent, "A"),
93 (29, electric_current_density, ElectricCurrentDensity, "A·m⁻²"),
94 (30, electric_dipole_moment, ElectricDipoleMoment, "C·m"),
95 (31, electric_displacement_field, ElectricDisplacementField, "C·m⁻²"),
96 (32, electric_field, ElectricField, "V·m⁻¹"),
97 (33, electric_flux, ElectricFlux, "V·m"),
98 (34, electric_permittivity, ElectricPermittivity, "F·m⁻¹"),
99 (35, electric_potential, ElectricPotential, "V"),
100 (36, electric_quadrupole_moment, ElectricQuadrupoleMoment, "C·m²"),
101 (37, electrical_conductance, ElectricalConductance, "S"),
102 (38, electrical_conductivity, ElectricalConductivity, "S·m⁻¹"),
103 (39, electrical_mobility, ElectricalMobility, "m²·V⁻¹·s⁻¹"),
104 (40, electrical_resistance, ElectricalResistance, "Ω"),
105 (41, electrical_resistivity, ElectricalResistivity, "Ω·m"),
106 (42, energy, Energy, "J"),
107 (43, force, Force, "N"),
108 (44, frequency, Frequency, "Hz"),
109 (45, frequency_drift, FrequencyDrift, "Hz·s⁻¹"),
110 (46, heat_capacity, HeatCapacity, "J·K⁻¹"),
111 (47, heat_flux_density, HeatFluxDensity, "W·m⁻²"),
112 (48, heat_transfer, HeatTransfer, "W·m⁻²·K⁻¹"),
113 (49, inductance, Inductance, "H"),
114 (50, information, Information, "bit"),
115 (51, information_rate, InformationRate, "bit·s⁻¹"),
116 (52, inverse_velocity, InverseVelocity, "s·m⁻¹"),
117 (53, jerk, Jerk, "m·s⁻³"),
118 (54, kinematic_viscosity, KinematicViscosity, "m²·s⁻¹"),
119 (55, length, Length, "m"),
120 (56, linear_density_of_states, LinearDensityOfStates, "m⁻¹·J⁻¹"),
121 (57, linear_mass_density, LinearMassDensity, "kg·m⁻¹"),
122 (58, linear_number_density, LinearNumberDensity, "m⁻¹"),
123 (59, linear_number_rate, LinearNumberRate, "m⁻¹·s⁻¹"),
124 (60, linear_power_density, LinearPowerDensity, "W·m⁻¹"),
125 (61, luminance, Luminance, "cd·m⁻²"),
126 (62, luminous_intensity, LuminousIntensity, "cd"),
127 (63, magnetic_field_strength, MagneticFieldStrength, "A·m⁻¹"),
128 (64, magnetic_flux, MagneticFlux, "Wb"),
129 (65, magnetic_flux_density, MagneticFluxDensity, "T"),
130 (66, magnetic_moment, MagneticMoment, "A·m²"),
131 (67, magnetic_permeability, MagneticPermeability, "H·m⁻¹"),
132 (68, mass, Mass, "kg"),
133 (69, mass_concentration, MassConcentration, "kg·m⁻³"),
134 (70, mass_density, MassDensity, "kg·m⁻³"),
135 (71, mass_flux, MassFlux, "kg·m⁻²·s⁻¹"),
136 (72, mass_per_energy, MassPerEnergy, "kg·J⁻¹"),
137 (73, mass_rate, MassRate, "kg·s⁻¹"),
138 (74, molality, Molality, "mol·kg⁻¹"),
139 (75, molar_concentration, MolarConcentration, "mol·m⁻³"),
140 (76, molar_energy, MolarEnergy, "J·mol⁻¹"),
141 (77, molar_flux, MolarFlux, "mol·m⁻²·s⁻¹"),
142 (78, molar_heat_capacity, MolarHeatCapacity, "J·K⁻¹·mol⁻¹"),
143 (79, molar_mass, MolarMass, "kg·mol⁻¹"),
144 (80, molar_radioactivity, MolarRadioactivity, "Bq·mol⁻¹"),
145 (81, molar_volume, MolarVolume, "m³·mol⁻¹"),
146 (82, moment_of_inertia, MomentOfInertia, "kg·m²"),
147 (83, momentum, Momentum, "kg·m·s⁻¹"),
148 (84, power, Power, "W"),
149 (85, power_rate, PowerRate, "W·s⁻¹"),
150 (86, pressure, Pressure, "Pa"),
151 (87, radiant_exposure, RadiantExposure, "J·m⁻²"),
152 (88, radioactivity, Radioactivity, "Bq"),
153 (89, ratio, Ratio, "1"),
154 (90, reciprocal_length, ReciprocalLength, "m⁻¹"),
155 (91, solid_angle, SolidAngle, "sr"),
156 (92, specific_area, SpecificArea, "m²·kg⁻¹"),
157 (93, specific_heat_capacity, SpecificHeatCapacity, "J·kg⁻¹·K⁻¹"),
158 (94, specific_power, SpecificPower, "W·kg⁻¹"),
159 (95, specific_radioactivity, SpecificRadioactivity, "Bq·kg⁻¹"),
160 (96, specific_volume, SpecificVolume, "m³·kg⁻¹"),
161 (97, surface_electric_current_density, SurfaceElectricCurrentDensity, "A·m⁻¹"),
162 (98, surface_tension, SurfaceTension, "N·m⁻¹"),
163 (99, temperature_coefficient, TemperatureCoefficient, "K⁻¹"),
164 (100, temperature_gradient, TemperatureGradient, "K·m⁻¹"),
165 (101, temperature_interval, TemperatureInterval, "K"),
166 (102, thermal_conductance, ThermalConductance, "W·K⁻¹"),
167 (103, thermal_conductivity, ThermalConductivity, "W·m⁻¹·K⁻¹"),
168 (104, thermal_resistance, ThermalResistance, "K·W⁻¹"),
169 (105, thermodynamic_temperature, ThermodynamicTemperature, "K"),
170 (106, time, Time, "s"),
171 (107, torque, Torque, "N·m"),
172 (108, velocity, Velocity, "m·s⁻¹"),
173 (109, volume, Volume, "m³"),
174 (110, volume_rate, VolumeRate, "m³·s⁻¹"),
175 (111, volumetric_density_of_states, VolumetricDensityOfStates, "m⁻³·J⁻¹"),
176 (112, volumetric_heat_capacity, VolumetricHeatCapacity, "J·m⁻³·K⁻¹"),
177 (113, volumetric_number_density, VolumetricNumberDensity, "m⁻³"),
178 (114, volumetric_number_rate, VolumetricNumberRate, "m⁻³·s⁻¹"),
179 (115, volumetric_power_density, VolumetricPowerDensity, "W·m⁻³"),
180 ]
181 }
182 };
183}
184
185macro_rules! define_quantities {
186 ([$(($id:literal, $module:ident, $variant:ident, $unit:literal),)+]) => {
187 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
189 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
190 #[repr(u32)]
191 pub enum Quantity {
192 $(#[doc = concat!("Physical quantity `", stringify!($module), "`.")]
193 $variant = $id,)+
194 }
195
196 impl Quantity {
197 pub const ALL: &'static [Self] = &[$(Self::$variant,)+];
199
200 pub const fn id(self) -> u32 { self as u32 }
202
203 pub const fn from_id(id: u32) -> Option<Self> {
205 match id { $($id => Some(Self::$variant),)+ _ => None }
206 }
207
208 pub const fn name(self) -> &'static str {
210 match self { $(Self::$variant => stringify!($module),)+ }
211 }
212
213 const fn coherent_unit_symbol(self) -> &'static str {
214 match self { $(Self::$variant => $unit,)+ }
215 }
216 }
217 };
218}
219__quantity_catalogue!(define_quantities);
220
221#[derive(Clone, Copy, Debug, PartialEq, Eq)]
223#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
224pub enum StorageUnit {
225 Coherent(Quantity),
227 Nanosecond,
229}
230
231impl StorageUnit {
232 pub const fn id(self) -> u32 {
234 match self {
235 Self::Coherent(_) => 1,
236 Self::Nanosecond => 2,
237 }
238 }
239
240 pub const fn symbol(self) -> &'static str {
242 match self {
243 Self::Coherent(quantity) => quantity.coherent_unit_symbol(),
244 Self::Nanosecond => "ns",
245 }
246 }
247}
248
249#[derive(Clone, Copy, Debug, PartialEq, Eq)]
251#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
252pub enum TimeStorageUnit {
253 Second,
255 Nanosecond,
257}
258
259#[derive(Clone, Copy, Debug, PartialEq, Eq)]
261#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
262pub enum QuantityMetadata {
263 Coherent(Quantity),
265 NanosecondTime,
267}
268
269impl QuantityMetadata {
270 pub const fn coherent(quantity: Quantity) -> Self {
272 Self::Coherent(quantity)
273 }
274
275 pub const fn time(unit: TimeStorageUnit) -> Self {
277 match unit {
278 TimeStorageUnit::Second => Self::Coherent(Quantity::Time),
279 TimeStorageUnit::Nanosecond => Self::NanosecondTime,
280 }
281 }
282
283 pub const fn quantity(self) -> Quantity {
285 match self {
286 Self::Coherent(quantity) => quantity,
287 Self::NanosecondTime => Quantity::Time,
288 }
289 }
290
291 pub const fn storage_unit(self) -> StorageUnit {
293 match self {
294 Self::Coherent(quantity) => StorageUnit::Coherent(quantity),
295 Self::NanosecondTime => StorageUnit::Nanosecond,
296 }
297 }
298}
299
300#[derive(Clone, Copy, Debug, PartialEq, Eq)]
302#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
303pub enum ValueMetadata {
304 Quantity(QuantityMetadata),
306}
307
308impl ValueMetadata {
309 pub const fn kind_id(self) -> u32 {
311 match self {
312 Self::Quantity(_) => 1,
313 }
314 }
315}
316
317#[cfg(test)]
318mod tests {
319 use super::*;
320
321 #[test]
322 fn test_catalogue_ids_are_unique_and_resolve() {
323 for (index, quantity) in Quantity::ALL.iter().enumerate() {
324 assert_eq!(Quantity::from_id(quantity.id()), Some(*quantity));
325 assert!(
326 !Quantity::ALL[..index]
327 .iter()
328 .any(|previous| previous.id() == quantity.id())
329 );
330 }
331 assert_eq!(Quantity::from_id(0), None);
332 assert_eq!(Quantity::from_id(u32::MAX), None);
333 }
334
335 #[test]
336 fn test_quantity_storage_and_presentation() {
337 for (quantity, symbol) in [
338 (Quantity::Length, "m"),
339 (Quantity::Mass, "kg"),
340 (Quantity::Velocity, "m·s⁻¹"),
341 (Quantity::Angle, "rad"),
342 (Quantity::SolidAngle, "sr"),
343 (Quantity::Information, "bit"),
344 (Quantity::InformationRate, "bit·s⁻¹"),
345 (Quantity::Ratio, "1"),
346 ] {
347 let metadata = QuantityMetadata::coherent(quantity);
348 assert_eq!(metadata.quantity(), quantity);
349 assert_eq!(metadata.storage_unit(), StorageUnit::Coherent(quantity));
350 assert_eq!(metadata.storage_unit().symbol(), symbol);
351 }
352 assert_eq!(
353 QuantityMetadata::time(TimeStorageUnit::Second),
354 QuantityMetadata::coherent(Quantity::Time)
355 );
356 let nanos = QuantityMetadata::time(TimeStorageUnit::Nanosecond);
357 assert_eq!(nanos.quantity(), Quantity::Time);
358 assert_eq!(nanos.storage_unit(), StorageUnit::Nanosecond);
359 assert_eq!(nanos.storage_unit().symbol(), "ns");
360 assert_eq!(nanos.storage_unit().id(), 2);
361 assert_eq!(ValueMetadata::Quantity(nanos).kind_id(), 1);
362 }
363}