From 22705f80c288d20164785b8ae4db4f50aeeb91c0 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Tue, 26 Apr 2022 10:50:11 -0700 Subject: [PATCH 01/80] gh-39 Update symbol parser to parse longer prefixes first --- api/src/parser/symbols/symbol.pest | 37 ++++++++++++++++-------------- api/tests/measurements_test.rs | 8 +++++++ 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/api/src/parser/symbols/symbol.pest b/api/src/parser/symbols/symbol.pest index 95442fa5..143e1595 100644 --- a/api/src/parser/symbols/symbol.pest +++ b/api/src/parser/symbols/symbol.pest @@ -16,7 +16,13 @@ secondary_symbol = _{ } pri_prefix = { - pri_yotta + pri_gibi + | pri_mebi + | pri_kibi + | pri_tebi + | pri_deka + + | pri_yotta | pri_zetta | pri_exa | pri_peta @@ -25,7 +31,6 @@ pri_prefix = { | pri_mega | pri_kilo | pri_hecto - | pri_deka | pri_deci | pri_centi | pri_milli @@ -36,10 +41,6 @@ pri_prefix = { | pri_atto | pri_zepto | pri_yocto - | pri_kibi - | pri_mebi - | pri_gibi - | pri_tebi } pri_atto = { "a" } @@ -697,16 +698,24 @@ pri_unified_atomic_mass_unit = { "u" } //----------------------------------------------------------------------------- sec_prefix = { - sec_yotta - | sec_zetta + sec_gibi + | sec_kibi + | sec_mebi + | sec_tebi + + | sec_deka | sec_exa - | sec_peta - | sec_tera | sec_giga | sec_mega + | sec_peta + | sec_tera + | sec_yotta + | sec_yocto + | sec_zetta + | sec_zepto + | sec_kilo | sec_hecto - | sec_deka | sec_deci | sec_centi | sec_milli @@ -715,12 +724,6 @@ sec_prefix = { | sec_pico | sec_femto | sec_atto - | sec_zepto - | sec_yocto - | sec_kibi - | sec_mebi - | sec_gibi - | sec_tebi } sec_atto = { "A" } diff --git a/api/tests/measurements_test.rs b/api/tests/measurements_test.rs index 61538899..e98b8bd8 100644 --- a/api/tests/measurements_test.rs +++ b/api/tests/measurements_test.rs @@ -412,3 +412,11 @@ validate_conversion!( "W", 1.0 ); + +#[test] +fn mebi() { + let over_one_mebibyte = Measurement::try_new(1.125, "MiBy").unwrap(); + let nine_mebi_bit = over_one_mebibyte.convert_to("bit").unwrap(); + assert_eq!(nine_mebi_bit, Measurement::try_new(9* 1024 * 1024, "bit").unwrap()); + eprintln!("M: {} {}", over_one_mebibyte, nine_mebi_bit); +} From 1118c545805f34a934fda298dfae27e827c2df29 Mon Sep 17 00:00:00 2001 From: Daniel Reiter Horn Date: Tue, 26 Apr 2022 22:10:21 -0700 Subject: [PATCH 02/80] Add more tests and fix bug in prefix.rs --- api/src/measurement/is_compatible_with.rs | 11 +++++++++++ api/src/parser/prefix.rs | 1 + api/src/parser/terms/mapper.rs | 9 +++++++++ api/src/unit.rs | 15 +++++++++++++++ api/tests/measurements_test.rs | 5 ++++- 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/api/src/measurement/is_compatible_with.rs b/api/src/measurement/is_compatible_with.rs index 3d819d68..64bf0125 100644 --- a/api/src/measurement/is_compatible_with.rs +++ b/api/src/measurement/is_compatible_with.rs @@ -38,6 +38,17 @@ mod tests { let other = Measurement::try_new(1.0, "g{foo}").unwrap(); assert!(!subject.is_compatible_with(&other)); + + let subject = Measurement::try_new(1.0, "GiBy{bit}").unwrap(); + let other = Measurement::try_new(1.0, "Kibit{bit}").unwrap(); + assert!(subject.is_compatible_with(&other)); + + assert!(subject.is_compatible_with(&Measurement::try_new(1.0, "Mibit{bit}").unwrap())); + assert!(subject.is_compatible_with(&Measurement::try_new(1.0, "Mbit{bit}").unwrap())); + assert!(subject.is_compatible_with(&Measurement::try_new(1.0, "MiBy{bit}").unwrap())); + + let other = Measurement::try_new(1.0, "kbit").unwrap(); + assert!(!subject.is_compatible_with(&other)); } #[test] diff --git a/api/src/parser/prefix.rs b/api/src/parser/prefix.rs index 8e5062b1..e53b4d02 100644 --- a/api/src/parser/prefix.rs +++ b/api/src/parser/prefix.rs @@ -219,6 +219,7 @@ impl Visit for Prefix { Rule::pri_gibi | Rule::sec_gibi => Self::Gibi, Rule::pri_giga | Rule::sec_giga => Self::Giga, Rule::pri_hecto | Rule::sec_hecto => Self::Hecto, + Rule::pri_kibi | Rule::sec_kibi => Self::Kibi, Rule::pri_kilo | Rule::sec_kilo => Self::Kilo, Rule::pri_mebi | Rule::sec_mebi => Self::Mebi, Rule::pri_mega | Rule::sec_mega => Self::Mega, diff --git a/api/src/parser/terms/mapper.rs b/api/src/parser/terms/mapper.rs index 3ab4ad4b..b2f3aa94 100644 --- a/api/src/parser/terms/mapper.rs +++ b/api/src/parser/terms/mapper.rs @@ -102,6 +102,15 @@ mod tests { ); validate_interpret!(validate_interpret_kilometer, "km", term!(Kilo, Meter)); + validate_interpret!(validate_interpret_kilobyte, "kBy", term!(Kilo, Byte)); + validate_interpret!(validate_sec_interpret_klobyte, "KBY", term!(Kilo, Byte)); + validate_interpret!(validate_sec_interpret_kibibyte, "KIBBY", term!(Kibi, Byte)); + validate_interpret!(validate_interpret_kibibyte, "KiBy", term!(Kibi, Byte)); + validate_interpret!(validate_interpret_mebibyte, "MiBy", term!(Mebi, Byte)); + validate_interpret!(validate_interpret_gibibyte, "GiBy", term!(Gibi, Byte)); + validate_interpret!(validate_interpret_tebibyte, "TiBy", term!(Tebi, Byte)); + validate_interpret!(validate_interpret_yottabyte, "YBy", term!(Yotta, Byte)); + // Slash terms validate_interpret!( validate_interpret_meter_per_second, diff --git a/api/src/unit.rs b/api/src/unit.rs index 2838d336..4c379635 100644 --- a/api/src/unit.rs +++ b/api/src/unit.rs @@ -220,6 +220,21 @@ mod tests { let unit = Unit::from_str("km3/nm2").unwrap(); assert_eq!(unit.expression_reduced().as_str(), "km3/nm2"); + + let unit = Unit::from_str("Kibit").unwrap(); + assert_eq!(unit.expression_reduced().as_str(), "Kibit"); + + let unit = Unit::from_str("KiBy").unwrap(); + assert_eq!(unit.expression_reduced().as_str(), "KiBy"); + + let unit = Unit::from_str("MiBy").unwrap(); + assert_eq!(unit.expression_reduced().as_str(), "MiBy"); + + let unit = Unit::from_str("GiBy").unwrap(); + assert_eq!(unit.expression_reduced().as_str(), "GiBy"); + + let unit = Unit::from_str("TiBy").unwrap(); + assert_eq!(unit.expression_reduced().as_str(), "TiBy"); } #[cfg(feature = "cffi")] diff --git a/api/tests/measurements_test.rs b/api/tests/measurements_test.rs index e98b8bd8..eb28c786 100644 --- a/api/tests/measurements_test.rs +++ b/api/tests/measurements_test.rs @@ -417,6 +417,9 @@ validate_conversion!( fn mebi() { let over_one_mebibyte = Measurement::try_new(1.125, "MiBy").unwrap(); let nine_mebi_bit = over_one_mebibyte.convert_to("bit").unwrap(); - assert_eq!(nine_mebi_bit, Measurement::try_new(9* 1024 * 1024, "bit").unwrap()); + assert_eq!( + nine_mebi_bit, + Measurement::try_new(9 * 1024 * 1024, "bit").unwrap() + ); eprintln!("M: {} {}", over_one_mebibyte, nine_mebi_bit); } From 80693a17e9a511a54ca262116f8e38818f33a5b7 Mon Sep 17 00:00:00 2001 From: Gretchen Reeves Date: Wed, 15 Feb 2023 16:51:16 -0500 Subject: [PATCH 03/80] Initial clippy fix run, then supression of certain lints and refactoring of problem areas to address linter warnings. --- api/src/convertible.rs | 3 ++ api/src/error.rs | 4 +- api/src/measurement/convertible.rs | 3 ++ api/src/measurement/ops.rs | 3 ++ api/src/parser.rs | 4 ++ api/src/parser/composition.rs | 2 +- api/src/parser/definition.rs | 40 +++++++++---------- api/src/parser/error.rs | 2 +- api/src/parser/property.rs | 2 +- api/src/parser/term/composable.rs | 17 +++----- api/src/parser/term/display.rs | 4 +- api/src/parser/term/invert.rs | 10 ++--- api/src/parser/term/reducible.rs | 23 +++++------ api/src/parser/term/ucum_unit.rs | 15 ++----- api/src/parser/terms/mapper.rs | 5 +++ api/src/parser/terms/mapper/exponent.rs | 10 ++--- api/src/unit/display.rs | 6 +-- api/src/unit/field_eq.rs | 8 ++-- api/src/unit/is_compatible_with.rs | 4 +- api/src/unit/ops.rs | 4 +- api/tests/measurements_test.rs | 2 +- atom_generator/src/from_toml.rs | 4 +- atom_generator/src/rust_structs.rs | 2 +- .../src/rust_structs/pest_symbol_list.rs | 7 ++-- atom_generator/src/toml_structs.rs | 2 + atom_generator/src/toml_structs/toml_atom.rs | 5 +-- .../src/toml_structs/toml_atom_list.rs | 6 +-- .../src/toml_structs/toml_definition.rs | 2 +- .../src/toml_structs/toml_prefix.rs | 1 + ffi/build.rs | 2 +- 30 files changed, 105 insertions(+), 97 deletions(-) diff --git a/api/src/convertible.rs b/api/src/convertible.rs index 80192a5e..a47ffe8c 100644 --- a/api/src/convertible.rs +++ b/api/src/convertible.rs @@ -1,3 +1,6 @@ +#![allow(clippy::large_enum_variant)] +#![allow(clippy::result_large_err)] + /// Intended for `Measurement`s, it allows for converting using various types to construct the /// destination `Unit`. /// diff --git a/api/src/error.rs b/api/src/error.rs index 264de6c3..6530c105 100644 --- a/api/src/error.rs +++ b/api/src/error.rs @@ -1,8 +1,10 @@ use crate::parser::Error as ParserError; -#[derive(Clone, Debug, thiserror::Error, PartialEq)] +#[derive(Clone, Debug, thiserror::Error, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize))] #[allow(variant_size_differences)] +#[allow(clippy::large_enum_variant)] +#[allow(clippy::result_large_err)] pub enum Error { #[error("Units are not compatible: {lhs:?}, {rhs:?}")] IncompatibleUnitTypes { lhs: String, rhs: String }, diff --git a/api/src/measurement/convertible.rs b/api/src/measurement/convertible.rs index 4391a443..dda73945 100644 --- a/api/src/measurement/convertible.rs +++ b/api/src/measurement/convertible.rs @@ -1,3 +1,6 @@ +#![allow(clippy::large_enum_variant)] +#![allow(clippy::result_large_err)] + use crate::{Convertible, Error, FieldEq, IsCompatibleWith, Measurement, Unit}; use std::str::FromStr; diff --git a/api/src/measurement/ops.rs b/api/src/measurement/ops.rs index 247ddda8..986c22ac 100644 --- a/api/src/measurement/ops.rs +++ b/api/src/measurement/ops.rs @@ -1,3 +1,6 @@ +#![allow(clippy::large_enum_variant)] +#![allow(clippy::result_large_err)] + use crate::{convertible::Convertible, error::Error, measurement::Measurement}; use std::ops::{Add, Div, Mul, Sub}; diff --git a/api/src/parser.rs b/api/src/parser.rs index 59d95838..62417f25 100644 --- a/api/src/parser.rs +++ b/api/src/parser.rs @@ -1,3 +1,6 @@ +#![allow(clippy::large_enum_variant)] +#![allow(clippy::result_large_err)] + // Because long numbers are generated, there's no way (that I know of) to // generate them using underscores (to make them pass the clippy lint). #[cfg_attr( @@ -58,6 +61,7 @@ trait Visit { // TODO: Move to atom_generator. // +#[allow(clippy::too_many_lines)] impl Visit for Atom { fn visit(pair: Pair<'_, SymbolRule>) -> Result { let atom = match pair.as_rule() { diff --git a/api/src/parser/composition.rs b/api/src/parser/composition.rs index 177eecb2..8289ee39 100644 --- a/api/src/parser/composition.rs +++ b/api/src/parser/composition.rs @@ -345,7 +345,7 @@ fn push_display_expression( if value == 1 { expressions.push(dimension_str.to_string()); } else { - expressions.push(format!("{}{}", dimension_str, value)); + expressions.push(format!("{dimension_str}{value}")); } } } diff --git a/api/src/parser/definition.rs b/api/src/parser/definition.rs index 33b02d3e..2d23cda5 100644 --- a/api/src/parser/definition.rs +++ b/api/src/parser/definition.rs @@ -1,3 +1,6 @@ +#![allow(clippy::large_enum_variant)] +#![allow(clippy::result_large_err)] + use crate::{ parser::{function_set::FunctionSet, Error, Term}, reducible::Reducible, @@ -46,30 +49,27 @@ impl Definition { impl Reducible for Definition { fn reduce_value(&self, other_value: f64) -> f64 { - match self.function_set { - None => { - if self.is_unity() { - self.value - } else { - self.value * self.terms.reduce_value(other_value) - } - } - Some(ref f) => (f.convert_to)(other_value), - } + self.function_set.as_ref().map_or_else( + || if self.is_unity() { + self.value + } else { + self.value * self.terms.reduce_value(other_value) + }, + |f| (f.convert_to)(other_value) + ) } fn calculate_magnitude(&self, other_value: f64) -> f64 { - match self.function_set { - None => { - if self.is_unity() { - self.value - } else { - self.value * self.terms.calculate_magnitude(other_value) - } - } - Some(ref f) => (f.convert_from)(other_value), - } + self.function_set.as_ref().map_or_else( + || if self.is_unity() { + self.value + } else { + self.value * self.terms.calculate_magnitude(other_value) + }, + |f| (f.convert_from)(other_value) + ) } + } impl Default for Definition { diff --git a/api/src/parser/error.rs b/api/src/parser/error.rs index c17ca632..180dd326 100644 --- a/api/src/parser/error.rs +++ b/api/src/parser/error.rs @@ -5,7 +5,7 @@ use pest::error::Error as PestError; /// Errors when trying to convert between types that aren't commensurable. /// -#[derive(Clone, thiserror::Error, Debug, PartialEq)] +#[derive(Clone, thiserror::Error, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize))] pub enum Error { #[error(transparent)] diff --git a/api/src/parser/property.rs b/api/src/parser/property.rs index 535067d2..7ecca923 100644 --- a/api/src/parser/property.rs +++ b/api/src/parser/property.rs @@ -1152,7 +1152,7 @@ impl fmt::Display for Property { }, }; - write!(formatter, "{}", string) + write!(formatter, "{string}") } } diff --git a/api/src/parser/term/composable.rs b/api/src/parser/term/composable.rs index ad5e72f0..5d576c18 100644 --- a/api/src/parser/term/composable.rs +++ b/api/src/parser/term/composable.rs @@ -8,20 +8,15 @@ impl Composable for Term { /// // TODO: https://agrian.atlassian.net/browse/DEV-971 // + #[allow(clippy::redundant_closure)] fn composition(&self) -> Composition { - match self.atom { - Some(atom) => { + self.atom.map_or_else( + || Composition::default(), + |atom| { let atom_composition = atom.composition(); - - match self.exponent { - Some(term_exponent) => atom_composition * term_exponent, - None => atom_composition, - } + self.exponent.map_or(atom_composition, |term_exponent| atom_composition * term_exponent) } - // If there's no Atom in the Term, there's no dimension--even if there's an exponent on - // the Term. - None => Composition::default(), - } + ) } } diff --git a/api/src/parser/term/display.rs b/api/src/parser/term/display.rs index 01a3aba6..9e70f245 100644 --- a/api/src/parser/term/display.rs +++ b/api/src/parser/term/display.rs @@ -17,7 +17,7 @@ fn extract_term_string(term: &Term) -> String { extract_term_string_atom(&mut term_string, term); if let Some(ref annotation) = term.annotation { - term_string.push_str(&format!("{{{}}}", annotation)); + term_string.push_str(&format!("{{{annotation}}}")); } term_string @@ -42,7 +42,7 @@ fn extract_term_string_atom(term_string: &mut String, term: &Term) { if exponent == 1 { term_string.push_str(&atom.to_string()); } else { - term_string.push_str(&format!("{}{}", atom, exponent)); + term_string.push_str(&format!("{atom}{exponent}")); } } None => term_string.push_str(&atom.to_string()), diff --git a/api/src/parser/term/invert.rs b/api/src/parser/term/invert.rs index 5399c169..1ce1d913 100644 --- a/api/src/parser/term/invert.rs +++ b/api/src/parser/term/invert.rs @@ -4,13 +4,13 @@ use crate::invert::{Invert, ToInverse}; // Term impl Invert for &mut Term { fn invert(self) { - self.exponent = match self.exponent { - Some(e) => match e { + self.exponent = self.exponent.map_or( + Some(-1), + |e| match e { -1 => None, _ => Some(-e), - }, - None => Some(-1), - }; + } + ); } } diff --git a/api/src/parser/term/reducible.rs b/api/src/parser/term/reducible.rs index bd5c4ca3..e560fa6b 100644 --- a/api/src/parser/term/reducible.rs +++ b/api/src/parser/term/reducible.rs @@ -1,3 +1,6 @@ +#![allow(clippy::large_enum_variant)] +#![allow(clippy::result_large_err)] + use super::Term; use crate::{parser::ucum_symbol::UcumSymbol, reducible::Reducible}; @@ -37,20 +40,16 @@ fn combine_term_values( ) -> f64 { let a_p_product = calculated_atom * calculated_prefix; - match factor { - Some(f) => { + factor.map_or_else( + || exponent.map_or(a_p_product, |e| a_p_product.powi(e)), + |f| { let product = a_p_product * f64::from(f); - - match exponent { - Some(e) => product.powi(e), - None => product, - } + exponent.map_or(product, |e| product.powi(e)) } - None => match exponent { - Some(e) => a_p_product.powi(e), - None => a_p_product, - }, - } + ) + + + } #[cfg(test)] diff --git a/api/src/parser/term/ucum_unit.rs b/api/src/parser/term/ucum_unit.rs index 3412126c..d390918a 100644 --- a/api/src/parser/term/ucum_unit.rs +++ b/api/src/parser/term/ucum_unit.rs @@ -3,10 +3,7 @@ use crate::{reducible::Reducible, ucum_unit::UcumUnit}; impl UcumUnit for Term { fn is_special(&self) -> bool { - match self.atom { - Some(ref a) => a.is_special(), - None => false, - } + self.atom.map_or(false, |a| a.is_special()) } /// The UCUM defines "arbitrary units" using three points. First: @@ -26,19 +23,13 @@ impl UcumUnit for Term { /// “commensurable with” any > other unit. /// fn is_arbitrary(&self) -> bool { - match self.atom { - Some(ref a) => a.is_arbitrary(), - None => false, - } + self.atom.map_or(false, |a| a.is_arbitrary()) } /// A `Term` is metric if it has some `Atom` that is metric. /// fn is_metric(&self) -> bool { - match self.atom { - Some(ref a) => a.is_metric(), - None => false, - } + self.atom.map_or(false, |a| a.is_metric()) } fn scalar(&self) -> f64 { diff --git a/api/src/parser/terms/mapper.rs b/api/src/parser/terms/mapper.rs index b2f3aa94..48da2451 100644 --- a/api/src/parser/terms/mapper.rs +++ b/api/src/parser/terms/mapper.rs @@ -1,3 +1,6 @@ +#![allow(clippy::large_enum_variant)] +#![allow(clippy::result_large_err)] + // Internal structs for mapping parser Rule data to an intermediate // representation of a Unit. pub(self) mod annotatable; @@ -20,6 +23,8 @@ use self::{ use crate::parser::{terms::term_parser::Rule, Atom, Error, Prefix, Term, Visit}; use pest::iterators::{Pair, Pairs}; +#[allow(clippy::large_enum_variant)] +#[allow(clippy::result_large_err)] pub(crate) fn map(mut pairs: Pairs<'_, Rule>) -> Result, Error> { fn visit_pairs(pair: Pair<'_, Rule>) -> Result, Error> { let main_term = if pair.as_rule() == Rule::main_term { diff --git a/api/src/parser/terms/mapper/exponent.rs b/api/src/parser/terms/mapper/exponent.rs index 90c1da10..e537dd8f 100644 --- a/api/src/parser/terms/mapper/exponent.rs +++ b/api/src/parser/terms/mapper/exponent.rs @@ -36,13 +36,13 @@ impl Visit for Exponent { } fn parse_second_token(next: Option>) -> Result { - match next { - Some(second) => match second.as_rule() { + next.map_or_else( + || unreachable!(), + |second| match second.as_rule() { TermRule::digits => Digits::visit(second), _ => unreachable!(), - }, - None => unreachable!(), - } + } + ) } enum FirstToken { diff --git a/api/src/unit/display.rs b/api/src/unit/display.rs index 15b6f899..932ea3ac 100644 --- a/api/src/unit/display.rs +++ b/api/src/unit/display.rs @@ -23,7 +23,7 @@ fn format_output(numerator: Option, denominator: Option) -> Stri match (numerator, denominator) { (Some(n), Some(d)) => [n, d].join("/"), (Some(n), None) => n, - (None, Some(d)) => format!("/{}", d), + (None, Some(d)) => format!("/{d}"), (None, None) => "1".to_string(), } } @@ -70,7 +70,7 @@ fn extract_denominator(term: &Term) -> Option { extract_denominator_atom(term, &mut term_string); if let Some(ref annotation) = term.annotation { - term_string.push_str(&format!("{{{}}}", annotation)); + term_string.push_str(&format!("{{{annotation}}}")); } Some(term_string) @@ -88,7 +88,7 @@ fn extract_denominator_atom(term: &Term, term_string: &mut String) { if ex_abs == 1 { term_string.push_str(&atom.to_string()); } else { - term_string.push_str(&format!("{}{}", atom, ex_abs)); + term_string.push_str(&format!("{atom}{ex_abs}")); } } else { term_string.push_str(&atom.to_string()); diff --git a/api/src/unit/field_eq.rs b/api/src/unit/field_eq.rs index 09f5673f..72d4778c 100644 --- a/api/src/unit/field_eq.rs +++ b/api/src/unit/field_eq.rs @@ -33,10 +33,10 @@ impl<'a> FieldEq<'a> for Unit { fn sort_em(terms: &[Term]) -> Vec { let mut t = terms.to_vec(); - t.sort_by(|a, b| match a.scalar().partial_cmp(&b.scalar()) { - Some(ordering) => ordering, - None => Ordering::Equal, - }); + t.sort_by( + |a, b| + a.scalar().partial_cmp(&b.scalar()).map_or(Ordering::Equal, |ordering| ordering) + ); t } diff --git a/api/src/unit/is_compatible_with.rs b/api/src/unit/is_compatible_with.rs index 0820e59b..4a48b083 100644 --- a/api/src/unit/is_compatible_with.rs +++ b/api/src/unit/is_compatible_with.rs @@ -19,7 +19,7 @@ impl IsCompatibleWith for Unit { impl IsCompatibleWith for Unit { #[inline] fn is_compatible_with(&self, rhs: &Measurement) -> bool { - (&*self).is_compatible_with(rhs.unit().terms()) + (*self).is_compatible_with(rhs.unit().terms()) } } @@ -66,7 +66,7 @@ mod tests { } #[test] - #[allow(clippy::blacklisted_name)] + #[allow(clippy::disallowed_names)] fn validate_is_compatible_with_units_with_annotations() { fn verify_compatible(lhs: &Unit, rhs: &Unit) { assert!(lhs.is_compatible_with(rhs)); diff --git a/api/src/unit/ops.rs b/api/src/unit/ops.rs index 17bcb644..94ec3b44 100644 --- a/api/src/unit/ops.rs +++ b/api/src/unit/ops.rs @@ -18,7 +18,7 @@ fn divide_terms(lhs: &[Term], rhs: &[Term]) -> Vec { #[cfg_attr(feature = "cffi", ffi_common::derive::expose_fn(extend_type(Unit)))] fn divide_units(lhs: &Unit, rhs: &Unit) -> Unit { - Unit::new(divide_terms(&*lhs.terms, &*rhs.terms)) + Unit::new(divide_terms(&lhs.terms, &rhs.terms)) } impl Div for Unit { @@ -72,7 +72,7 @@ fn multiply_terms(lhs: &[Term], rhs: &[Term]) -> Vec { #[cfg_attr(feature = "cffi", ffi_common::derive::expose_fn(extend_type(Unit)))] fn multiply_units(lhs: &Unit, rhs: &Unit) -> Unit { - Unit::new(multiply_terms(&*lhs.terms, &*rhs.terms)) + Unit::new(multiply_terms(&lhs.terms, &rhs.terms)) } impl Mul for Unit { diff --git a/api/tests/measurements_test.rs b/api/tests/measurements_test.rs index eb28c786..b732f8da 100644 --- a/api/tests/measurements_test.rs +++ b/api/tests/measurements_test.rs @@ -421,5 +421,5 @@ fn mebi() { nine_mebi_bit, Measurement::try_new(9 * 1024 * 1024, "bit").unwrap() ); - eprintln!("M: {} {}", over_one_mebibyte, nine_mebi_bit); + eprintln!("M: {over_one_mebibyte} {nine_mebi_bit}"); } diff --git a/atom_generator/src/from_toml.rs b/atom_generator/src/from_toml.rs index 0a7bd29c..8ad87fe5 100644 --- a/atom_generator/src/from_toml.rs +++ b/atom_generator/src/from_toml.rs @@ -126,7 +126,7 @@ fn build_scalar_function(primary_code: &str) -> String { "[pH]" => "|value: f64| -value.log10()", "[degF]" => "|value: f64| 5.0 / 9.0 * (value + 459.67)", "[degRe]" => "|value: f64| (value / 0.8) + 273.15", - _ => panic!("Unknown primary code on special unit: {}", primary_code), + _ => panic!("Unknown primary code on special unit: {primary_code}"), } .to_string() } @@ -154,7 +154,7 @@ fn build_magnitude_function(primary_code: &str) -> String { "[pH]" => "|value: f64| 10.0_f64.powf(-value)", "[degF]" => "|value: f64| 9.0 * value / 5.0 - 459.67", "[degRe]" => "|value: f64| (value - 273.15) * 0.8", - _ => panic!("Unknown primary code on special unit: {}", primary_code), + _ => panic!("Unknown primary code on special unit: {primary_code}"), } .to_string() } diff --git a/atom_generator/src/rust_structs.rs b/atom_generator/src/rust_structs.rs index 453e04de..e0216cf7 100644 --- a/atom_generator/src/rust_structs.rs +++ b/atom_generator/src/rust_structs.rs @@ -21,5 +21,5 @@ pub(crate) struct RustAtomList { pub(self) fn build_pest_rule_name(prefix: &str, symbol: &str) -> String { let symbol = symbol.to_snake_case(); - format!("{}_{}", prefix, symbol) + format!("{prefix}_{symbol}") } diff --git a/atom_generator/src/rust_structs/pest_symbol_list.rs b/atom_generator/src/rust_structs/pest_symbol_list.rs index df6b2dd8..1e5ca171 100644 --- a/atom_generator/src/rust_structs/pest_symbol_list.rs +++ b/atom_generator/src/rust_structs/pest_symbol_list.rs @@ -17,7 +17,7 @@ impl<'a> From<&'a RustAtomList> for PestSymbolList { PestSymbol::new(super::build_pest_rule_name("pri", &s), code) }) - .collect(); + .collect::>(); sort_symbols(&mut primary_rule_names); @@ -32,7 +32,7 @@ impl<'a> From<&'a RustAtomList> for PestSymbolList { PestSymbol::new(super::build_pest_rule_name("sec", &s), code) }) }) - .collect(); + .collect::>(); sort_symbols(&mut secondary_rule_names); @@ -43,7 +43,8 @@ impl<'a> From<&'a RustAtomList> for PestSymbolList { } } -fn sort_symbols(symbols: &mut Vec) { +//#[allow(clippy::all)] +fn sort_symbols(symbols: &mut [PestSymbol]) { symbols.sort_by(|a, b| a.code.cmp(&b.code)); symbols.sort_by(|a, b| b.code.len().cmp(&a.code.len())); } diff --git a/atom_generator/src/toml_structs.rs b/atom_generator/src/toml_structs.rs index d72583ec..f7f4afd7 100644 --- a/atom_generator/src/toml_structs.rs +++ b/atom_generator/src/toml_structs.rs @@ -1,3 +1,5 @@ +#![allow(unused_imports)] + pub(crate) mod toml_atom; pub(crate) mod toml_atom_list; pub(crate) mod toml_base_unit; diff --git a/atom_generator/src/toml_structs/toml_atom.rs b/atom_generator/src/toml_structs/toml_atom.rs index 0b607f46..5cec036b 100644 --- a/atom_generator/src/toml_structs/toml_atom.rs +++ b/atom_generator/src/toml_structs/toml_atom.rs @@ -63,8 +63,7 @@ fn sanitize_type_name_segment(mut string: String) -> String { #[allow(clippy::non_ascii_literal)] fn remove_non_latin_chars(string: &str) -> String { string - .replace('è', "e") - .replace('é', "e") + .replace(['è', 'é'], "e") .replace('Å', "A") .replace('ö', "o") } @@ -77,7 +76,7 @@ fn remove_non_letter_chars(string: &str) -> String { } fn finally(name: &str, primary_code: &str) -> String { - let type_name = format!("{}{}", name, primary_code); + let type_name = format!("{name}{primary_code}"); let mut type_name = NUMBER_REGEX.replace(&type_name, "").into_owned(); type_name.truncate(64); diff --git a/atom_generator/src/toml_structs/toml_atom_list.rs b/atom_generator/src/toml_structs/toml_atom_list.rs index 6b93da2a..6f22147e 100644 --- a/atom_generator/src/toml_structs/toml_atom_list.rs +++ b/atom_generator/src/toml_structs/toml_atom_list.rs @@ -1,10 +1,10 @@ -use super::{TomlBaseUnit, TomlPrefix, TomlUnit}; +use super::{TomlBaseUnit, TomlUnit}; use std::str::FromStr; #[derive(Debug, Deserialize)] pub(crate) struct TomlAtomList { - #[serde(rename = "prefix")] - pub(crate) prefixes: Vec, + //#[serde(rename = "prefix")] + //pub(crate) prefixes: Vec, #[serde(rename = "base-unit")] pub(crate) base_units: Vec, diff --git a/atom_generator/src/toml_structs/toml_definition.rs b/atom_generator/src/toml_structs/toml_definition.rs index 6e9fd201..8214058b 100644 --- a/atom_generator/src/toml_structs/toml_definition.rs +++ b/atom_generator/src/toml_structs/toml_definition.rs @@ -11,7 +11,7 @@ pub(crate) struct TomlDefinition { #[derive(Debug, Deserialize, Clone)] pub(crate) struct TomlFunction { - pub(crate) name: String, + //pub(crate) name: String, pub(crate) value: f64, #[serde(rename = "Unit")] pub(crate) unit: String, diff --git a/atom_generator/src/toml_structs/toml_prefix.rs b/atom_generator/src/toml_structs/toml_prefix.rs index b121fe47..cad1afb7 100644 --- a/atom_generator/src/toml_structs/toml_prefix.rs +++ b/atom_generator/src/toml_structs/toml_prefix.rs @@ -1,3 +1,4 @@ +#[allow(dead_code)] #[derive(Debug, Deserialize)] pub(crate) struct TomlPrefix { #[serde(rename = "Code")] diff --git a/ffi/build.rs b/ffi/build.rs index 42001bc7..c1fcd2e9 100644 --- a/ffi/build.rs +++ b/ffi/build.rs @@ -10,7 +10,7 @@ fn main() { .generate() .map(|bindings| bindings.write_to_file("bindings.h")) .unwrap_or_else(|e| { - eprintln!("Unable to generate bindings: {}", e); + eprintln!("Unable to generate bindings: {e}"); false }); } From e0da9b1cc7ce7f6a2c14489f034fa46f6f99f0d7 Mon Sep 17 00:00:00 2001 From: Gretchen Reeves Date: Fri, 17 Feb 2023 18:52:25 -0500 Subject: [PATCH 04/80] Removed dead code --- atom_generator/src/toml_structs/toml_atom_list.rs | 3 --- atom_generator/src/toml_structs/toml_definition.rs | 1 - 2 files changed, 4 deletions(-) diff --git a/atom_generator/src/toml_structs/toml_atom_list.rs b/atom_generator/src/toml_structs/toml_atom_list.rs index 6f22147e..76972d29 100644 --- a/atom_generator/src/toml_structs/toml_atom_list.rs +++ b/atom_generator/src/toml_structs/toml_atom_list.rs @@ -3,9 +3,6 @@ use std::str::FromStr; #[derive(Debug, Deserialize)] pub(crate) struct TomlAtomList { - //#[serde(rename = "prefix")] - //pub(crate) prefixes: Vec, - #[serde(rename = "base-unit")] pub(crate) base_units: Vec, diff --git a/atom_generator/src/toml_structs/toml_definition.rs b/atom_generator/src/toml_structs/toml_definition.rs index 8214058b..38389b79 100644 --- a/atom_generator/src/toml_structs/toml_definition.rs +++ b/atom_generator/src/toml_structs/toml_definition.rs @@ -11,7 +11,6 @@ pub(crate) struct TomlDefinition { #[derive(Debug, Deserialize, Clone)] pub(crate) struct TomlFunction { - //pub(crate) name: String, pub(crate) value: f64, #[serde(rename = "Unit")] pub(crate) unit: String, From a6195b485c463cfe89f63f35e611229e2689b4b9 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Tue, 21 Feb 2023 17:38:47 -0800 Subject: [PATCH 05/80] fix(ci): Remove MAC_OS_BUILD_AGENT_PRIVATE_KEY --- .github/workflows/rust-ci.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index ba034647..b83409cb 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -16,7 +16,6 @@ jobs: uses: webfactory/ssh-agent@ee29fafb6aa450493bac9136b346e51ea60a8b5e with: ssh-private-key: | - ${{ secrets.MAC_OS_BUILD_AGENT_PRIVATE_KEY }} ${{ secrets.SSH_PRIVATE_KEY }} - uses: actions/checkout@v2 - uses: actions/cache@v2 @@ -39,13 +38,12 @@ jobs: name: Test (x86_64-apple-ios) runs-on: macos-10.15 env: - DYLD_ROOT_PATH: '/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app' + DYLD_ROOT_PATH: "/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app" steps: - name: Setup SSH uses: webfactory/ssh-agent@ee29fafb6aa450493bac9136b346e51ea60a8b5e with: ssh-private-key: | - ${{ secrets.MAC_OS_BUILD_AGENT_PRIVATE_KEY }} ${{ secrets.SSH_PRIVATE_KEY }} - uses: actions/checkout@v2 - uses: actions/cache@v2 From 82c8daff37dd3cd1f29d84d4fccab094c5e8a5e3 Mon Sep 17 00:00:00 2001 From: Gretchen Reeves Date: Mon, 13 Mar 2023 11:29:02 -0400 Subject: [PATCH 06/80] Updated cargo config.toml to point to telus-agcg/crates-registry --- .cargo/config.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index dda5bc73..f3f0bdb8 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,2 +1,2 @@ [registries] -agrian-registry = { index = "ssh://git@github.com/agrian-inc/crates-registry.git" } +agrian-registry = { index = "ssh://git@github.com/telus-agcg/crates-registry.git" } From c5aad557f4774ed2c60e90cb7c3d0c16fd6d80a4 Mon Sep 17 00:00:00 2001 From: Gretchen Reeves Date: Mon, 13 Mar 2023 11:33:39 -0400 Subject: [PATCH 07/80] Corrected crates registry name and updated api and ffi cargo toml files to use correct registry name --- .cargo/config.toml | 2 +- api/Cargo.toml | 4 ++-- ffi/Cargo.toml | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index f3f0bdb8..092e6109 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,2 +1,2 @@ [registries] -agrian-registry = { index = "ssh://git@github.com/telus-agcg/crates-registry.git" } +crates-registry = { index = "ssh://git@github.com/telus-agcg/crates-registry.git" } diff --git a/api/Cargo.toml b/api/Cargo.toml index c431a5f5..7779741b 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -6,11 +6,11 @@ repository = "https://github.com/agrian-inc/wise_units" license = "MIT" authors = ["Steve Loveless "] edition = "2021" -publish = ["agrian-registry"] +publish = ["crates-registry"] [dependencies] approx = "0.5" -ffi_common = { version = "0.7", registry = "agrian-registry", optional = true } +ffi_common = { version = "0.7", registry = "crates-registry", optional = true } pest = "^2.1" pest_derive = "^2.1" serde = { version = "1.0", optional = true, features = ["derive"] } diff --git a/ffi/Cargo.toml b/ffi/Cargo.toml index 01b6acbd..dd021716 100644 --- a/ffi/Cargo.toml +++ b/ffi/Cargo.toml @@ -6,11 +6,11 @@ repository = "https://github.com/agrian-inc/wise_units" license = "MIT" authors = ["Nicholas Smillie "] edition = "2021" -publish = ["agrian-registry"] +publish = ["crates-registry"] [dependencies] -ffi_common = { version = "0.7", registry = "agrian-registry" } -wise_units = { version = "0.22", registry = "agrian-registry" } +ffi_common = { version = "0.7", registry = "crates-registry" } +wise_units = { version = "0.22", registry = "crates-registry" } [build-dependencies] cbindgen = "0.20" From 6459296036b22f1058760cd8bcefc28405c840cf Mon Sep 17 00:00:00 2001 From: Gretchen Reeves Date: Mon, 13 Mar 2023 11:47:54 -0400 Subject: [PATCH 08/80] Updated ssh-private-key to use Telus key --- .github/workflows/rust-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index b83409cb..74f8b28f 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -16,7 +16,7 @@ jobs: uses: webfactory/ssh-agent@ee29fafb6aa450493bac9136b346e51ea60a8b5e with: ssh-private-key: | - ${{ secrets.SSH_PRIVATE_KEY }} + ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - uses: actions/checkout@v2 - uses: actions/cache@v2 with: @@ -44,7 +44,7 @@ jobs: uses: webfactory/ssh-agent@ee29fafb6aa450493bac9136b346e51ea60a8b5e with: ssh-private-key: | - ${{ secrets.SSH_PRIVATE_KEY }} + ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - uses: actions/checkout@v2 - uses: actions/cache@v2 with: From 2f3999f92aafbe5418aaa89adf2ad3c8ea39d944 Mon Sep 17 00:00:00 2001 From: Gretchen Reeves Date: Tue, 16 May 2023 11:20:40 -0400 Subject: [PATCH 09/80] =?UTF-8?q?Added=20extra=C2=A0unit=20tests=20for=20a?= =?UTF-8?q?rbitrary=20units?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/src/measurement/ops.rs | 30 +++++++++++++++++++++++ api/src/parser/term/is_compatible_with.rs | 12 +++++++++ 2 files changed, 42 insertions(+) diff --git a/api/src/measurement/ops.rs b/api/src/measurement/ops.rs index 986c22ac..498512ed 100644 --- a/api/src/measurement/ops.rs +++ b/api/src/measurement/ops.rs @@ -328,6 +328,10 @@ mod tests { } mod add { + use crate::Unit; + use crate::Term; + use crate::error; + use super::*; #[test] @@ -365,6 +369,32 @@ mod tests { assert_eq!((&m1 + m2).unwrap(), expected); } + + #[test] + fn validate_add_arbitrary() { + let term_tree = term!(annotation: "tree".to_string()); + let term_tree2 = term!(annotation: "tree".to_string()); + let expected_term_tree = term!(annotation: "tree".to_string()); + let m1 = Measurement::new(10.0, Unit::new(vec![term_tree])); + let m2 = Measurement::new(7.0, Unit::new(vec![term_tree2])); + let expected = Measurement::new(17.0, Unit::new(vec![expected_term_tree])); + + assert_eq!((&m1 + m2).unwrap(), expected); + } + + + #[test] + fn validate_sub_arbitrary() { + let term_tree = term!(annotation: "tree".to_string()); + let term_tree2 = term!(annotation: "tree".to_string()); + let expected_term_tree = term!(annotation: "tree".to_string()); + let m1 = Measurement::new(10.0, Unit::new(vec![term_tree])); + let m2 = Measurement::new(7.0, Unit::new(vec![term_tree2])); + let expected = Measurement::new(3.0, Unit::new(vec![expected_term_tree])); + + assert_eq!((&m1 - m2).unwrap(), expected); + } + } mod sub { diff --git a/api/src/parser/term/is_compatible_with.rs b/api/src/parser/term/is_compatible_with.rs index 4a6d88c1..bc19bdf4 100644 --- a/api/src/parser/term/is_compatible_with.rs +++ b/api/src/parser/term/is_compatible_with.rs @@ -133,5 +133,17 @@ mod tests { let km_no_annotation = vec![term!(Kilo, Meter)]; assert!(!m.is_compatible_with(&km_no_annotation)); } + + #[test] + fn validate_atomless_term() { + let lhs_tree = term!(annotation: "tree".to_string()); + let rhs_tree = term!(annotation: "tree".to_string()); + assert!(lhs_tree.is_compatible_with(&rhs_tree)); + + // Different annotation + let rhs_plant = term!(annotation: "plant".to_string()); + assert!(!lhs_tree.is_compatible_with(&rhs_plant)); + } + } } From 1ca8afbbd4397fb21988735389d56d45c55bb9b3 Mon Sep 17 00:00:00 2001 From: Gretchen Reeves Date: Tue, 16 May 2023 15:56:31 -0400 Subject: [PATCH 10/80] Added convertible unit tests for arbitrary conversions --- api/src/measurement/convertible.rs | 56 ++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/api/src/measurement/convertible.rs b/api/src/measurement/convertible.rs index dda73945..38202594 100644 --- a/api/src/measurement/convertible.rs +++ b/api/src/measurement/convertible.rs @@ -134,4 +134,60 @@ mod tests { assert_relative_eq!(converted.value, 0.5); assert_ulps_eq!(converted.value, 0.5); } + + #[test] + fn validate_arbitrary_den_conversions() { + + let m1 = Measurement::try_new( + 10.0, + "[acr_us]/{tree}" + ).unwrap(); + + let u1 = Unit::from_str("m2/{tree}").unwrap(); + let u2 = Unit::from_str("m2/{vine}").unwrap(); + + let converted = m1.convert_to(&u1).unwrap(); + + assert_relative_eq!(converted.value, 40468.72609874252); + assert_ulps_eq!(converted.value, 40468.72609874252); + + assert!(m1.convert_to(&u2).is_err()); + } + + #[test] + fn validate_arbitrary_num_conversions() { + let m1 = Measurement::try_new( + 10.0, + "{tree}/[acr_us]" + ).unwrap(); + + let u1 = Unit::from_str("{tree}/m2").unwrap(); + let u2 = Unit::from_str("{vine}/m2").unwrap(); + + let converted = m1.convert_to(&u1).unwrap(); + + assert_relative_eq!(converted.value, 0.002471043930466279); + assert_ulps_eq!(converted.value, 0.002471043930466279); + + assert!(m1.convert_to(&u2).is_err()); + } + + #[test] + fn validate_arbitrary_conversions() { + let m1 = Measurement::try_new( + 10.0, + "{tree}" + ).unwrap(); + + let u1 = Unit::from_str("{tree}").unwrap(); + let u2 = Unit::from_str("{vine}").unwrap(); + + let converted = m1.convert_to(&u1).unwrap(); + + assert_relative_eq!(converted.value, 10.0); + assert_ulps_eq!(converted.value, 10.0); + + assert!(m1.convert_to(&u2).is_err()); + } + } From ea077198d6165d2a5850c5bfe74350329061a733 Mon Sep 17 00:00:00 2001 From: Gretchen Reeves Date: Fri, 19 May 2023 11:49:20 -0400 Subject: [PATCH 11/80] Clippy formatting fixes --- api/src/measurement/convertible.rs | 29 +++++++---------------- api/src/measurement/ops.rs | 8 +++---- api/src/parser/definition.rs | 27 +++++++++++---------- api/src/parser/term/composable.rs | 6 +++-- api/src/parser/term/invert.rs | 11 ++++----- api/src/parser/term/is_compatible_with.rs | 1 - api/src/parser/term/reducible.rs | 7 ++---- api/src/parser/terms/mapper/exponent.rs | 4 ++-- api/src/unit/field_eq.rs | 9 +++---- 9 files changed, 44 insertions(+), 58 deletions(-) diff --git a/api/src/measurement/convertible.rs b/api/src/measurement/convertible.rs index 38202594..eaaf18e1 100644 --- a/api/src/measurement/convertible.rs +++ b/api/src/measurement/convertible.rs @@ -137,14 +137,10 @@ mod tests { #[test] fn validate_arbitrary_den_conversions() { + let m1 = Measurement::try_new(10.0, "[acr_us]/{tree}").unwrap(); - let m1 = Measurement::try_new( - 10.0, - "[acr_us]/{tree}" - ).unwrap(); - - let u1 = Unit::from_str("m2/{tree}").unwrap(); - let u2 = Unit::from_str("m2/{vine}").unwrap(); + let u1 = Unit::from_str("m2/{tree}").unwrap(); + let u2 = Unit::from_str("m2/{vine}").unwrap(); let converted = m1.convert_to(&u1).unwrap(); @@ -156,13 +152,10 @@ mod tests { #[test] fn validate_arbitrary_num_conversions() { - let m1 = Measurement::try_new( - 10.0, - "{tree}/[acr_us]" - ).unwrap(); + let m1 = Measurement::try_new(10.0, "{tree}/[acr_us]").unwrap(); - let u1 = Unit::from_str("{tree}/m2").unwrap(); - let u2 = Unit::from_str("{vine}/m2").unwrap(); + let u1 = Unit::from_str("{tree}/m2").unwrap(); + let u2 = Unit::from_str("{vine}/m2").unwrap(); let converted = m1.convert_to(&u1).unwrap(); @@ -174,13 +167,10 @@ mod tests { #[test] fn validate_arbitrary_conversions() { - let m1 = Measurement::try_new( - 10.0, - "{tree}" - ).unwrap(); + let m1 = Measurement::try_new(10.0, "{tree}").unwrap(); - let u1 = Unit::from_str("{tree}").unwrap(); - let u2 = Unit::from_str("{vine}").unwrap(); + let u1 = Unit::from_str("{tree}").unwrap(); + let u2 = Unit::from_str("{vine}").unwrap(); let converted = m1.convert_to(&u1).unwrap(); @@ -189,5 +179,4 @@ mod tests { assert!(m1.convert_to(&u2).is_err()); } - } diff --git a/api/src/measurement/ops.rs b/api/src/measurement/ops.rs index 498512ed..e7f7c949 100644 --- a/api/src/measurement/ops.rs +++ b/api/src/measurement/ops.rs @@ -328,9 +328,9 @@ mod tests { } mod add { - use crate::Unit; - use crate::Term; use crate::error; + use crate::Term; + use crate::Unit; use super::*; @@ -381,8 +381,7 @@ mod tests { assert_eq!((&m1 + m2).unwrap(), expected); } - - + #[test] fn validate_sub_arbitrary() { let term_tree = term!(annotation: "tree".to_string()); @@ -394,7 +393,6 @@ mod tests { assert_eq!((&m1 - m2).unwrap(), expected); } - } mod sub { diff --git a/api/src/parser/definition.rs b/api/src/parser/definition.rs index 2d23cda5..a859d8d4 100644 --- a/api/src/parser/definition.rs +++ b/api/src/parser/definition.rs @@ -50,26 +50,29 @@ impl Definition { impl Reducible for Definition { fn reduce_value(&self, other_value: f64) -> f64 { self.function_set.as_ref().map_or_else( - || if self.is_unity() { - self.value - } else { - self.value * self.terms.reduce_value(other_value) - }, - |f| (f.convert_to)(other_value) + || { + if self.is_unity() { + self.value + } else { + self.value * self.terms.reduce_value(other_value) + } + }, + |f| (f.convert_to)(other_value), ) } fn calculate_magnitude(&self, other_value: f64) -> f64 { self.function_set.as_ref().map_or_else( - || if self.is_unity() { - self.value - } else { - self.value * self.terms.calculate_magnitude(other_value) + || { + if self.is_unity() { + self.value + } else { + self.value * self.terms.calculate_magnitude(other_value) + } }, - |f| (f.convert_from)(other_value) + |f| (f.convert_from)(other_value), ) } - } impl Default for Definition { diff --git a/api/src/parser/term/composable.rs b/api/src/parser/term/composable.rs index 5d576c18..c90b2be9 100644 --- a/api/src/parser/term/composable.rs +++ b/api/src/parser/term/composable.rs @@ -14,8 +14,10 @@ impl Composable for Term { || Composition::default(), |atom| { let atom_composition = atom.composition(); - self.exponent.map_or(atom_composition, |term_exponent| atom_composition * term_exponent) - } + self.exponent.map_or(atom_composition, |term_exponent| { + atom_composition * term_exponent + }) + }, ) } } diff --git a/api/src/parser/term/invert.rs b/api/src/parser/term/invert.rs index 1ce1d913..b54f4c49 100644 --- a/api/src/parser/term/invert.rs +++ b/api/src/parser/term/invert.rs @@ -4,13 +4,10 @@ use crate::invert::{Invert, ToInverse}; // Term impl Invert for &mut Term { fn invert(self) { - self.exponent = self.exponent.map_or( - Some(-1), - |e| match e { - -1 => None, - _ => Some(-e), - } - ); + self.exponent = self.exponent.map_or(Some(-1), |e| match e { + -1 => None, + _ => Some(-e), + }); } } diff --git a/api/src/parser/term/is_compatible_with.rs b/api/src/parser/term/is_compatible_with.rs index bc19bdf4..8e2396ed 100644 --- a/api/src/parser/term/is_compatible_with.rs +++ b/api/src/parser/term/is_compatible_with.rs @@ -144,6 +144,5 @@ mod tests { let rhs_plant = term!(annotation: "plant".to_string()); assert!(!lhs_tree.is_compatible_with(&rhs_plant)); } - } } diff --git a/api/src/parser/term/reducible.rs b/api/src/parser/term/reducible.rs index e560fa6b..f373ff2b 100644 --- a/api/src/parser/term/reducible.rs +++ b/api/src/parser/term/reducible.rs @@ -41,15 +41,12 @@ fn combine_term_values( let a_p_product = calculated_atom * calculated_prefix; factor.map_or_else( - || exponent.map_or(a_p_product, |e| a_p_product.powi(e)), + || exponent.map_or(a_p_product, |e| a_p_product.powi(e)), |f| { let product = a_p_product * f64::from(f); exponent.map_or(product, |e| product.powi(e)) - } + }, ) - - - } #[cfg(test)] diff --git a/api/src/parser/terms/mapper/exponent.rs b/api/src/parser/terms/mapper/exponent.rs index e537dd8f..96c0417e 100644 --- a/api/src/parser/terms/mapper/exponent.rs +++ b/api/src/parser/terms/mapper/exponent.rs @@ -37,11 +37,11 @@ impl Visit for Exponent { fn parse_second_token(next: Option>) -> Result { next.map_or_else( - || unreachable!(), + || unreachable!(), |second| match second.as_rule() { TermRule::digits => Digits::visit(second), _ => unreachable!(), - } + }, ) } diff --git a/api/src/unit/field_eq.rs b/api/src/unit/field_eq.rs index 72d4778c..3a0f4f41 100644 --- a/api/src/unit/field_eq.rs +++ b/api/src/unit/field_eq.rs @@ -33,10 +33,11 @@ impl<'a> FieldEq<'a> for Unit { fn sort_em(terms: &[Term]) -> Vec { let mut t = terms.to_vec(); - t.sort_by( - |a, b| - a.scalar().partial_cmp(&b.scalar()).map_or(Ordering::Equal, |ordering| ordering) - ); + t.sort_by(|a, b| { + a.scalar() + .partial_cmp(&b.scalar()) + .map_or(Ordering::Equal, |ordering| ordering) + }); t } From 46a8529f71e0e8c00d3ab41fbb8ee9e620ff0bea Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 19 May 2023 09:36:42 -0700 Subject: [PATCH 12/80] Create dependabot.yml --- .github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..e8d486ab --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "cargo" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" From 3c682e0c594273956c7817c59569abe759d6cdba Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Wed, 14 Jun 2023 16:04:54 -0700 Subject: [PATCH 13/80] PCC-175 Update deps Update changelog, readme --- Cargo.toml | 16 ++++++++++------ README.md | 2 +- api/CHANGELOG.md | 6 ++++++ api/Cargo.toml | 10 +++++----- api/src/measurement/ops.rs | 1 - atom_generator/Cargo.toml | 7 +++---- atom_generator/src/from_toml/custom_atoms.rs | 5 ++++- atom_generator/src/generator/handlebars.rs | 6 ++++-- atom_generator/src/main.rs | 9 --------- atom_generator/src/rust_structs.rs | 2 +- .../src/rust_structs/pest_symbol_list.rs | 2 ++ atom_generator/src/rust_structs/rust_atom.rs | 2 +- .../src/rust_structs/rust_classification_list.rs | 5 +++-- .../src/rust_structs/rust_function_set.rs | 2 +- .../src/rust_structs/rust_mapper_list.rs | 2 ++ .../src/rust_structs/rust_property_list.rs | 1 + atom_generator/src/toml_structs/toml_atom.rs | 1 + .../src/toml_structs/toml_atom_list.rs | 2 +- .../src/toml_structs/toml_base_unit.rs | 2 +- .../src/toml_structs/toml_custom_atom_list.rs | 2 +- .../src/toml_structs/toml_definition.rs | 2 ++ atom_generator/src/toml_structs/toml_prefix.rs | 2 +- atom_generator/src/toml_structs/toml_unit.rs | 2 +- definition_fetcher/Cargo.toml | 6 +++--- definition_fetcher/src/main.rs | 4 ++-- ffi/Cargo.toml | 6 +++--- 26 files changed, 60 insertions(+), 47 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 704f0638..6fc93ec8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,11 @@ [workspace] -members = [ - "api", - "atom_generator", - "definition_fetcher", - "ffi", -] +members = ["api", "atom_generator", "definition_fetcher", "ffi"] + +[workspace.package] +rust-version = "1.64.0" + +[workspace.dependencies] +approx = "0.5" +ffi_common = { version = "0.7", registry = "crates-registry" } +lazy_static = "1.4" +serde = { version = "1.0", features = ["derive"] } diff --git a/README.md b/README.md index 28e30df3..e9364798 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ terms. It's similar to Ruby's [unitwise](https://github.com/joshwlewis/unitwise) ## Prerequisites -- Rust 1.56 +- Rust 1.64 - Get it [here](https://rustup.rs/) ## Usage diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 592284a6..9a5a613f 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [unreleased] + +### Changed + +- Rust minimum version updated to `1.64.0`. + ## [0.22.0] - 2022-03-23 ### Added diff --git a/api/Cargo.toml b/api/Cargo.toml index 7779741b..41c0deb2 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -9,17 +9,17 @@ edition = "2021" publish = ["crates-registry"] [dependencies] -approx = "0.5" -ffi_common = { version = "0.7", registry = "crates-registry", optional = true } +approx.workspace = true +ffi_common = { workspace = true, optional = true } pest = "^2.1" pest_derive = "^2.1" -serde = { version = "1.0", optional = true, features = ["derive"] } +serde = { workspace = true, optional = true } thiserror = "1.0" [dev-dependencies] bincode = "1.3" -criterion = "0.3" -lazy_static = "1.4" +criterion = "0.5" +lazy_static.workspace = true rmp-serde = "1.0" serde_json = "1.0" diff --git a/api/src/measurement/ops.rs b/api/src/measurement/ops.rs index e7f7c949..840b039c 100644 --- a/api/src/measurement/ops.rs +++ b/api/src/measurement/ops.rs @@ -328,7 +328,6 @@ mod tests { } mod add { - use crate::error; use crate::Term; use crate::Unit; diff --git a/atom_generator/Cargo.toml b/atom_generator/Cargo.toml index c1bc8f5a..25e34435 100644 --- a/atom_generator/Cargo.toml +++ b/atom_generator/Cargo.toml @@ -8,9 +8,8 @@ publish = false [dependencies] handlebars = "4.0" heck = "0.4" -lazy_static = "1.0" +lazy_static.workspace = true log = "0.4" regex = "1.0" -serde = "1.0" -serde_derive = "1.0" -toml = "0.5" +serde.workspace = true +toml = "0.7" diff --git a/atom_generator/src/from_toml/custom_atoms.rs b/atom_generator/src/from_toml/custom_atoms.rs index 1c60ffc3..40609164 100644 --- a/atom_generator/src/from_toml/custom_atoms.rs +++ b/atom_generator/src/from_toml/custom_atoms.rs @@ -1,6 +1,9 @@ -use crate::{rust_structs::RustAtomList, toml_structs::TomlCustomAtomList}; use std::{env, fs::File, io::Read, path::Path, str::FromStr}; +use log::debug; + +use crate::{rust_structs::RustAtomList, toml_structs::TomlCustomAtomList}; + static CUSTOM_ATOMS_FILE_NAME: &str = "CustomAtoms.toml"; /// Reads the `Atoms.toml` file (containing UCUM unit definitions) that's part diff --git a/atom_generator/src/generator/handlebars.rs b/atom_generator/src/generator/handlebars.rs index 79260233..25815490 100644 --- a/atom_generator/src/generator/handlebars.rs +++ b/atom_generator/src/generator/handlebars.rs @@ -1,6 +1,8 @@ -use super::{atom, classification, mapper, property, symbol_grammar}; -use handlebars::Handlebars; +use handlebars::{handlebars_helper, Handlebars}; use heck::ToUpperCamelCase; +use lazy_static::lazy_static; + +use super::{atom, classification, mapper, property, symbol_grammar}; handlebars_helper!(camel_case_helper: |word: str| word.to_upper_camel_case()); diff --git a/atom_generator/src/main.rs b/atom_generator/src/main.rs index 7b5c2d46..acef435d 100644 --- a/atom_generator/src/main.rs +++ b/atom_generator/src/main.rs @@ -17,15 +17,6 @@ )] #![allow(clippy::redundant_pub_crate)] -#[macro_use(handlebars_helper)] -extern crate handlebars; -#[macro_use] -extern crate lazy_static; -#[macro_use] -extern crate log; -#[macro_use] -extern crate serde_derive; - mod from_toml; mod generator; mod rust_structs; diff --git a/atom_generator/src/rust_structs.rs b/atom_generator/src/rust_structs.rs index e0216cf7..aeaa277d 100644 --- a/atom_generator/src/rust_structs.rs +++ b/atom_generator/src/rust_structs.rs @@ -13,7 +13,7 @@ pub(crate) use self::{ use heck::ToSnakeCase; -#[derive(Debug, Serialize)] +#[derive(Debug, serde::Serialize)] pub(crate) struct RustAtomList { pub(crate) atoms: Vec, } diff --git a/atom_generator/src/rust_structs/pest_symbol_list.rs b/atom_generator/src/rust_structs/pest_symbol_list.rs index 1e5ca171..7b97ce7b 100644 --- a/atom_generator/src/rust_structs/pest_symbol_list.rs +++ b/atom_generator/src/rust_structs/pest_symbol_list.rs @@ -1,3 +1,5 @@ +use serde::Serialize; + use super::RustAtomList; #[derive(Debug, Serialize)] diff --git a/atom_generator/src/rust_structs/rust_atom.rs b/atom_generator/src/rust_structs/rust_atom.rs index ddda6dcb..ca2fc3e7 100644 --- a/atom_generator/src/rust_structs/rust_atom.rs +++ b/atom_generator/src/rust_structs/rust_atom.rs @@ -1,4 +1,4 @@ -#[derive(Debug, Serialize)] +#[derive(Debug, serde::Serialize)] pub(crate) struct RustAtom { pub(crate) type_name: String, pub(crate) classification: String, diff --git a/atom_generator/src/rust_structs/rust_classification_list.rs b/atom_generator/src/rust_structs/rust_classification_list.rs index 14f47a17..bbdcda6c 100644 --- a/atom_generator/src/rust_structs/rust_classification_list.rs +++ b/atom_generator/src/rust_structs/rust_classification_list.rs @@ -1,7 +1,8 @@ -use super::RustAtomList; use std::collections::HashSet; -#[derive(Debug, Serialize)] +use super::RustAtomList; + +#[derive(Debug, serde::Serialize)] pub(crate) struct RustClassificationList { pub(crate) type_names: Vec, } diff --git a/atom_generator/src/rust_structs/rust_function_set.rs b/atom_generator/src/rust_structs/rust_function_set.rs index 94eb1381..2398ef64 100644 --- a/atom_generator/src/rust_structs/rust_function_set.rs +++ b/atom_generator/src/rust_structs/rust_function_set.rs @@ -1,4 +1,4 @@ -#[derive(Debug, Serialize)] +#[derive(Debug, serde::Serialize)] pub(crate) struct RustFunctionSet { // AKA "calculate_magnitude" pub(crate) convert_from: String, diff --git a/atom_generator/src/rust_structs/rust_mapper_list.rs b/atom_generator/src/rust_structs/rust_mapper_list.rs index b59cbae2..64392b82 100644 --- a/atom_generator/src/rust_structs/rust_mapper_list.rs +++ b/atom_generator/src/rust_structs/rust_mapper_list.rs @@ -1,3 +1,5 @@ +use serde::Serialize; + use super::RustAtomList; use std::collections::HashMap; diff --git a/atom_generator/src/rust_structs/rust_property_list.rs b/atom_generator/src/rust_structs/rust_property_list.rs index e900c469..107faa04 100644 --- a/atom_generator/src/rust_structs/rust_property_list.rs +++ b/atom_generator/src/rust_structs/rust_property_list.rs @@ -1,5 +1,6 @@ use super::RustAtomList; use heck::ToUpperCamelCase; +use serde::Serialize; use std::collections::HashMap; type PropertyTypeName = String; diff --git a/atom_generator/src/toml_structs/toml_atom.rs b/atom_generator/src/toml_structs/toml_atom.rs index 5cec036b..b926c2ae 100644 --- a/atom_generator/src/toml_structs/toml_atom.rs +++ b/atom_generator/src/toml_structs/toml_atom.rs @@ -1,4 +1,5 @@ use heck::ToUpperCamelCase; +use lazy_static::lazy_static; use regex::Regex; lazy_static! { diff --git a/atom_generator/src/toml_structs/toml_atom_list.rs b/atom_generator/src/toml_structs/toml_atom_list.rs index 76972d29..83e34029 100644 --- a/atom_generator/src/toml_structs/toml_atom_list.rs +++ b/atom_generator/src/toml_structs/toml_atom_list.rs @@ -1,7 +1,7 @@ use super::{TomlBaseUnit, TomlUnit}; use std::str::FromStr; -#[derive(Debug, Deserialize)] +#[derive(Debug, serde::Deserialize)] pub(crate) struct TomlAtomList { #[serde(rename = "base-unit")] pub(crate) base_units: Vec, diff --git a/atom_generator/src/toml_structs/toml_base_unit.rs b/atom_generator/src/toml_structs/toml_base_unit.rs index 61282704..95514e2e 100644 --- a/atom_generator/src/toml_structs/toml_base_unit.rs +++ b/atom_generator/src/toml_structs/toml_base_unit.rs @@ -1,6 +1,6 @@ use crate::toml_structs::TomlAtom; -#[derive(Debug, Deserialize)] +#[derive(Debug, serde::Deserialize)] pub(crate) struct TomlBaseUnit { #[serde(rename = "Code")] pub(crate) primary_code: String, diff --git a/atom_generator/src/toml_structs/toml_custom_atom_list.rs b/atom_generator/src/toml_structs/toml_custom_atom_list.rs index 24db2081..c928ed5f 100644 --- a/atom_generator/src/toml_structs/toml_custom_atom_list.rs +++ b/atom_generator/src/toml_structs/toml_custom_atom_list.rs @@ -1,7 +1,7 @@ use super::{TomlBaseUnit, TomlUnit}; use std::str::FromStr; -#[derive(Debug, Deserialize)] +#[derive(Debug, serde::Deserialize)] pub(crate) struct TomlCustomAtomList { #[serde(rename = "base-unit")] pub(crate) base_units: Option>, diff --git a/atom_generator/src/toml_structs/toml_definition.rs b/atom_generator/src/toml_structs/toml_definition.rs index 38389b79..4eabc33d 100644 --- a/atom_generator/src/toml_structs/toml_definition.rs +++ b/atom_generator/src/toml_structs/toml_definition.rs @@ -1,3 +1,5 @@ +use serde::Deserialize; + #[derive(Debug, Deserialize, Clone)] pub(crate) struct TomlDefinition { #[serde(default = "default_value")] diff --git a/atom_generator/src/toml_structs/toml_prefix.rs b/atom_generator/src/toml_structs/toml_prefix.rs index cad1afb7..07a8af6b 100644 --- a/atom_generator/src/toml_structs/toml_prefix.rs +++ b/atom_generator/src/toml_structs/toml_prefix.rs @@ -1,5 +1,5 @@ #[allow(dead_code)] -#[derive(Debug, Deserialize)] +#[derive(Debug, serde::Deserialize)] pub(crate) struct TomlPrefix { #[serde(rename = "Code")] pub(crate) primary_code: String, diff --git a/atom_generator/src/toml_structs/toml_unit.rs b/atom_generator/src/toml_structs/toml_unit.rs index 7961f6e5..5c8a7d94 100644 --- a/atom_generator/src/toml_structs/toml_unit.rs +++ b/atom_generator/src/toml_structs/toml_unit.rs @@ -1,6 +1,6 @@ use super::{TomlAtom, TomlDefinition}; -#[derive(Debug, Deserialize)] +#[derive(Debug, serde::Deserialize)] #[serde(rename_all = "camelCase")] pub(crate) struct TomlUnit { #[serde(rename = "Code")] diff --git a/definition_fetcher/Cargo.toml b/definition_fetcher/Cargo.toml index 09920cc3..9804f5d0 100644 --- a/definition_fetcher/Cargo.toml +++ b/definition_fetcher/Cargo.toml @@ -8,6 +8,6 @@ publish = false [dependencies] reqwest = "0.11" serde-transcode = "1.0" -serde-xml-rs = "0.5" -simple_logger = "2.1" -toml = "0.5" +serde-xml-rs = "0.6" +simple_logger = "4.2" +toml = "0.7" diff --git a/definition_fetcher/src/main.rs b/definition_fetcher/src/main.rs index 0678cf5b..8c514cc4 100644 --- a/definition_fetcher/src/main.rs +++ b/definition_fetcher/src/main.rs @@ -58,9 +58,9 @@ fn transcode(xml_string: &str) -> String { { let mut deserializer = serde_xml_rs::Deserializer::new_from_reader(xml_string.as_bytes()); - let mut serializer = toml::ser::Serializer::pretty(&mut toml_string); + let serializer = toml::ser::Serializer::pretty(&mut toml_string); - serde_transcode::transcode(&mut deserializer, &mut serializer) + serde_transcode::transcode(&mut deserializer, serializer) .expect("Unable to translcode XML to TOML"); } diff --git a/ffi/Cargo.toml b/ffi/Cargo.toml index dd021716..4be88185 100644 --- a/ffi/Cargo.toml +++ b/ffi/Cargo.toml @@ -9,14 +9,14 @@ edition = "2021" publish = ["crates-registry"] [dependencies] -ffi_common = { version = "0.7", registry = "crates-registry" } +ffi_common.workspace = true wise_units = { version = "0.22", registry = "crates-registry" } [build-dependencies] -cbindgen = "0.20" +cbindgen = "0.24" [dev-dependencies] -approx = "0.5" +approx.workspace = true [lib] crate-type = ["staticlib", "rlib", "cdylib"] From 16ce2a13d3acc75bbac1f8b41db7adff02f707a6 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Wed, 14 Jun 2023 16:08:24 -0700 Subject: [PATCH 14/80] cargo clippy --- api/src/measurement/convertible.rs | 8 ++++---- api/src/unit/custom_ffi.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/api/src/measurement/convertible.rs b/api/src/measurement/convertible.rs index eaaf18e1..ee0368be 100644 --- a/api/src/measurement/convertible.rs +++ b/api/src/measurement/convertible.rs @@ -144,8 +144,8 @@ mod tests { let converted = m1.convert_to(&u1).unwrap(); - assert_relative_eq!(converted.value, 40468.72609874252); - assert_ulps_eq!(converted.value, 40468.72609874252); + assert_relative_eq!(converted.value, 40_468.726_098_742_52); + assert_ulps_eq!(converted.value, 40_468.726_098_742_52); assert!(m1.convert_to(&u2).is_err()); } @@ -159,8 +159,8 @@ mod tests { let converted = m1.convert_to(&u1).unwrap(); - assert_relative_eq!(converted.value, 0.002471043930466279); - assert_ulps_eq!(converted.value, 0.002471043930466279); + assert_relative_eq!(converted.value, 0.002_471_043_930_466_279); + assert_ulps_eq!(converted.value, 0.002_471_043_930_466_279); assert!(m1.convert_to(&u2).is_err()); } diff --git a/api/src/unit/custom_ffi.rs b/api/src/unit/custom_ffi.rs index b85c7cff..0ac3c504 100644 --- a/api/src/unit/custom_ffi.rs +++ b/api/src/unit/custom_ffi.rs @@ -31,7 +31,7 @@ pub unsafe extern "C" fn unit_init(required_expression: *const c_char) -> *const #[allow(box_pointers)] #[no_mangle] pub unsafe extern "C" fn clone_unit(ptr: *const Unit) -> *const Unit { - Box::into_raw(Box::new((&*ptr).clone())) + Box::into_raw(Box::new((*ptr).clone())) } /// Returns the `expression` for the `Unit` behind `ptr` as a C string. @@ -42,5 +42,5 @@ pub unsafe extern "C" fn clone_unit(ptr: *const Unit) -> *const Unit { /// #[no_mangle] pub unsafe extern "C" fn get_unit_expression(ptr: *const Unit) -> *const c_char { - core::ffi_string!((&*ptr).expression()) + core::ffi_string!((*ptr).expression()) } From dedc4c730d5ff241231e23232ce58168976e2ef3 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Wed, 14 Jun 2023 16:08:49 -0700 Subject: [PATCH 15/80] cargo fmt --- api/src/measurement/ops.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api/src/measurement/ops.rs b/api/src/measurement/ops.rs index 840b039c..192436d5 100644 --- a/api/src/measurement/ops.rs +++ b/api/src/measurement/ops.rs @@ -328,8 +328,7 @@ mod tests { } mod add { - use crate::Term; - use crate::Unit; + use crate::{Term, Unit}; use super::*; From b1e15b01bba186a505785d83a9bdac75416c20f9 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Wed, 14 Jun 2023 16:36:32 -0700 Subject: [PATCH 16/80] PCC-174 derive Hash for Atom; update atom_generator Update changelog with codegen changes clippy; refix symbol.pest.hbs Fix clippies for generated FunctionSets atom_gen: use quote for atom atom_gen: Use quote for property atom_gen: No need to generate mapper atom_gen: Use quote, syn for generating classification Fix the borks --- api/CHANGELOG.md | 76 +- api/src/parser/atom.rs | 995 +++++++------- api/src/parser/atom/composable.rs | 16 + api/src/parser/atom/display.rs | 9 + api/src/parser/atom/hash.rs | 9 + api/src/parser/atom/partial_eq.rs | 11 + api/src/parser/atom/reducible.rs | 15 + api/src/parser/classification.rs | 3 - api/src/parser/property.rs | 1182 ++++------------- api/src/parser/symbols/mapper.rs | 5 - api/src/parser/symbols/symbol.pest | 2 - atom_generator/Cargo.toml | 5 + atom_generator/src/from_toml.rs | 168 ++- atom_generator/src/from_toml/atoms.rs | 2 +- atom_generator/src/from_toml/custom_atoms.rs | 2 +- atom_generator/src/generator.rs | 55 +- atom_generator/src/generator/atom.rs | 83 +- .../src/generator/classification.rs | 92 +- atom_generator/src/generator/handlebars.rs | 14 +- atom_generator/src/generator/mapper.rs | 12 - atom_generator/src/generator/property.rs | 72 +- atom_generator/src/rust_structs.rs | 24 +- .../src/rust_structs/pest_symbol_list.rs | 13 +- atom_generator/src/rust_structs/rust_atom.rs | 15 - .../src/rust_structs/rust_atom_list.rs | 251 ++++ .../src/rust_structs/rust_function_set.rs | 14 +- .../src/rust_structs/rust_mapper_list.rs | 42 - .../src/rust_structs/rust_property_list.rs | 66 +- atom_generator/src/templates/atom.rs.hbs | 178 --- .../src/templates/classification.rs.hbs | 19 - atom_generator/src/templates/mapper.rs.hbs | 21 - atom_generator/src/templates/property.rs.hbs | 71 - atom_generator/src/templates/symbol.pest.hbs | 53 +- 33 files changed, 1653 insertions(+), 1942 deletions(-) create mode 100644 api/src/parser/atom/composable.rs create mode 100644 api/src/parser/atom/display.rs create mode 100644 api/src/parser/atom/hash.rs create mode 100644 api/src/parser/atom/partial_eq.rs create mode 100644 api/src/parser/atom/reducible.rs delete mode 100644 atom_generator/src/generator/mapper.rs delete mode 100644 atom_generator/src/rust_structs/rust_atom.rs create mode 100644 atom_generator/src/rust_structs/rust_atom_list.rs delete mode 100644 atom_generator/src/rust_structs/rust_mapper_list.rs delete mode 100644 atom_generator/src/templates/atom.rs.hbs delete mode 100644 atom_generator/src/templates/classification.rs.hbs delete mode 100644 atom_generator/src/templates/mapper.rs.hbs delete mode 100644 atom_generator/src/templates/property.rs.hbs diff --git a/api/CHANGELOG.md b/api/CHANGELOG.md index 9a5a613f..77a4dc00 100644 --- a/api/CHANGELOG.md +++ b/api/CHANGELOG.md @@ -7,11 +7,17 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [unreleased] +### Added + +- PCC-174: Derive `Hash` for `Atom`. + ### Changed - Rust minimum version updated to `1.64.0`. +- (Internal) Rust Codegen is now using `quote` instead of `handlebars` (the pest parser grammar is + still generated using `handlebars`). -## [0.22.0] - 2022-03-23 +## [0.22.0] — 2022-03-23 ### Added @@ -31,7 +37,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Changed `AsFraction` trait definition to allow for non-optional `Numerator` and `Denominator`. - Updated to Rust edition `2021`. -## [0.21.1] - 2021-11-19 +## [0.21.1] — 2021-11-19 ### Changed @@ -41,7 +47,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - gh-35: Use a separate rule for parsing annotations--one that permits more characters. -## [0.21.0] - 2021-10-20 +## [0.21.0] — 2021-10-20 ### Added @@ -56,28 +62,28 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Fixed -- Manually implemeted `PartialEq` for `Term`, comparing the composition and `scalar()` +- Manually implemented `PartialEq` for `Term`, comparing the composition and `scalar()` value (like `Measurement` and `Unit`). -## [0.20.0] - 2021-09-29 +## [0.20.0] — 2021-09-29 ### Changed - Updated deps: - `ffi_common` to 0.6.0. -## [0.19.0] - 2021-09-22 +## [0.19.0] — 2021-09-22 ### Added -- Derive FFI for `Measurement` and `Unit` things. +- Derive `FFI` for `Measurement` and `Unit` things. ### Changed - Updated deps: - `ffi_common` to 0.5.0. -## [0.18.0] - 2021-08-11 +## [0.18.0] — 2021-08-11 ### Changed @@ -91,13 +97,13 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - _BREAKING_: Removed `impl From> for Unit`; replaced with standard constructor: `Unit::new(terms)`. -## [0.17.1] - 2021-07-16 +## [0.17.1] — 2021-07-16 ### Changed - Point `ffi_derive`, `ffi_common` to 0.3.0. -## [0.17.0] - 2021-07-16 +## [0.17.0] — 2021-07-16 ### Changed @@ -114,7 +120,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). `impl IsCompatibleWith for Term`. - _BREAKING_ (maybe?): `impl<'a, 'b> IsCompatibleWith<&'b [Term]> for &'a [Term]>` is now `impl IsCompatibleWith for Vec`. - - _BREAKING_ (maybe?): `impl<'a> Compsable for &'a [Term]` is now `impl Composable for Vec`. + - _BREAKING_ (maybe?): `impl<'a> Composable for &'a [Term]` is now `impl Composable for Vec`. - Updated `pest` to `2.0` - Refactored parser. - Made functions `const`: @@ -125,7 +131,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - `Term::has_value()` - `Term::exponent_is_positive()` - `Term::exponent_is_negative()` -- Updated functions used for converting some arbitrary units to use more accurate implementations: +- Updated functions used for converting some arbitrary units to use more correct implementations: - `Neper` - `MeterPerSquareSecondsPerSquareRootOfHertz` - `BitLogarithmusDualis` @@ -138,7 +144,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Used [typos](https://github.com/crate-ci/typos) to find and fix typos. This included some internal types. -## [0.16.0] - 2020-12-16 +## [0.16.0] — 2020-12-16 ### Added @@ -153,20 +159,20 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Pointed `agrian-registry` to GitHub. -## [0.15.0] - 2020-07-31 +## [0.15.0] — 2020-07-31 ### Changed - No longer generate code every time we build. That code now just needs to be manually generated any time `Atoms.toml` is updated. -## [0.14.1] - 2020-07-22 +## [0.14.1] — 2020-07-22 ### Fixed - Removed `serde_json` as a dep for the `atom_generator`, resolving downstream serialization issues. -## [0.14.0] - 2020-05-08 +## [0.14.0] — 2020-05-08 ### Added @@ -178,7 +184,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Switched internal error-helper crate from `failure` to `thiserror`. -## [0.13.0] - 2020-03-20 +## [0.13.0] — 2020-03-20 ### Added @@ -194,7 +200,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - `parser::property::Property`'s implementation of `Display` wasn't working. -## [0.12.0] - 2019-11-07 +## [0.12.0] — 2019-11-07 ### Added @@ -202,7 +208,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). wrapper types around `Measurement` and `Unit`. - Derive `Clone` for `error::Error` and `parser::Error`. -## [0.11.0] - 2019-07-17 +## [0.11.0] — 2019-07-17 ### Added @@ -223,7 +229,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Removed `derive(Serialize, Deserialize)` from `Atom`, `Prefix`, and `Term` since these no longer need to be (de)serialized. -## [0.10.0] - 2019-01-11 +## [0.10.0] — 2019-01-11 ### Added @@ -232,12 +238,12 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). errors with that. The new type should provide errors for the whole crate and thus wraps the old `parser::error::Error` as needed. Also moved the `IncompatibleUnitTypes` variant to the new type. The new type also implements `From` for ergonomic conversions. -- [DEV-4385] Implemented all of the `invert` traits for `Measurement`. Seems I forgot to do that for +- [DEV-4385] Implemented all the `invert` traits for `Measurement`. Seems I forgot to do that for 0.9.0. This also required a new `DivideByZero` error variant in the new `error::Error`. ...which also required changing the `ToInverse` and `IntoInverse` traits to add an `Output` associated type to allow clients to handle the `DivideByZero` case. -## [0.9.0] - 2019-01-10 +## [0.9.0] — 2019-01-10 ### Added @@ -257,20 +263,20 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Removed `decomposer::Deomposable` and turned the old `Simple` decomposer struct into a function, `decomposer::decompose()`. -## [0.8.0] - 2019-01-09 +## [0.8.0] — 2019-01-09 ### Added - [DEV-4413] Added `IntoReduced` trait and implemented for `Measurement` and `Unit`. -## [0.7.1] - 2019-01-08 +## [0.7.1] — 2019-01-08 ### Changed - Updated implementations of `Div` and `Mul` for `Unit` to be more performant. - Updated implementation of `IntoInverse` for `Vec` to be more performant. -## [0.7.0] - 2019-01-07 +## [0.7.0] — 2019-01-07 ### Added @@ -293,7 +299,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - [DEV-4385] Removed `Term::invert_exponent` in favor of the new implementations of `Invert` and `IntoInverse`. -## [0.6.0] - 2019-01-04 +## [0.6.0] — 2019-01-04 ### Added @@ -304,14 +310,14 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - `Unit::from_str("1")` didn't parse such that `unit.terms[0].is_unity()` returned `true`; it now skips parsing and just returns a proper `Unit`. -## [0.5.1] - 2018-11-06 +## [0.5.1] — 2018-11-06 ### Changed - [DEV-3155] Reverted the change to the `Composable` trait definition to deal only with `self`; this caused `cannot move out of borrowed content` errors when trying to use the API normally. -## [0.5.0] - 2018-11-06 +## [0.5.0] — 2018-11-06 ### Added @@ -345,7 +351,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - [DEV-3300] Parsing annotations now excludes curly braces in the resulting string capture. -## [0.4.0] - 2018-10-02 +## [0.4.0] — 2018-10-02 ### Added @@ -363,7 +369,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). possible that a `Unit` with 0 `Term`s may still be interpreted similarly (haven't looked into this yet). -## [0.3.0] - 2018-08-27 +## [0.3.0] — 2018-08-27 ### Added @@ -383,7 +389,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - `Decomposable::decompose()` now takes a value to let the caller decide what to pass in. - `Decomposable` now defines associated types for more `impl` flexibility. - Extracted some of `Decomposable::decompose()` to a new method, `Decomposable::format_output()`, - which let's consumers customize the formatted output. + which lets consumers customize the formatted output. - `Decomposable::numerator()` and `Decomposable::denominator()` now return `Option` instead of `String`. - Refactored a number of `Decomposable` implementation methods. @@ -398,7 +404,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - To match SI displaying, added a space for the implementation of `Display` for `Measurement` in between the value and the unit. -## [0.2.0] - 2018-06-26 +## [0.2.0] — 2018-06-26 ### Added @@ -416,14 +422,14 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Removed implementations of `Add`, `Sub`, `Mul`, `Div` for `&'a mut Measurement` and `&'a mut Unit`. Those seem like edge-cases and thus code bloat at this point. -## [0.2.0] - 2018-06-26 +## [0.2.0] — 2018-06-26 ### Added - [AGDEV-30315] Add serde support using "with_serde" feature flag. - [AGDEV-30253] Add stdweb support using "with_stdweb" feature flag. Just adds `js_serializable!` and `js_deserializable!` for both `Measurement` and `Unit`. -- The `UcumUnit` trait now handles some of the core attributes defined by the UCUM spec. `Atom`, +- The `UcumUnit` trait now handles some core attributes defined by the UCUM spec. `Atom`, `Term`, `Unit`, and `Measurement` implement this. - The `Convertible` trait allows for converting to different objects using `convert_to()`. `Measurement` implements this for `Unit` and `&str`. @@ -473,7 +479,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Removed `Atom::TheUnity` in favor of dealing with this as a `Term` with a `factor` of 1. - `Composable::composition()` now returns a `Composition` instead of `Option`. -## [0.1.0] - 2018-01-22 +## [0.1.0] — 2018-01-22 ### Added diff --git a/api/src/parser/atom.rs b/api/src/parser/atom.rs index d67eefee..c765eb76 100644 --- a/api/src/parser/atom.rs +++ b/api/src/parser/atom.rs @@ -3,17 +3,19 @@ // This is generated by wise_units-atom_generator. //----------------------------------------------------------------------------- +mod composable; +mod display; +mod hash; +mod partial_eq; +mod reducible; use crate::{ - is_compatible_with::{DefaultCompatibility, IsCompatibleWith}, + is_compatible_with::DefaultCompatibility, parser::{ - definition::Definition, function_set::FunctionSet, Classification, Composable, Composition, - Dimension, Property, UcumSymbol, + definition::Definition, function_set::FunctionSet, Classification, Property, UcumSymbol, }, reducible::Reducible, UcumUnit, Unit, }; -use std::fmt; - #[derive(Clone, Copy, Debug, Eq, PartialOrd, Ord)] pub enum Atom { Meter, @@ -327,7 +329,6 @@ pub enum Atom { Byte, Baud, } - impl Atom { pub(crate) fn definition(self) -> Definition { let result = match self { @@ -338,256 +339,258 @@ impl Atom { Self::Kelvin => Ok(Definition::default()), Self::Coulomb => Ok(Definition::default()), Self::Candela => Ok(Definition::default()), - Self::TheNumberTenForArbitraryPowersStar => Definition::new(10.0, "1", None), - Self::TheNumberTenForArbitraryPowersCaret => Definition::new(10.0, "1", None), + Self::TheNumberTenForArbitraryPowersStar => Definition::new(10f64, "1", None), + Self::TheNumberTenForArbitraryPowersCaret => Definition::new(10f64, "1", None), Self::TheNumberPi => Definition::new(::std::f64::consts::PI, "1", None), - Self::Percent => Definition::new(1.0, "10*-2", None), - Self::PartsPerThousand => Definition::new(1.0, "10*-3", None), - Self::PartsPerMillion => Definition::new(1.0, "10*-6", None), - Self::PartsPerBillion => Definition::new(1.0, "10*-9", None), - Self::PartsPerTrillion => Definition::new(1.0, "10*-12", None), - Self::Mole => Definition::new(6.0221367, "10*23", None), - Self::Steradian => Definition::new(1.0, "rad2", None), - Self::Hertz => Definition::new(1.0, "s-1", None), - Self::Newton => Definition::new(1.0, "kg.m/s2", None), - Self::Pascal => Definition::new(1.0, "N/m2", None), - Self::Joule => Definition::new(1.0, "N.m", None), - Self::Watt => Definition::new(1.0, "J/s", None), - Self::Ampere => Definition::new(1.0, "C/s", None), - Self::Volt => Definition::new(1.0, "J/C", None), - Self::Farad => Definition::new(1.0, "C/V", None), - Self::Ohm => Definition::new(1.0, "V/A", None), - Self::Siemens => Definition::new(1.0, "Ohm-1", None), - Self::Weber => Definition::new(1.0, "V.s", None), + Self::Percent => Definition::new(1f64, "10*-2", None), + Self::PartsPerThousand => Definition::new(1f64, "10*-3", None), + Self::PartsPerMillion => Definition::new(1f64, "10*-6", None), + Self::PartsPerBillion => Definition::new(1f64, "10*-9", None), + Self::PartsPerTrillion => Definition::new(1f64, "10*-12", None), + Self::Mole => Definition::new(6.0221367f64, "10*23", None), + Self::Steradian => Definition::new(1f64, "rad2", None), + Self::Hertz => Definition::new(1f64, "s-1", None), + Self::Newton => Definition::new(1f64, "kg.m/s2", None), + Self::Pascal => Definition::new(1f64, "N/m2", None), + Self::Joule => Definition::new(1f64, "N.m", None), + Self::Watt => Definition::new(1f64, "J/s", None), + Self::Ampere => Definition::new(1f64, "C/s", None), + Self::Volt => Definition::new(1f64, "J/C", None), + Self::Farad => Definition::new(1f64, "C/V", None), + Self::Ohm => Definition::new(1f64, "V/A", None), + Self::Siemens => Definition::new(1f64, "Ohm-1", None), + Self::Weber => Definition::new(1f64, "V.s", None), Self::DegreeCelsius => Definition::new( - 1.0, + 1f64, "K", Some(FunctionSet { convert_from: |value: f64| value - 273.15, convert_to: |value: f64| value + 273.15, }), ), - Self::Tesla => Definition::new(1.0, "Wb/m2", None), - Self::Henry => Definition::new(1.0, "Wb/A", None), - Self::Lumen => Definition::new(1.0, "cd.sr", None), - Self::Lux => Definition::new(1.0, "lm/m2", None), - Self::Becquerel => Definition::new(1.0, "s-1", None), - Self::Gray => Definition::new(1.0, "J/kg", None), - Self::Sievert => Definition::new(1.0, "J/kg", None), - Self::Gon => Definition::new(0.9, "deg", None), - Self::Degree => Definition::new(2.0, "[pi].rad/360", None), - Self::MinuteAngle => Definition::new(1.0, "deg/60", None), - Self::SecondAngle => Definition::new(1.0, "'/60", None), - Self::Liter => Definition::new(1.0, "dm3", None), - Self::LiterSecondary => Definition::new(1.0, "l", None), - Self::Are => Definition::new(100.0, "m2", None), - Self::Minute => Definition::new(60.0, "s", None), - Self::Hour => Definition::new(60.0, "min", None), - Self::Day => Definition::new(24.0, "h", None), - Self::TropicalYear => Definition::new(365.24219, "d", None), - Self::MeanJulianYear => Definition::new(365.25, "d", None), - Self::MeanGregorianYear => Definition::new(365.2425, "d", None), - Self::Year => Definition::new(1.0, "a_j", None), - Self::Week => Definition::new(7.0, "d", None), - Self::SynodalMonth => Definition::new(29.53059, "d", None), - Self::MeanJulianMonth => Definition::new(1.0, "a_j/12", None), - Self::MeanGregorianMonth => Definition::new(1.0, "a_g/12", None), - Self::Month => Definition::new(1.0, "mo_j", None), - Self::Tonne => Definition::new(1000.0, "kg", None), - Self::Bar => Definition::new(100000.0, "Pa", None), + Self::Tesla => Definition::new(1f64, "Wb/m2", None), + Self::Henry => Definition::new(1f64, "Wb/A", None), + Self::Lumen => Definition::new(1f64, "cd.sr", None), + Self::Lux => Definition::new(1f64, "lm/m2", None), + Self::Becquerel => Definition::new(1f64, "s-1", None), + Self::Gray => Definition::new(1f64, "J/kg", None), + Self::Sievert => Definition::new(1f64, "J/kg", None), + Self::Gon => Definition::new(0.9f64, "deg", None), + Self::Degree => Definition::new(2f64, "[pi].rad/360", None), + Self::MinuteAngle => Definition::new(1f64, "deg/60", None), + Self::SecondAngle => Definition::new(1f64, "'/60", None), + Self::Liter => Definition::new(1f64, "dm3", None), + Self::LiterSecondary => Definition::new(1f64, "l", None), + Self::Are => Definition::new(100f64, "m2", None), + Self::Minute => Definition::new(60f64, "s", None), + Self::Hour => Definition::new(60f64, "min", None), + Self::Day => Definition::new(24f64, "h", None), + Self::TropicalYear => Definition::new(365.24219f64, "d", None), + Self::MeanJulianYear => Definition::new(365.25f64, "d", None), + Self::MeanGregorianYear => Definition::new(365.2425f64, "d", None), + Self::Year => Definition::new(1f64, "a_j", None), + Self::Week => Definition::new(7f64, "d", None), + Self::SynodalMonth => Definition::new(29.53059f64, "d", None), + Self::MeanJulianMonth => Definition::new(1f64, "a_j/12", None), + Self::MeanGregorianMonth => Definition::new(1f64, "a_g/12", None), + Self::Month => Definition::new(1f64, "mo_j", None), + Self::Tonne => Definition::new(1000f64, "kg", None), + Self::Bar => Definition::new(100000f64, "Pa", None), Self::UnifiedAtomicMassUnit => { - Definition::new(0.0000000000000000000000016605402, "g", None) + Definition::new(0.0000000000000000000000016605402f64, "g", None) } - Self::Electronvolt => Definition::new(1.0, "[e].V", None), - Self::AstronomicUnit => Definition::new(149597.870691, "Mm", None), - Self::Parsec => Definition::new(30856780000000000.0, "m", None), - Self::VelocityOfLight => Definition::new(299792458.0, "m/s", None), + Self::Electronvolt => Definition::new(1f64, "[e].V", None), + Self::AstronomicUnit => Definition::new(149597.870691f64, "Mm", None), + Self::Parsec => Definition::new(30856780000000000f64, "m", None), + Self::VelocityOfLight => Definition::new(299792458f64, "m/s", None), Self::PlanckConstant => { - Definition::new(0.00000000000000000000000000000000066260755, "J.s", None) + Definition::new(0.00000000000000000000000000000000066260755f64, "J.s", None) } Self::BoltzmannConstant => { - Definition::new(0.00000000000000000000001380658, "J/K", None) + Definition::new(0.00000000000000000000001380658f64, "J/K", None) + } + Self::PermittivityOfVacuum => Definition::new(0.000000000008854187817f64, "F/m", None), + Self::PermeabilityOfVacuum => Definition::new(1f64, "4.[pi].10*-7.N/A2", None), + Self::ElementaryCharge => Definition::new(0.000000000000000000160217733f64, "C", None), + Self::ElectronMass => { + Definition::new(0.00000000000000000000000000091093897f64, "g", None) } - Self::PermittivityOfVacuum => Definition::new(0.000000000008854187817, "F/m", None), - Self::PermeabilityOfVacuum => Definition::new(1.0, "4.[pi].10*-7.N/A2", None), - Self::ElementaryCharge => Definition::new(0.000000000000000000160217733, "C", None), - Self::ElectronMass => Definition::new(0.00000000000000000000000000091093897, "g", None), - Self::ProtonMass => Definition::new(0.0000000000000000000000016726231, "g", None), + Self::ProtonMass => Definition::new(0.0000000000000000000000016726231f64, "g", None), Self::NewtonianConstantOfGravitation => { - Definition::new(0.0000000000667259, "m3.kg-1.s-2", None) + Definition::new(0.0000000000667259f64, "m3.kg-1.s-2", None) } - Self::StandardAccelerationOfFreeFall => Definition::new(9.80665, "m/s2", None), - Self::StandardAtmosphere => Definition::new(101325.0, "Pa", None), - Self::LightYear => Definition::new(1.0, "[c].a_j", None), - Self::GramForce => Definition::new(1.0, "g.[g]", None), - Self::PoundForceAvoirdupois => Definition::new(1.0, "[lb_av].[g]", None), - Self::Kayser => Definition::new(1.0, "cm-1", None), - Self::Gal => Definition::new(1.0, "cm/s2", None), - Self::Dyne => Definition::new(1.0, "g.cm/s2", None), - Self::Erg => Definition::new(1.0, "dyn.cm", None), - Self::Poise => Definition::new(1.0, "dyn.s/cm2", None), - Self::Biot => Definition::new(10.0, "A", None), - Self::Stokes => Definition::new(1.0, "cm2/s", None), - Self::Maxwell => Definition::new(0.00000001, "Wb", None), - Self::Gauss => Definition::new(0.0001, "T", None), - Self::Oersted => Definition::new(250.0, "/[pi].A/m", None), - Self::Gilbert => Definition::new(1.0, "Oe.cm", None), - Self::Stilb => Definition::new(1.0, "cd/cm2", None), - Self::Lambert => Definition::new(1.0, "cd/cm2/[pi]", None), - Self::Phot => Definition::new(0.0001, "lx", None), - Self::Curie => Definition::new(37000000000.0, "Bq", None), - Self::Roentgen => Definition::new(0.000258, "C/kg", None), - Self::RadiationAbsorbedDose => Definition::new(100.0, "erg/g", None), - Self::RadiationEquivalentMan => Definition::new(1.0, "RAD", None), - Self::InchInternational => Definition::new(2.54, "cm", None), - Self::FootInternational => Definition::new(12.0, "[in_i]", None), - Self::YardInternational => Definition::new(3.0, "[ft_i]", None), - Self::MileInternational => Definition::new(5280.0, "[ft_i]", None), - Self::FathomInternational => Definition::new(6.0, "[ft_i]", None), - Self::NauticalMileInternational => Definition::new(1852.0, "m", None), - Self::KnotInternational => Definition::new(1.0, "[nmi_i]/h", None), - Self::SquareInchInternational => Definition::new(1.0, "[in_i]2", None), - Self::SquareFootInternational => Definition::new(1.0, "[ft_i]2", None), - Self::SquareYardInternational => Definition::new(1.0, "[yd_i]2", None), - Self::CubicInchInternational => Definition::new(1.0, "[in_i]3", None), - Self::CubicFootInternational => Definition::new(1.0, "[ft_i]3", None), - Self::CubicYardInternational => Definition::new(1.0, "[yd_i]3", None), - Self::BoardFootInternational => Definition::new(144.0, "[in_i]3", None), - Self::CordInternational => Definition::new(128.0, "[ft_i]3", None), - Self::MilInternational => Definition::new(0.001, "[in_i]", None), - Self::CircularMilInternational => Definition::new(1.0, "[pi]/4.[mil_i]2", None), - Self::HandInternational => Definition::new(4.0, "[in_i]", None), - Self::FootUS => Definition::new(1200.0, "m/3937", None), - Self::YardUS => Definition::new(3.0, "[ft_us]", None), - Self::InchUS => Definition::new(1.0, "[ft_us]/12", None), - Self::RodUS => Definition::new(16.5, "[ft_us]", None), - Self::GuntersChainUS => Definition::new(4.0, "[rd_us]", None), - Self::LinkForGuntersChainUS => Definition::new(1.0, "[ch_us]/100", None), - Self::RamdensChainUS => Definition::new(100.0, "[ft_us]", None), - Self::LinkForRamdensChainUS => Definition::new(1.0, "[rch_us]/100", None), - Self::FathomUS => Definition::new(6.0, "[ft_us]", None), - Self::FurlongUS => Definition::new(40.0, "[rd_us]", None), - Self::MileUS => Definition::new(8.0, "[fur_us]", None), - Self::AcreUS => Definition::new(160.0, "[rd_us]2", None), - Self::SquareRodUS => Definition::new(1.0, "[rd_us]2", None), - Self::SquareMileUS => Definition::new(1.0, "[mi_us]2", None), - Self::Section => Definition::new(1.0, "[mi_us]2", None), - Self::Township => Definition::new(36.0, "[sct]", None), - Self::MilUS => Definition::new(0.001, "[in_us]", None), - Self::InchBritish => Definition::new(2.539998, "cm", None), - Self::FootBritish => Definition::new(12.0, "[in_br]", None), - Self::RodBritish => Definition::new(16.5, "[ft_br]", None), - Self::GuntersChainBritish => Definition::new(4.0, "[rd_br]", None), - Self::LinkForGuntersChainBritish => Definition::new(1.0, "[ch_br]/100", None), - Self::FathomBritish => Definition::new(6.0, "[ft_br]", None), - Self::PaceBritish => Definition::new(2.5, "[ft_br]", None), - Self::YardBritish => Definition::new(3.0, "[ft_br]", None), - Self::MileBritish => Definition::new(5280.0, "[ft_br]", None), - Self::NauticalMileBritish => Definition::new(6080.0, "[ft_br]", None), - Self::KnotBritish => Definition::new(1.0, "[nmi_br]/h", None), - Self::AcreBritish => Definition::new(4840.0, "[yd_br]2", None), - Self::QueenAnnesWineGallonUS => Definition::new(231.0, "[in_i]3", None), - Self::BarrelUS => Definition::new(42.0, "[gal_us]", None), - Self::QuartUS => Definition::new(1.0, "[gal_us]/4", None), - Self::PintUS => Definition::new(1.0, "[qt_us]/2", None), - Self::GillUS => Definition::new(1.0, "[pt_us]/4", None), - Self::FluidOunceUS => Definition::new(1.0, "[gil_us]/4", None), - Self::FluidDramUS => Definition::new(1.0, "[foz_us]/8", None), - Self::MinimUS => Definition::new(1.0, "[fdr_us]/60", None), - Self::CordUS => Definition::new(128.0, "[ft_i]3", None), - Self::BushelUS => Definition::new(2150.42, "[in_i]3", None), - Self::HistoricalWinchesterGallon => Definition::new(1.0, "[bu_us]/8", None), - Self::PeckUS => Definition::new(1.0, "[bu_us]/4", None), - Self::DryQuartUS => Definition::new(1.0, "[pk_us]/8", None), - Self::DryPintUS => Definition::new(1.0, "[dqt_us]/2", None), - Self::TablespoonUS => Definition::new(1.0, "[foz_us]/2", None), - Self::TeaspoonUS => Definition::new(1.0, "[tbs_us]/3", None), - Self::CupUS => Definition::new(16.0, "[tbs_us]", None), - Self::MetricFluidOunce => Definition::new(30.0, "mL", None), - Self::MetricCup => Definition::new(240.0, "mL", None), - Self::MetricTeaspoon => Definition::new(5.0, "mL", None), - Self::MetricTablespoon => Definition::new(15.0, "mL", None), - Self::GallonBritish => Definition::new(4.54609, "l", None), - Self::PeckBritish => Definition::new(2.0, "[gal_br]", None), - Self::BushelBritish => Definition::new(4.0, "[pk_br]", None), - Self::QuartBritish => Definition::new(1.0, "[gal_br]/4", None), - Self::PintBritish => Definition::new(1.0, "[qt_br]/2", None), - Self::GillBritish => Definition::new(1.0, "[pt_br]/4", None), - Self::FluidOunceBritish => Definition::new(1.0, "[gil_br]/5", None), - Self::FluidDramBritish => Definition::new(1.0, "[foz_br]/8", None), - Self::MinimBritish => Definition::new(1.0, "[fdr_br]/60", None), - Self::Grain => Definition::new(64.79891, "mg", None), - Self::PoundAvoirdupois => Definition::new(7000.0, "[gr]", None), - Self::OunceAvoirdupois => Definition::new(1.0, "[lb_av]/16", None), - Self::DramAvoirdupois => Definition::new(1.0, "[oz_av]/16", None), - Self::ShortHundredweightAvoirdupois => Definition::new(100.0, "[lb_av]", None), - Self::LongHunderdweightAvoirdupois => Definition::new(112.0, "[lb_av]", None), - Self::ShortTonAvoirdupois => Definition::new(20.0, "[scwt_av]", None), - Self::LongTonAvoirdupois => Definition::new(20.0, "[lcwt_av]", None), - Self::StoneAvoirdupois => Definition::new(14.0, "[lb_av]", None), - Self::PennyweightTroy => Definition::new(24.0, "[gr]", None), - Self::OunceTroy => Definition::new(20.0, "[pwt_tr]", None), - Self::PoundTroy => Definition::new(12.0, "[oz_tr]", None), - Self::ScrupleApothecaries => Definition::new(20.0, "[gr]", None), - Self::DramApothecaries => Definition::new(3.0, "[sc_ap]", None), - Self::OunceApothecaries => Definition::new(8.0, "[dr_ap]", None), - Self::PoundApothecaries => Definition::new(12.0, "[oz_ap]", None), - Self::MetricOunce => Definition::new(28.0, "g", None), - Self::Line => Definition::new(1.0, "[in_i]/12", None), - Self::Point => Definition::new(1.0, "[lne]/6", None), - Self::Pica => Definition::new(12.0, "[pnt]", None), - Self::PrintersPoint => Definition::new(0.013837, "[in_i]", None), - Self::PrintersPica => Definition::new(12.0, "[pnt_pr]", None), - Self::Pied => Definition::new(32.48, "cm", None), - Self::Pouce => Definition::new(1.0, "[pied]/12", None), - Self::Ligne => Definition::new(1.0, "[pouce]/12", None), - Self::Didot => Definition::new(1.0, "[ligne]/6", None), - Self::Cicero => Definition::new(12.0, "[didot]", None), + Self::StandardAccelerationOfFreeFall => Definition::new(9.80665f64, "m/s2", None), + Self::StandardAtmosphere => Definition::new(101325f64, "Pa", None), + Self::LightYear => Definition::new(1f64, "[c].a_j", None), + Self::GramForce => Definition::new(1f64, "g.[g]", None), + Self::PoundForceAvoirdupois => Definition::new(1f64, "[lb_av].[g]", None), + Self::Kayser => Definition::new(1f64, "cm-1", None), + Self::Gal => Definition::new(1f64, "cm/s2", None), + Self::Dyne => Definition::new(1f64, "g.cm/s2", None), + Self::Erg => Definition::new(1f64, "dyn.cm", None), + Self::Poise => Definition::new(1f64, "dyn.s/cm2", None), + Self::Biot => Definition::new(10f64, "A", None), + Self::Stokes => Definition::new(1f64, "cm2/s", None), + Self::Maxwell => Definition::new(0.00000001f64, "Wb", None), + Self::Gauss => Definition::new(0.0001f64, "T", None), + Self::Oersted => Definition::new(250f64, "/[pi].A/m", None), + Self::Gilbert => Definition::new(1f64, "Oe.cm", None), + Self::Stilb => Definition::new(1f64, "cd/cm2", None), + Self::Lambert => Definition::new(1f64, "cd/cm2/[pi]", None), + Self::Phot => Definition::new(0.0001f64, "lx", None), + Self::Curie => Definition::new(37000000000f64, "Bq", None), + Self::Roentgen => Definition::new(0.000258f64, "C/kg", None), + Self::RadiationAbsorbedDose => Definition::new(100f64, "erg/g", None), + Self::RadiationEquivalentMan => Definition::new(1f64, "RAD", None), + Self::InchInternational => Definition::new(2.54f64, "cm", None), + Self::FootInternational => Definition::new(12f64, "[in_i]", None), + Self::YardInternational => Definition::new(3f64, "[ft_i]", None), + Self::MileInternational => Definition::new(5280f64, "[ft_i]", None), + Self::FathomInternational => Definition::new(6f64, "[ft_i]", None), + Self::NauticalMileInternational => Definition::new(1852f64, "m", None), + Self::KnotInternational => Definition::new(1f64, "[nmi_i]/h", None), + Self::SquareInchInternational => Definition::new(1f64, "[in_i]2", None), + Self::SquareFootInternational => Definition::new(1f64, "[ft_i]2", None), + Self::SquareYardInternational => Definition::new(1f64, "[yd_i]2", None), + Self::CubicInchInternational => Definition::new(1f64, "[in_i]3", None), + Self::CubicFootInternational => Definition::new(1f64, "[ft_i]3", None), + Self::CubicYardInternational => Definition::new(1f64, "[yd_i]3", None), + Self::BoardFootInternational => Definition::new(144f64, "[in_i]3", None), + Self::CordInternational => Definition::new(128f64, "[ft_i]3", None), + Self::MilInternational => Definition::new(0.001f64, "[in_i]", None), + Self::CircularMilInternational => Definition::new(1f64, "[pi]/4.[mil_i]2", None), + Self::HandInternational => Definition::new(4f64, "[in_i]", None), + Self::FootUS => Definition::new(1200f64, "m/3937", None), + Self::YardUS => Definition::new(3f64, "[ft_us]", None), + Self::InchUS => Definition::new(1f64, "[ft_us]/12", None), + Self::RodUS => Definition::new(16.5f64, "[ft_us]", None), + Self::GuntersChainUS => Definition::new(4f64, "[rd_us]", None), + Self::LinkForGuntersChainUS => Definition::new(1f64, "[ch_us]/100", None), + Self::RamdensChainUS => Definition::new(100f64, "[ft_us]", None), + Self::LinkForRamdensChainUS => Definition::new(1f64, "[rch_us]/100", None), + Self::FathomUS => Definition::new(6f64, "[ft_us]", None), + Self::FurlongUS => Definition::new(40f64, "[rd_us]", None), + Self::MileUS => Definition::new(8f64, "[fur_us]", None), + Self::AcreUS => Definition::new(160f64, "[rd_us]2", None), + Self::SquareRodUS => Definition::new(1f64, "[rd_us]2", None), + Self::SquareMileUS => Definition::new(1f64, "[mi_us]2", None), + Self::Section => Definition::new(1f64, "[mi_us]2", None), + Self::Township => Definition::new(36f64, "[sct]", None), + Self::MilUS => Definition::new(0.001f64, "[in_us]", None), + Self::InchBritish => Definition::new(2.539998f64, "cm", None), + Self::FootBritish => Definition::new(12f64, "[in_br]", None), + Self::RodBritish => Definition::new(16.5f64, "[ft_br]", None), + Self::GuntersChainBritish => Definition::new(4f64, "[rd_br]", None), + Self::LinkForGuntersChainBritish => Definition::new(1f64, "[ch_br]/100", None), + Self::FathomBritish => Definition::new(6f64, "[ft_br]", None), + Self::PaceBritish => Definition::new(2.5f64, "[ft_br]", None), + Self::YardBritish => Definition::new(3f64, "[ft_br]", None), + Self::MileBritish => Definition::new(5280f64, "[ft_br]", None), + Self::NauticalMileBritish => Definition::new(6080f64, "[ft_br]", None), + Self::KnotBritish => Definition::new(1f64, "[nmi_br]/h", None), + Self::AcreBritish => Definition::new(4840f64, "[yd_br]2", None), + Self::QueenAnnesWineGallonUS => Definition::new(231f64, "[in_i]3", None), + Self::BarrelUS => Definition::new(42f64, "[gal_us]", None), + Self::QuartUS => Definition::new(1f64, "[gal_us]/4", None), + Self::PintUS => Definition::new(1f64, "[qt_us]/2", None), + Self::GillUS => Definition::new(1f64, "[pt_us]/4", None), + Self::FluidOunceUS => Definition::new(1f64, "[gil_us]/4", None), + Self::FluidDramUS => Definition::new(1f64, "[foz_us]/8", None), + Self::MinimUS => Definition::new(1f64, "[fdr_us]/60", None), + Self::CordUS => Definition::new(128f64, "[ft_i]3", None), + Self::BushelUS => Definition::new(2150.42f64, "[in_i]3", None), + Self::HistoricalWinchesterGallon => Definition::new(1f64, "[bu_us]/8", None), + Self::PeckUS => Definition::new(1f64, "[bu_us]/4", None), + Self::DryQuartUS => Definition::new(1f64, "[pk_us]/8", None), + Self::DryPintUS => Definition::new(1f64, "[dqt_us]/2", None), + Self::TablespoonUS => Definition::new(1f64, "[foz_us]/2", None), + Self::TeaspoonUS => Definition::new(1f64, "[tbs_us]/3", None), + Self::CupUS => Definition::new(16f64, "[tbs_us]", None), + Self::MetricFluidOunce => Definition::new(30f64, "mL", None), + Self::MetricCup => Definition::new(240f64, "mL", None), + Self::MetricTeaspoon => Definition::new(5f64, "mL", None), + Self::MetricTablespoon => Definition::new(15f64, "mL", None), + Self::GallonBritish => Definition::new(4.54609f64, "l", None), + Self::PeckBritish => Definition::new(2f64, "[gal_br]", None), + Self::BushelBritish => Definition::new(4f64, "[pk_br]", None), + Self::QuartBritish => Definition::new(1f64, "[gal_br]/4", None), + Self::PintBritish => Definition::new(1f64, "[qt_br]/2", None), + Self::GillBritish => Definition::new(1f64, "[pt_br]/4", None), + Self::FluidOunceBritish => Definition::new(1f64, "[gil_br]/5", None), + Self::FluidDramBritish => Definition::new(1f64, "[foz_br]/8", None), + Self::MinimBritish => Definition::new(1f64, "[fdr_br]/60", None), + Self::Grain => Definition::new(64.79891f64, "mg", None), + Self::PoundAvoirdupois => Definition::new(7000f64, "[gr]", None), + Self::OunceAvoirdupois => Definition::new(1f64, "[lb_av]/16", None), + Self::DramAvoirdupois => Definition::new(1f64, "[oz_av]/16", None), + Self::ShortHundredweightAvoirdupois => Definition::new(100f64, "[lb_av]", None), + Self::LongHunderdweightAvoirdupois => Definition::new(112f64, "[lb_av]", None), + Self::ShortTonAvoirdupois => Definition::new(20f64, "[scwt_av]", None), + Self::LongTonAvoirdupois => Definition::new(20f64, "[lcwt_av]", None), + Self::StoneAvoirdupois => Definition::new(14f64, "[lb_av]", None), + Self::PennyweightTroy => Definition::new(24f64, "[gr]", None), + Self::OunceTroy => Definition::new(20f64, "[pwt_tr]", None), + Self::PoundTroy => Definition::new(12f64, "[oz_tr]", None), + Self::ScrupleApothecaries => Definition::new(20f64, "[gr]", None), + Self::DramApothecaries => Definition::new(3f64, "[sc_ap]", None), + Self::OunceApothecaries => Definition::new(8f64, "[dr_ap]", None), + Self::PoundApothecaries => Definition::new(12f64, "[oz_ap]", None), + Self::MetricOunce => Definition::new(28f64, "g", None), + Self::Line => Definition::new(1f64, "[in_i]/12", None), + Self::Point => Definition::new(1f64, "[lne]/6", None), + Self::Pica => Definition::new(12f64, "[pnt]", None), + Self::PrintersPoint => Definition::new(0.013837f64, "[in_i]", None), + Self::PrintersPica => Definition::new(12f64, "[pnt_pr]", None), + Self::Pied => Definition::new(32.48f64, "cm", None), + Self::Pouce => Definition::new(1f64, "[pied]/12", None), + Self::Ligne => Definition::new(1f64, "[pouce]/12", None), + Self::Didot => Definition::new(1f64, "[ligne]/6", None), + Self::Cicero => Definition::new(12f64, "[didot]", None), Self::DegreeFahrenheit => Definition::new( - 5.0, + 5f64, "K/9", Some(FunctionSet { convert_from: |value: f64| 9.0 * value / 5.0 - 459.67, convert_to: |value: f64| 5.0 / 9.0 * (value + 459.67), }), ), - Self::DegreeRankine => Definition::new(5.0, "K/9", None), + Self::DegreeRankine => Definition::new(5f64, "K/9", None), Self::DegreeReaumur => Definition::new( - 5.0, + 5f64, "K/4", Some(FunctionSet { convert_from: |value: f64| (value - 273.15) * 0.8, convert_to: |value: f64| (value / 0.8) + 273.15, }), ), - Self::CalorieAt15C => Definition::new(4.1858, "J", None), - Self::CalorieAt20C => Definition::new(4.1819, "J", None), - Self::MeanCalorie => Definition::new(4.19002, "J", None), - Self::InternationalTableCalorie => Definition::new(4.1868, "J", None), - Self::ThermochemicalCalorie => Definition::new(4.184, "J", None), - Self::Calorie => Definition::new(1.0, "cal_th", None), - Self::NutritionLabelCalories => Definition::new(1.0, "kcal_th", None), - Self::BritishThermalUnitAt39F => Definition::new(1.05967, "kJ", None), - Self::BritishThermalUnitAt59F => Definition::new(1.0548, "kJ", None), - Self::BritishThermalUnitAt60F => Definition::new(1.05468, "kJ", None), - Self::MeanBritishThermalUnit => Definition::new(1.05587, "kJ", None), + Self::CalorieAt15C => Definition::new(4.1858f64, "J", None), + Self::CalorieAt20C => Definition::new(4.1819f64, "J", None), + Self::MeanCalorie => Definition::new(4.19002f64, "J", None), + Self::InternationalTableCalorie => Definition::new(4.1868f64, "J", None), + Self::ThermochemicalCalorie => Definition::new(4.184f64, "J", None), + Self::Calorie => Definition::new(1f64, "cal_th", None), + Self::NutritionLabelCalories => Definition::new(1f64, "kcal_th", None), + Self::BritishThermalUnitAt39F => Definition::new(1.05967f64, "kJ", None), + Self::BritishThermalUnitAt59F => Definition::new(1.0548f64, "kJ", None), + Self::BritishThermalUnitAt60F => Definition::new(1.05468f64, "kJ", None), + Self::MeanBritishThermalUnit => Definition::new(1.05587f64, "kJ", None), Self::InternationalTableBritishThermalUnit => { - Definition::new(1.05505585262, "kJ", None) + Definition::new(1.05505585262f64, "kJ", None) } - Self::ThermochemicalBritishThermalUnit => Definition::new(1.05435, "kJ", None), - Self::BritishThermalUnit => Definition::new(1.0, "[Btu_th]", None), - Self::Horsepower => Definition::new(550.0, "[ft_i].[lbf_av]/s", None), - Self::Tex => Definition::new(1.0, "g/km", None), - Self::Denier => Definition::new(1.0, "g/9/km", None), - Self::MeterOfWaterColumn => Definition::new(9.80665, "kPa", None), - Self::MeterOfMercuryColumn => Definition::new(133.322, "kPa", None), - Self::InchOfWaterColumn => Definition::new(1.0, "m[H2O].[in_i]/m", None), - Self::InchOfMercuryColumn => Definition::new(1.0, "m[Hg].[in_i]/m", None), - Self::PeripheralVascularResistanceUnit => Definition::new(1.0, "mm[Hg].s/ml", None), - Self::WoodUnit => Definition::new(1.0, "mm[Hg].min/L", None), - Self::Diopter => Definition::new(1.0, "/m", None), + Self::ThermochemicalBritishThermalUnit => Definition::new(1.05435f64, "kJ", None), + Self::BritishThermalUnit => Definition::new(1f64, "[Btu_th]", None), + Self::Horsepower => Definition::new(550f64, "[ft_i].[lbf_av]/s", None), + Self::Tex => Definition::new(1f64, "g/km", None), + Self::Denier => Definition::new(1f64, "g/9/km", None), + Self::MeterOfWaterColumn => Definition::new(9.80665f64, "kPa", None), + Self::MeterOfMercuryColumn => Definition::new(133.322f64, "kPa", None), + Self::InchOfWaterColumn => Definition::new(1f64, "m[H2O].[in_i]/m", None), + Self::InchOfMercuryColumn => Definition::new(1f64, "m[Hg].[in_i]/m", None), + Self::PeripheralVascularResistanceUnit => Definition::new(1f64, "mm[Hg].s/ml", None), + Self::WoodUnit => Definition::new(1f64, "mm[Hg].min/L", None), + Self::Diopter => Definition::new(1f64, "/m", None), Self::PrismDiopter => Definition::new( - 1.0, + 1f64, "rad", Some(FunctionSet { convert_from: |value: f64| (value / 100.0).atan(), @@ -595,20 +598,20 @@ impl Atom { }), ), Self::PercentOfSlope => Definition::new( - 1.0, + 1f64, "deg", Some(FunctionSet { convert_from: |value: f64| (value / 100.0).atan(), convert_to: |value: f64| value.tan() * 100.0, }), ), - Self::MeshInternational => Definition::new(1.0, "/[in_i]", None), - Self::Charriere => Definition::new(1.0, "mm/3", None), - Self::Drop => Definition::new(1.0, "ml/20", None), + Self::MeshInternational => Definition::new(1f64, "/[in_i]", None), + Self::Charriere => Definition::new(1f64, "mm/3", None), + Self::Drop => Definition::new(1f64, "ml/20", None), Self::HounsfieldUnit => Ok(Definition::default()), - Self::MetabolicEquivalent => Definition::new(3.5, "mL/min/kg", None), + Self::MetabolicEquivalent => Definition::new(3.5f64, "mL/min/kg", None), Self::HomeopathicPotencyOfDecimalSeriesRetired => Definition::new( - 1.0, + 1f64, "1", Some(FunctionSet { convert_from: |value: f64| -value.log10(), @@ -616,7 +619,7 @@ impl Atom { }), ), Self::HomeopathicPotencyOfCentesimalSeriesRetired => Definition::new( - 1.0, + 1f64, "1", Some(FunctionSet { convert_from: |value: f64| -value.ln() / 100_f64.ln(), @@ -624,7 +627,7 @@ impl Atom { }), ), Self::HomeopathicPotencyOfMillesimalSeriesRetired => Definition::new( - 1.0, + 1f64, "1", Some(FunctionSet { convert_from: |value: f64| -value.ln() / 1_000_f64.ln(), @@ -632,7 +635,7 @@ impl Atom { }), ), Self::HomeopathicPotencyOfQuintamillesimalSeriesRetired => Definition::new( - 1.0, + 1f64, "1", Some(FunctionSet { convert_from: |value: f64| -value.ln() / 50_000_f64.ln(), @@ -651,24 +654,24 @@ impl Atom { Self::HomeopathicPotencyOfQuintamillesimalKorsakovianSeries => { Ok(Definition::default()) } - Self::Equivalents => Definition::new(1.0, "mol", None), - Self::Osmole => Definition::new(1.0, "mol", None), + Self::Equivalents => Definition::new(1f64, "mol", None), + Self::Osmole => Definition::new(1f64, "mol", None), Self::PH => Definition::new( - 1.0, + 1f64, "mol/l", Some(FunctionSet { convert_from: |value: f64| 10.0_f64.powf(-value), convert_to: |value: f64| -value.log10(), }), ), - Self::GramPercent => Definition::new(1.0, "g/dl", None), - Self::SvedbergUnit => Definition::new(1.0, "10*-13.s", None), + Self::GramPercent => Definition::new(1f64, "g/dl", None), + Self::SvedbergUnit => Definition::new(1f64, "10*-13.s", None), Self::HighPowerField => Ok(Definition::default()), - Self::LowPowerField => Definition::new(100.0, "1", None), - Self::Katal => Definition::new(1.0, "mol/s", None), - Self::Unit => Definition::new(1.0, "umol/min", None), + Self::LowPowerField => Definition::new(100f64, "1", None), + Self::Katal => Definition::new(1f64, "mol/s", None), + Self::Unit => Definition::new(1f64, "umol/min", None), Self::InternationalUnit => Ok(Definition::default()), - Self::InternationalUnitSecondary => Definition::new(1.0, "[iU]", None), + Self::InternationalUnitSecondary => Definition::new(1f64, "[iU]", None), Self::ArbitraryUnit => Ok(Definition::default()), Self::UnitedStatesPharmacopeiaUnit => Ok(Definition::default()), Self::GplUnit => Ok(Definition::default()), @@ -701,7 +704,7 @@ impl Atom { Self::ElisaUnit => Ok(Definition::default()), Self::EhrlichUnit => Ok(Definition::default()), Self::Neper => Definition::new( - 1.0, + 1f64, "1", Some(FunctionSet { convert_from: f64::ln, @@ -709,7 +712,7 @@ impl Atom { }), ), Self::Bel => Definition::new( - 1.0, + 1f64, "1", Some(FunctionSet { convert_from: f64::log10, @@ -717,7 +720,7 @@ impl Atom { }), ), Self::BelSoundPressure => Definition::new( - 2.0, + 2f64, "10*-5.Pa", Some(FunctionSet { convert_from: |value: f64| 2.0 * value.log10(), @@ -725,7 +728,7 @@ impl Atom { }), ), Self::BelVolt => Definition::new( - 1.0, + 1f64, "V", Some(FunctionSet { convert_from: |value: f64| 2.0 * value.log10(), @@ -733,7 +736,7 @@ impl Atom { }), ), Self::BelMillivolt => Definition::new( - 1.0, + 1f64, "mV", Some(FunctionSet { convert_from: |value: f64| 2.0 * value.log10(), @@ -741,7 +744,7 @@ impl Atom { }), ), Self::BelMicrovolt => Definition::new( - 1.0, + 1f64, "uV", Some(FunctionSet { convert_from: |value: f64| 2.0 * value.log10(), @@ -749,7 +752,7 @@ impl Atom { }), ), Self::Bel10Nanovolt => Definition::new( - 10.0, + 10f64, "nV", Some(FunctionSet { convert_from: |value: f64| 2.0 * value.log10(), @@ -757,7 +760,7 @@ impl Atom { }), ), Self::BelWatt => Definition::new( - 1.0, + 1f64, "W", Some(FunctionSet { convert_from: f64::log10, @@ -765,26 +768,26 @@ impl Atom { }), ), Self::BelKilowatt => Definition::new( - 1.0, + 1f64, "kW", Some(FunctionSet { convert_from: f64::log10, convert_to: |value: f64| 10_f64.powf(value), }), ), - Self::Stere => Definition::new(1.0, "m3", None), - Self::Angstrom => Definition::new(0.1, "nm", None), - Self::Barn => Definition::new(100.0, "fm2", None), - Self::TechnicalAtmosphere => Definition::new(1.0, "kgf/cm2", None), - Self::Mho => Definition::new(1.0, "S", None), - Self::PoundPerSqareInch => Definition::new(1.0, "[lbf_av]/[in_i]2", None), - Self::Circle => Definition::new(2.0, "[pi].rad", None), - Self::Spere => Definition::new(4.0, "[pi].sr", None), - Self::MetricCarat => Definition::new(0.2, "g", None), - Self::CaratOfGoldAlloys => Definition::new(1.0, "/24", None), - Self::Smoot => Definition::new(67.0, "[in_i]", None), + Self::Stere => Definition::new(1f64, "m3", None), + Self::Angstrom => Definition::new(0.1f64, "nm", None), + Self::Barn => Definition::new(100f64, "fm2", None), + Self::TechnicalAtmosphere => Definition::new(1f64, "kgf/cm2", None), + Self::Mho => Definition::new(1f64, "S", None), + Self::PoundPerSqareInch => Definition::new(1f64, "[lbf_av]/[in_i]2", None), + Self::Circle => Definition::new(2f64, "[pi].rad", None), + Self::Spere => Definition::new(4f64, "[pi].sr", None), + Self::MetricCarat => Definition::new(0.2f64, "g", None), + Self::CaratOfGoldAlloys => Definition::new(1f64, "/24", None), + Self::Smoot => Definition::new(67f64, "[in_i]", None), Self::MeterPerSquareSecondsPerSquareRootOfHertz => Definition::new( - 1.0, + 1f64, "m2/s4/Hz", Some(FunctionSet { convert_from: f64::sqrt, @@ -792,7 +795,7 @@ impl Atom { }), ), Self::BitLogarithmusDualis => Definition::new( - 1.0, + 1f64, "1", Some(FunctionSet { convert_from: f64::log2, @@ -800,13 +803,11 @@ impl Atom { }), ), Self::Bit => Ok(Definition::default()), - Self::Byte => Definition::new(8.0, "bit", None), - Self::Baud => Definition::new(1.0, "/s", None), + Self::Byte => Definition::new(8f64, "bit", None), + Self::Baud => Definition::new(1f64, "/s", None), }; - result.expect("BUG! Bad Atom -> Definition mapping!") } - #[must_use] pub const fn property(self) -> Property { match self { @@ -1041,18 +1042,42 @@ impl Atom { Self::Drop => Property::Volume, Self::HounsfieldUnit => Property::XRayAttenuation, Self::MetabolicEquivalent => Property::MetabolicCostOfPhysicalActivity, - Self::HomeopathicPotencyOfDecimalSeriesRetired => Property::HomeopathicPotencyRetired, - Self::HomeopathicPotencyOfCentesimalSeriesRetired => Property::HomeopathicPotencyRetired, - Self::HomeopathicPotencyOfMillesimalSeriesRetired => Property::HomeopathicPotencyRetired, - Self::HomeopathicPotencyOfQuintamillesimalSeriesRetired => Property::HomeopathicPotencyRetired, - Self::HomeopathicPotencyOfDecimalHahnemannianSeries => Property::HomeopathicPotencyHahnemann, - Self::HomeopathicPotencyOfCentesimalHahnemannianSeries => Property::HomeopathicPotencyHahnemann, - Self::HomeopathicPotencyOfMillesimalHahnemannianSeries => Property::HomeopathicPotencyHahnemann, - Self::HomeopathicPotencyOfQuintamillesimalHahnemannianSeries => Property::HomeopathicPotencyHahnemann, - Self::HomeopathicPotencyOfDecimalKorsakovianSeries => Property::HomeopathicPotencyKorsakov, - Self::HomeopathicPotencyOfCentesimalKorsakovianSeries => Property::HomeopathicPotencyKorsakov, - Self::HomeopathicPotencyOfMillesimalKorsakovianSeries => Property::HomeopathicPotencyKorsakov, - Self::HomeopathicPotencyOfQuintamillesimalKorsakovianSeries => Property::HomeopathicPotencyKorsakov, + Self::HomeopathicPotencyOfDecimalSeriesRetired => { + Property::HomeopathicPotencyRetired + } + Self::HomeopathicPotencyOfCentesimalSeriesRetired => { + Property::HomeopathicPotencyRetired + } + Self::HomeopathicPotencyOfMillesimalSeriesRetired => { + Property::HomeopathicPotencyRetired + } + Self::HomeopathicPotencyOfQuintamillesimalSeriesRetired => { + Property::HomeopathicPotencyRetired + } + Self::HomeopathicPotencyOfDecimalHahnemannianSeries => { + Property::HomeopathicPotencyHahnemann + } + Self::HomeopathicPotencyOfCentesimalHahnemannianSeries => { + Property::HomeopathicPotencyHahnemann + } + Self::HomeopathicPotencyOfMillesimalHahnemannianSeries => { + Property::HomeopathicPotencyHahnemann + } + Self::HomeopathicPotencyOfQuintamillesimalHahnemannianSeries => { + Property::HomeopathicPotencyHahnemann + } + Self::HomeopathicPotencyOfDecimalKorsakovianSeries => { + Property::HomeopathicPotencyKorsakov + } + Self::HomeopathicPotencyOfCentesimalKorsakovianSeries => { + Property::HomeopathicPotencyKorsakov + } + Self::HomeopathicPotencyOfMillesimalKorsakovianSeries => { + Property::HomeopathicPotencyKorsakov + } + Self::HomeopathicPotencyOfQuintamillesimalKorsakovianSeries => { + Property::HomeopathicPotencyKorsakov + } Self::Equivalents => Property::AmountOfSubstance, Self::Osmole => Property::AmountOfSubstanceDissolvedParticles, Self::PH => Property::Acidity, @@ -1070,7 +1095,9 @@ impl Atom { Self::MplUnit => Property::BiologicActivityOfAnticardiolipinIgM, Self::AplUnit => Property::BiologicActivityOfAnticardiolipinIgA, Self::BethesdaUnit => Property::BiologicActivityOfFactorViiiInhibitor, - Self::AntiFactorXaUnit => Property::BiologicActivityOfFactorXaInhibitorHeparin, + Self::AntiFactorXaUnit => { + Property::BiologicActivityOfFactorXaInhibitorHeparin + } Self::ToddUnit => Property::BiologicActivityAntistreptolysinO, Self::DyeUnit => Property::BiologicActivityOfAmylase, Self::SomogyiUnit => Property::BiologicActivityOfAmylase, @@ -1079,20 +1106,42 @@ impl Atom { Self::KunkelUnit => Property::ArbitraryBiologicActivity, Self::MacLaganUnit => Property::ArbitraryBiologicActivity, Self::TuberculinUnit => Property::BiologicActivityOfTuberculin, - Self::CellCultureInfectiousDose => Property::BiologicActivityInfectivityOfAnInfectiousAgentPreparation, - Self::TissueCultureInfectiousDose => Property::BiologicActivityInfectivityOfAnInfectiousAgentPreparation, - Self::EmbryoInfectiousDose => Property::BiologicActivityInfectivityOfAnInfectiousAgentPreparation, + Self::CellCultureInfectiousDose => { + Property::BiologicActivityInfectivityOfAnInfectiousAgentPreparation + } + Self::TissueCultureInfectiousDose => { + Property::BiologicActivityInfectivityOfAnInfectiousAgentPreparation + } + Self::EmbryoInfectiousDose => { + Property::BiologicActivityInfectivityOfAnInfectiousAgentPreparation + } Self::PlaqueFormingUnits => Property::AmountOfAnInfectiousAgent, Self::FocusFormingUnits => Property::AmountOfAnInfectiousAgent, Self::ColonyFormingUnits => Property::AmountOfAProliferatingOrganism, - Self::IndexOfReactivity => Property::AmountOfAnAllergenCallibratedThroughInVivoTestingUsingTheStallergenesMethod, - Self::BioequivalentAllergenUnit => Property::AmountOfAnAllergenCallibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters, - Self::AllergenUnit => Property::ProcedureDefinedAmountOfAnAllergenUsingSomeReferenceStandard, - Self::AllergenUnitForAmbrosiaArtemisiifolia => Property::ProcedureDefinedAmountOfTheMajorAllergenOfRagweed, - Self::ProteinNitrogenUnit => Property::ProcedureDefinedAmountOfAProteinSubstance, - Self::LimitOfFlocculation => Property::ProcedureDefinedAmountOfAnAntigenSubstance, - Self::DAntigenUnit => Property::ProcedureDefinedAmountOfAPoliomyelitisDAntigenSubstance, - Self::FibrinogenEquivalentUnit => Property::AmountOfFibrinogenBrokenDownIntoTheMeasuredDDimers, + Self::IndexOfReactivity => { + Property::AmountOfAnAllergenCallibratedThroughInVivoTestingUsingTheStallergenesMethod + } + Self::BioequivalentAllergenUnit => { + Property::AmountOfAnAllergenCallibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters + } + Self::AllergenUnit => { + Property::ProcedureDefinedAmountOfAnAllergenUsingSomeReferenceStandard + } + Self::AllergenUnitForAmbrosiaArtemisiifolia => { + Property::ProcedureDefinedAmountOfTheMajorAllergenOfRagweed + } + Self::ProteinNitrogenUnit => { + Property::ProcedureDefinedAmountOfAProteinSubstance + } + Self::LimitOfFlocculation => { + Property::ProcedureDefinedAmountOfAnAntigenSubstance + } + Self::DAntigenUnit => { + Property::ProcedureDefinedAmountOfAPoliomyelitisDAntigenSubstance + } + Self::FibrinogenEquivalentUnit => { + Property::AmountOfFibrinogenBrokenDownIntoTheMeasuredDDimers + } Self::ElisaUnit => Property::ArbitraryElisaUnit, Self::EhrlichUnit => Property::EhrlichUnit, Self::Neper => Property::Level, @@ -1115,7 +1164,9 @@ impl Atom { Self::MetricCarat => Property::Mass, Self::CaratOfGoldAlloys => Property::MassFraction, Self::Smoot => Property::Length, - Self::MeterPerSquareSecondsPerSquareRootOfHertz => Property::AmplitudeSpectralDensity, + Self::MeterPerSquareSecondsPerSquareRootOfHertz => { + Property::AmplitudeSpectralDensity + } Self::BitLogarithmusDualis => Property::AmountOfInformation, Self::Bit => Property::AmountOfInformation, Self::Byte => Property::AmountOfInformation, @@ -1123,7 +1174,6 @@ impl Atom { } } } - impl UcumSymbol for Atom { fn classification(&self) -> Classification { match *self { @@ -1441,7 +1491,6 @@ impl UcumSymbol for Atom { Self::Baud => Classification::Infotech, } } - fn names(&self) -> Vec<&'static str> { match *self { Self::Meter => vec!["meter"], @@ -1451,7 +1500,9 @@ impl UcumSymbol for Atom { Self::Kelvin => vec!["kelvin"], Self::Coulomb => vec!["coulomb"], Self::Candela => vec!["candela"], - Self::TheNumberTenForArbitraryPowersStar => vec!["the number ten for arbitrary powers"], + Self::TheNumberTenForArbitraryPowersStar => { + vec!["the number ten for arbitrary powers"] + } Self::TheNumberTenForArbitraryPowersCaret => { vec!["the number ten for arbitrary powers"] } @@ -1515,8 +1566,12 @@ impl UcumSymbol for Atom { Self::ElementaryCharge => vec!["elementary charge"], Self::ElectronMass => vec!["electron mass"], Self::ProtonMass => vec!["proton mass"], - Self::NewtonianConstantOfGravitation => vec!["Newtonian constant of gravitation"], - Self::StandardAccelerationOfFreeFall => vec!["standard acceleration of free fall"], + Self::NewtonianConstantOfGravitation => { + vec!["Newtonian constant of gravitation"] + } + Self::StandardAccelerationOfFreeFall => { + vec!["standard acceleration of free fall"] + } Self::StandardAtmosphere => vec!["standard atmosphere"], Self::LightYear => vec!["light-year"], Self::GramForce => vec!["gram-force"], @@ -1586,7 +1641,7 @@ impl UcumSymbol for Atom { Self::NauticalMileBritish => vec!["nautical mile"], Self::KnotBritish => vec!["knot"], Self::AcreBritish => vec!["acre"], - Self::QueenAnnesWineGallonUS => vec!["Queen Anne's wine gallon"], + Self::QueenAnnesWineGallonUS => vec!["Queen\u{a0}Anne's wine gallon"], Self::BarrelUS => vec!["barrel"], Self::QuartUS => vec!["quart"], Self::PintUS => vec!["pint"], @@ -1650,21 +1705,23 @@ impl UcumSymbol for Atom { Self::DegreeFahrenheit => vec!["degree Fahrenheit"], Self::DegreeRankine => vec!["degree Rankine"], Self::DegreeReaumur => vec!["degree Réaumur"], - Self::CalorieAt15C => vec!["calorie at 15 °C"], - Self::CalorieAt20C => vec!["calorie at 20 °C"], + Self::CalorieAt15C => vec!["calorie at 15\u{a0}°C"], + Self::CalorieAt20C => vec!["calorie at 20\u{a0}°C"], Self::MeanCalorie => vec!["mean calorie"], Self::InternationalTableCalorie => vec!["international table calorie"], Self::ThermochemicalCalorie => vec!["thermochemical calorie"], Self::Calorie => vec!["calorie"], Self::NutritionLabelCalories => vec!["nutrition label Calories"], - Self::BritishThermalUnitAt39F => vec!["British thermal unit at 39 °F"], - Self::BritishThermalUnitAt59F => vec!["British thermal unit at 59 °F"], - Self::BritishThermalUnitAt60F => vec!["British thermal unit at 60 °F"], + Self::BritishThermalUnitAt39F => vec!["British thermal unit at 39\u{a0}°F"], + Self::BritishThermalUnitAt59F => vec!["British thermal unit at 59\u{a0}°F"], + Self::BritishThermalUnitAt60F => vec!["British thermal unit at 60\u{a0}°F"], Self::MeanBritishThermalUnit => vec!["mean British thermal unit"], Self::InternationalTableBritishThermalUnit => { vec!["international table British thermal unit"] } - Self::ThermochemicalBritishThermalUnit => vec!["thermochemical British thermal unit"], + Self::ThermochemicalBritishThermalUnit => { + vec!["thermochemical British thermal unit"] + } Self::BritishThermalUnit => vec!["British thermal unit"], Self::Horsepower => vec!["horsepower"], Self::Tex => vec!["tex"], @@ -1673,7 +1730,9 @@ impl UcumSymbol for Atom { Self::MeterOfMercuryColumn => vec!["meter of mercury column"], Self::InchOfWaterColumn => vec!["inch of water column"], Self::InchOfMercuryColumn => vec!["inch of mercury column"], - Self::PeripheralVascularResistanceUnit => vec!["peripheral vascular resistance unit"], + Self::PeripheralVascularResistanceUnit => { + vec!["peripheral vascular resistance unit"] + } Self::WoodUnit => vec!["Wood unit"], Self::Diopter => vec!["diopter"], Self::PrismDiopter => vec!["prism diopter"], @@ -1746,7 +1805,9 @@ impl UcumSymbol for Atom { Self::MacLaganUnit => vec!["Mac Lagan unit"], Self::TuberculinUnit => vec!["tuberculin unit"], Self::CellCultureInfectiousDose => vec!["50% cell culture infectious dose"], - Self::TissueCultureInfectiousDose => vec!["50% tissue culture infectious dose"], + Self::TissueCultureInfectiousDose => { + vec!["50% tissue culture infectious dose"] + } Self::EmbryoInfectiousDose => vec!["50% embryo infectious dose"], Self::PlaqueFormingUnits => vec!["plaque forming units"], Self::FocusFormingUnits => vec!["focus forming units"], @@ -1792,7 +1853,6 @@ impl UcumSymbol for Atom { Self::Baud => vec!["baud"], } } - fn primary_code(&self) -> &'static str { match *self { Self::Meter => "m", @@ -2107,7 +2167,6 @@ impl UcumSymbol for Atom { Self::Baud => "Bd", } } - fn print_symbol(&self) -> Option<&'static str> { match *self { Self::Meter => Some("m"), @@ -2238,10 +2297,10 @@ impl UcumSymbol for Atom { Self::BritishThermalUnit => Some("btu"), Self::Tex => Some("tex"), Self::Denier => Some("den"), - Self::MeterOfWaterColumn => Some("m H2O"), - Self::MeterOfMercuryColumn => Some("m Hg"), - Self::InchOfWaterColumn => Some("in H2O"), - Self::InchOfMercuryColumn => Some("in Hg"), + Self::MeterOfWaterColumn => Some("m\u{a0}H2O"), + Self::MeterOfMercuryColumn => Some("m\u{a0}Hg"), + Self::InchOfWaterColumn => Some("in\u{a0}H2O"), + Self::InchOfMercuryColumn => Some("in\u{a0}Hg"), Self::PeripheralVascularResistanceUnit => Some("P.R.U."), Self::WoodUnit => Some("Wood U."), Self::Diopter => Some("dpt"), @@ -2314,7 +2373,6 @@ impl UcumSymbol for Atom { _ => None, } } - fn secondary_code(&self) -> Option<&'static str> { match *self { Self::Meter => Some("M"), @@ -2358,6 +2416,7 @@ impl UcumSymbol for Atom { Self::MinuteAngle => Some("'"), Self::SecondAngle => Some("''"), Self::Liter => Some("L"), + Self::LiterSecondary => None, Self::Are => Some("AR"), Self::Minute => Some("MIN"), Self::Hour => Some("HR"), @@ -2626,248 +2685,194 @@ impl UcumSymbol for Atom { Self::Bit => Some("BIT"), Self::Byte => Some("BY"), Self::Baud => Some("BD"), - Self::LiterSecondary => None, } } - fn definition_value(&self) -> f64 { self.definition().value() } - fn definition_unit(&self) -> Unit { Unit::new(self.definition().terms().clone()) } } - impl UcumUnit for Atom { fn scalar(&self) -> f64 { self.reduce_value(1.0) } - fn magnitude(&self) -> f64 { self.calculate_magnitude(self.scalar()) } - fn is_arbitrary(&self) -> bool { matches!( *self, - Self::HomeopathicPotencyOfDecimalHahnemannianSeries + Self::AllergenUnit + | Self::AllergenUnitForAmbrosiaArtemisiifolia + | Self::AntiFactorXaUnit + | Self::AplUnit + | Self::ArbitraryUnit + | Self::BethesdaUnit + | Self::BioequivalentAllergenUnit + | Self::BodanskyUnit + | Self::CellCultureInfectiousDose + | Self::ColonyFormingUnits + | Self::DAntigenUnit + | Self::DyeUnit + | Self::EhrlichUnit + | Self::ElisaUnit + | Self::EmbryoInfectiousDose + | Self::FibrinogenEquivalentUnit + | Self::FocusFormingUnits + | Self::GplUnit | Self::HomeopathicPotencyOfCentesimalHahnemannianSeries - | Self::HomeopathicPotencyOfMillesimalHahnemannianSeries - | Self::HomeopathicPotencyOfQuintamillesimalHahnemannianSeries - | Self::HomeopathicPotencyOfDecimalKorsakovianSeries | Self::HomeopathicPotencyOfCentesimalKorsakovianSeries + | Self::HomeopathicPotencyOfDecimalHahnemannianSeries + | Self::HomeopathicPotencyOfDecimalKorsakovianSeries + | Self::HomeopathicPotencyOfMillesimalHahnemannianSeries | Self::HomeopathicPotencyOfMillesimalKorsakovianSeries + | Self::HomeopathicPotencyOfQuintamillesimalHahnemannianSeries | Self::HomeopathicPotencyOfQuintamillesimalKorsakovianSeries + | Self::IndexOfReactivity | Self::InternationalUnit | Self::InternationalUnitSecondary - | Self::ArbitraryUnit - | Self::UnitedStatesPharmacopeiaUnit - | Self::GplUnit - | Self::MplUnit - | Self::AplUnit - | Self::BethesdaUnit - | Self::AntiFactorXaUnit - | Self::ToddUnit - | Self::DyeUnit - | Self::SomogyiUnit - | Self::BodanskyUnit | Self::KingArmstrongUnit | Self::KunkelUnit + | Self::LimitOfFlocculation | Self::MacLaganUnit - | Self::TuberculinUnit - | Self::CellCultureInfectiousDose - | Self::TissueCultureInfectiousDose - | Self::EmbryoInfectiousDose + | Self::MplUnit | Self::PlaqueFormingUnits - | Self::FocusFormingUnits - | Self::ColonyFormingUnits - | Self::IndexOfReactivity - | Self::BioequivalentAllergenUnit - | Self::AllergenUnit - | Self::AllergenUnitForAmbrosiaArtemisiifolia | Self::ProteinNitrogenUnit - | Self::LimitOfFlocculation - | Self::DAntigenUnit - | Self::FibrinogenEquivalentUnit - | Self::ElisaUnit - | Self::EhrlichUnit + | Self::SomogyiUnit + | Self::TissueCultureInfectiousDose + | Self::ToddUnit + | Self::TuberculinUnit + | Self::UnitedStatesPharmacopeiaUnit ) } - fn is_special(&self) -> bool { matches!( *self, - Self::DegreeCelsius + Self::Bel + | Self::Bel10Nanovolt + | Self::BelKilowatt + | Self::BelMicrovolt + | Self::BelMillivolt + | Self::BelSoundPressure + | Self::BelVolt + | Self::BelWatt + | Self::BitLogarithmusDualis + | Self::DegreeCelsius | Self::DegreeFahrenheit | Self::DegreeReaumur - | Self::PrismDiopter - | Self::PercentOfSlope - | Self::HomeopathicPotencyOfDecimalSeriesRetired | Self::HomeopathicPotencyOfCentesimalSeriesRetired + | Self::HomeopathicPotencyOfDecimalSeriesRetired | Self::HomeopathicPotencyOfMillesimalSeriesRetired | Self::HomeopathicPotencyOfQuintamillesimalSeriesRetired - | Self::PH - | Self::Neper - | Self::Bel - | Self::BelSoundPressure - | Self::BelVolt - | Self::BelMillivolt - | Self::BelMicrovolt - | Self::Bel10Nanovolt - | Self::BelWatt - | Self::BelKilowatt | Self::MeterPerSquareSecondsPerSquareRootOfHertz - | Self::BitLogarithmusDualis + | Self::Neper + | Self::PH + | Self::PercentOfSlope + | Self::PrismDiopter ) } - fn is_metric(&self) -> bool { matches!( *self, - Self::Meter - | Self::Second - | Self::Gram - | Self::Radian - | Self::Kelvin - | Self::Coulomb - | Self::Candela - | Self::Mole - | Self::Steradian - | Self::Hertz - | Self::Newton - | Self::Pascal - | Self::Joule - | Self::Watt - | Self::Ampere - | Self::Volt - | Self::Farad - | Self::Ohm - | Self::Siemens - | Self::Weber - | Self::DegreeCelsius - | Self::Tesla - | Self::Henry - | Self::Lumen - | Self::Lux - | Self::Becquerel - | Self::Gray - | Self::Sievert - | Self::Liter - | Self::LiterSecondary + Self::Ampere | Self::Are - | Self::Tonne | Self::Bar - | Self::UnifiedAtomicMassUnit - | Self::Electronvolt - | Self::Parsec - | Self::VelocityOfLight - | Self::PlanckConstant + | Self::Baud + | Self::Becquerel + | Self::Bel + | Self::Bel10Nanovolt + | Self::BelKilowatt + | Self::BelMicrovolt + | Self::BelMillivolt + | Self::BelSoundPressure + | Self::BelVolt + | Self::BelWatt + | Self::Biot + | Self::Bit | Self::BoltzmannConstant - | Self::PermittivityOfVacuum - | Self::PermeabilityOfVacuum - | Self::ElementaryCharge - | Self::ElectronMass - | Self::ProtonMass - | Self::NewtonianConstantOfGravitation - | Self::StandardAccelerationOfFreeFall - | Self::LightYear - | Self::GramForce - | Self::Kayser - | Self::Gal + | Self::Byte + | Self::Calorie + | Self::CalorieAt15C + | Self::CalorieAt20C + | Self::Candela + | Self::Coulomb + | Self::Curie + | Self::DegreeCelsius | Self::Dyne + | Self::ElectronMass + | Self::Electronvolt + | Self::ElementaryCharge + | Self::Equivalents | Self::Erg - | Self::Poise - | Self::Biot - | Self::Stokes - | Self::Maxwell + | Self::Farad + | Self::Gal | Self::Gauss - | Self::Oersted | Self::Gilbert - | Self::Stilb + | Self::Gram + | Self::GramForce + | Self::GramPercent + | Self::Gray + | Self::Henry + | Self::Hertz + | Self::InternationalTableCalorie + | Self::InternationalUnit + | Self::InternationalUnitSecondary + | Self::Joule + | Self::Katal + | Self::Kayser + | Self::Kelvin | Self::Lambert + | Self::LightYear + | Self::Liter + | Self::LiterSecondary + | Self::Lumen + | Self::Lux + | Self::Maxwell + | Self::MeanCalorie + | Self::Meter + | Self::MeterOfMercuryColumn + | Self::MeterOfWaterColumn + | Self::Mho + | Self::Mole + | Self::Neper + | Self::Newton + | Self::NewtonianConstantOfGravitation + | Self::Oersted + | Self::Ohm + | Self::Osmole + | Self::Parsec + | Self::Pascal + | Self::PermeabilityOfVacuum + | Self::PermittivityOfVacuum | Self::Phot - | Self::Curie - | Self::Roentgen + | Self::PlanckConstant + | Self::Poise + | Self::ProtonMass + | Self::Radian | Self::RadiationAbsorbedDose | Self::RadiationEquivalentMan - | Self::CalorieAt15C - | Self::CalorieAt20C - | Self::MeanCalorie - | Self::InternationalTableCalorie - | Self::ThermochemicalCalorie - | Self::Calorie + | Self::Roentgen + | Self::Second + | Self::Siemens + | Self::Sievert + | Self::StandardAccelerationOfFreeFall + | Self::Steradian + | Self::Stere + | Self::Stilb + | Self::Stokes + | Self::Tesla | Self::Tex - | Self::MeterOfWaterColumn - | Self::MeterOfMercuryColumn - | Self::Equivalents - | Self::Osmole - | Self::GramPercent - | Self::Katal + | Self::ThermochemicalCalorie + | Self::Tonne + | Self::UnifiedAtomicMassUnit | Self::Unit - | Self::InternationalUnit - | Self::InternationalUnitSecondary - | Self::Neper - | Self::Bel - | Self::BelSoundPressure - | Self::BelVolt - | Self::BelMillivolt - | Self::BelMicrovolt - | Self::Bel10Nanovolt - | Self::BelWatt - | Self::BelKilowatt - | Self::Stere - | Self::Mho - | Self::Bit - | Self::Byte - | Self::Baud + | Self::VelocityOfLight + | Self::Volt + | Self::Watt + | Self::Weber ) } } - -impl Reducible for Atom { - fn reduce_value(&self, value: f64) -> f64 { - self.definition().reduce_value(value) - } - - fn calculate_magnitude(&self, value: f64) -> f64 { - if self.is_special() { - self.definition().calculate_magnitude(value) - } else { - 1.0 - } - } -} - impl DefaultCompatibility for Atom {} - -impl Composable for Atom { - fn composition(&self) -> Composition { - match self { - Self::Candela => Composition::new(Dimension::LuminousIntensity, 1), - Self::Coulomb => Composition::new(Dimension::ElectricCharge, 1), - Self::Gram => Composition::new(Dimension::Mass, 1), - Self::Kelvin => Composition::new(Dimension::Temperature, 1), - Self::Meter => Composition::new(Dimension::Length, 1), - Self::Radian => Composition::new(Dimension::PlaneAngle, 1), - Self::Second => Composition::new(Dimension::Time, 1), - _ => self.definition().terms().composition(), - } - } -} - -impl PartialEq for Atom { - fn eq(&self, other: &Self) -> bool { - if !self.is_compatible_with(other) { - return false; - } - - self.scalar() == other.scalar() - } -} - -impl fmt::Display for Atom { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.primary_code()) - } -} diff --git a/api/src/parser/atom/composable.rs b/api/src/parser/atom/composable.rs new file mode 100644 index 00000000..d9c4047f --- /dev/null +++ b/api/src/parser/atom/composable.rs @@ -0,0 +1,16 @@ +use crate::{Atom, Composable, Composition, Dimension}; + +impl Composable for Atom { + fn composition(&self) -> Composition { + match self { + Self::Candela => Composition::new(Dimension::LuminousIntensity, 1), + Self::Coulomb => Composition::new(Dimension::ElectricCharge, 1), + Self::Gram => Composition::new(Dimension::Mass, 1), + Self::Kelvin => Composition::new(Dimension::Temperature, 1), + Self::Meter => Composition::new(Dimension::Length, 1), + Self::Radian => Composition::new(Dimension::PlaneAngle, 1), + Self::Second => Composition::new(Dimension::Time, 1), + _ => self.definition().terms().composition(), + } + } +} diff --git a/api/src/parser/atom/display.rs b/api/src/parser/atom/display.rs new file mode 100644 index 00000000..84b93661 --- /dev/null +++ b/api/src/parser/atom/display.rs @@ -0,0 +1,9 @@ +use std::fmt; + +use crate::{Atom, UcumSymbol}; + +impl fmt::Display for Atom { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.primary_code()) + } +} diff --git a/api/src/parser/atom/hash.rs b/api/src/parser/atom/hash.rs new file mode 100644 index 00000000..939892b6 --- /dev/null +++ b/api/src/parser/atom/hash.rs @@ -0,0 +1,9 @@ +use std::hash::{Hash, Hasher}; + +use crate::Atom; + +impl Hash for Atom { + fn hash(&self, state: &mut H) { + stringify!(self).hash(state); + } +} diff --git a/api/src/parser/atom/partial_eq.rs b/api/src/parser/atom/partial_eq.rs new file mode 100644 index 00000000..2fdf13c5 --- /dev/null +++ b/api/src/parser/atom/partial_eq.rs @@ -0,0 +1,11 @@ +use crate::{Atom, IsCompatibleWith, UcumUnit}; + +impl PartialEq for Atom { + fn eq(&self, other: &Self) -> bool { + if !self.is_compatible_with(other) { + return false; + } + + self.scalar() == other.scalar() + } +} diff --git a/api/src/parser/atom/reducible.rs b/api/src/parser/atom/reducible.rs new file mode 100644 index 00000000..bdf4f91a --- /dev/null +++ b/api/src/parser/atom/reducible.rs @@ -0,0 +1,15 @@ +use crate::{reducible::Reducible, Atom, UcumUnit}; + +impl Reducible for Atom { + fn reduce_value(&self, value: f64) -> f64 { + self.definition().reduce_value(value) + } + + fn calculate_magnitude(&self, value: f64) -> f64 { + if self.is_special() { + self.definition().calculate_magnitude(value) + } else { + 1.0 + } + } +} diff --git a/api/src/parser/classification.rs b/api/src/parser/classification.rs index de4e3d28..dacb19ec 100644 --- a/api/src/parser/classification.rs +++ b/api/src/parser/classification.rs @@ -29,13 +29,11 @@ pub enum Classification { UsLengths, UsVolumes, } - impl Default for Classification { fn default() -> Self { Self::Si } } - impl std::fmt::Display for Classification { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let s = match self { @@ -60,7 +58,6 @@ impl std::fmt::Display for Classification { Self::UsLengths => "UsLengths", Self::UsVolumes => "UsVolumes", }; - f.write_str(s) } } diff --git a/api/src/parser/property.rs b/api/src/parser/property.rs index 7ecca923..cbf4ecd3 100644 --- a/api/src/parser/property.rs +++ b/api/src/parser/property.rs @@ -5,7 +5,6 @@ use crate::parser::Atom; use std::fmt; - /// Property categorizes the unit by use. Not much mention of it in the UCUM /// HTML spec, but is used throughout the /// [XML description](http://unitsofmeasure.org/ucum-essence.xml). @@ -113,7 +112,6 @@ pub enum Property { Volume, XRayAttenuation, } - impl Property { /// All `Atom`s that match the `Property` variant. /// @@ -124,1042 +122,444 @@ impl Property { /// assert_eq!(Property::Acidity.atoms(), vec![Atom::PH]); /// ``` /// + #[allow(clippy::too_many_lines)] #[must_use] pub fn atoms(self) -> Vec { match self { - Self::Acceleration => { - vec![ - Atom::StandardAccelerationOfFreeFall, - Atom::Gal, - ] - }, - Self::Acidity => { - vec![ - Atom::PH, - ] - }, - Self::Action => { - vec![ - Atom::PlanckConstant, - ] - }, - Self::ActionArea => { - vec![ - Atom::Barn, - ] - }, - Self::AmountOfAProliferatingOrganism => { - vec![ - Atom::ColonyFormingUnits, - ] - }, + Self::Acceleration => vec![Atom::Gal, Atom::StandardAccelerationOfFreeFall,], + Self::Acidity => vec![Atom::PH,], + Self::Action => vec![Atom::PlanckConstant,], + Self::ActionArea => vec![Atom::Barn,], + Self::AmountOfAProliferatingOrganism => vec![Atom::ColonyFormingUnits,], Self::AmountOfAnAllergenCallibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters => { - vec![ - Atom::BioequivalentAllergenUnit, - ] - }, + vec![Atom::BioequivalentAllergenUnit,] + } Self::AmountOfAnAllergenCallibratedThroughInVivoTestingUsingTheStallergenesMethod => { - vec![ - Atom::IndexOfReactivity, - ] - }, + vec![Atom::IndexOfReactivity,] + } Self::AmountOfAnInfectiousAgent => { - vec![ - Atom::PlaqueFormingUnits, - Atom::FocusFormingUnits, - ] - }, + vec![Atom::FocusFormingUnits, Atom::PlaqueFormingUnits,] + } Self::AmountOfFibrinogenBrokenDownIntoTheMeasuredDDimers => { - vec![ - Atom::FibrinogenEquivalentUnit, - ] - }, + vec![Atom::FibrinogenEquivalentUnit,] + } Self::AmountOfInformation => { - vec![ - Atom::BitLogarithmusDualis, - Atom::Bit, - Atom::Byte, - ] - }, - Self::AmountOfSubstance => { - vec![ - Atom::Mole, - Atom::Equivalents, - ] - }, - Self::AmountOfSubstanceDissolvedParticles => { - vec![ - Atom::Osmole, - ] - }, + vec![Atom::Bit, Atom::BitLogarithmusDualis, Atom::Byte,] + } + Self::AmountOfSubstance => vec![Atom::Equivalents, Atom::Mole,], + Self::AmountOfSubstanceDissolvedParticles => vec![Atom::Osmole,], Self::AmplitudeSpectralDensity => { - vec![ - Atom::MeterPerSquareSecondsPerSquareRootOfHertz, - ] - }, + vec![Atom::MeterPerSquareSecondsPerSquareRootOfHertz,] + } Self::Arbitrary => { vec![ - Atom::InternationalUnit, - Atom::InternationalUnitSecondary, - Atom::ArbitraryUnit, - Atom::UnitedStatesPharmacopeiaUnit, + Atom::ArbitraryUnit, Atom::InternationalUnit, + Atom::InternationalUnitSecondary, Atom::UnitedStatesPharmacopeiaUnit, ] - }, + } Self::ArbitraryBiologicActivity => { - vec![ - Atom::KunkelUnit, - Atom::MacLaganUnit, - ] - }, - Self::ArbitraryElisaUnit => { - vec![ - Atom::ElisaUnit, - ] - }, + vec![Atom::KunkelUnit, Atom::MacLaganUnit,] + } + Self::ArbitraryElisaUnit => vec![Atom::ElisaUnit,], Self::Area => { vec![ - Atom::Are, - Atom::SquareInchInternational, - Atom::SquareFootInternational, - Atom::SquareYardInternational, - Atom::CircularMilInternational, - Atom::AcreUS, - Atom::SquareRodUS, - Atom::SquareMileUS, - Atom::Section, + Atom::AcreBritish, Atom::AcreUS, Atom::Are, + Atom::CircularMilInternational, Atom::Section, + Atom::SquareFootInternational, Atom::SquareInchInternational, + Atom::SquareMileUS, Atom::SquareRodUS, Atom::SquareYardInternational, Atom::Township, - Atom::AcreBritish, ] - }, - Self::BiologicActivityAntistreptolysinO => { - vec![ - Atom::ToddUnit, - ] - }, + } + Self::BiologicActivityAntistreptolysinO => vec![Atom::ToddUnit,], Self::BiologicActivityInfectivityOfAnInfectiousAgentPreparation => { vec![ - Atom::CellCultureInfectiousDose, + Atom::CellCultureInfectiousDose, Atom::EmbryoInfectiousDose, Atom::TissueCultureInfectiousDose, - Atom::EmbryoInfectiousDose, - ] - }, - Self::BiologicActivityOfAmylase => { - vec![ - Atom::DyeUnit, - Atom::SomogyiUnit, - ] - }, - Self::BiologicActivityOfAnticardiolipinIgA => { - vec![ - Atom::AplUnit, - ] - }, - Self::BiologicActivityOfAnticardiolipinIgG => { - vec![ - Atom::GplUnit, - ] - }, - Self::BiologicActivityOfAnticardiolipinIgM => { - vec![ - Atom::MplUnit, ] - }, - Self::BiologicActivityOfFactorViiiInhibitor => { - vec![ - Atom::BethesdaUnit, - ] - }, + } + Self::BiologicActivityOfAmylase => vec![Atom::DyeUnit, Atom::SomogyiUnit,], + Self::BiologicActivityOfAnticardiolipinIgA => vec![Atom::AplUnit,], + Self::BiologicActivityOfAnticardiolipinIgG => vec![Atom::GplUnit,], + Self::BiologicActivityOfAnticardiolipinIgM => vec![Atom::MplUnit,], + Self::BiologicActivityOfFactorViiiInhibitor => vec![Atom::BethesdaUnit,], Self::BiologicActivityOfFactorXaInhibitorHeparin => { - vec![ - Atom::AntiFactorXaUnit, - ] - }, + vec![Atom::AntiFactorXaUnit,] + } Self::BiologicActivityOfPhosphatase => { - vec![ - Atom::BodanskyUnit, - Atom::KingArmstrongUnit, - ] - }, - Self::BiologicActivityOfTuberculin => { - vec![ - Atom::TuberculinUnit, - ] - }, - Self::Brightness => { - vec![ - Atom::Lambert, - ] - }, - Self::CatalyticActivity => { - vec![ - Atom::Katal, - Atom::Unit, - ] - }, - Self::DepthOfWater => { - vec![ - Atom::FathomInternational, - ] - }, - Self::DoseEquivalent => { - vec![ - Atom::Sievert, - Atom::RadiationEquivalentMan, - ] - }, + vec![Atom::BodanskyUnit, Atom::KingArmstrongUnit,] + } + Self::BiologicActivityOfTuberculin => vec![Atom::TuberculinUnit,], + Self::Brightness => vec![Atom::Lambert,], + Self::CatalyticActivity => vec![Atom::Katal, Atom::Unit,], + Self::DepthOfWater => vec![Atom::FathomInternational,], + Self::DoseEquivalent => vec![Atom::RadiationEquivalentMan, Atom::Sievert,], Self::DryVolume => { vec![ - Atom::BushelUS, - Atom::HistoricalWinchesterGallon, - Atom::PeckUS, - Atom::DryQuartUS, - Atom::DryPintUS, - ] - }, - Self::DynamicViscosity => { - vec![ - Atom::Poise, - ] - }, - Self::EhrlichUnit => { - vec![ - Atom::EhrlichUnit, - ] - }, - Self::ElectricCapacitance => { - vec![ - Atom::Farad, - ] - }, - Self::ElectricCharge => { - vec![ - Atom::Coulomb, - Atom::ElementaryCharge, - ] - }, - Self::ElectricConductance => { - vec![ - Atom::Siemens, - Atom::Mho, - ] - }, - Self::ElectricCurrent => { - vec![ - Atom::Ampere, - Atom::Biot, - ] - }, - Self::ElectricPermittivity => { - vec![ - Atom::PermittivityOfVacuum, - ] - }, - Self::ElectricPotential => { - vec![ - Atom::Volt, - ] - }, + Atom::BushelUS, Atom::DryPintUS, Atom::DryQuartUS, + Atom::HistoricalWinchesterGallon, Atom::PeckUS, + ] + } + Self::DynamicViscosity => vec![Atom::Poise,], + Self::EhrlichUnit => vec![Atom::EhrlichUnit,], + Self::ElectricCapacitance => vec![Atom::Farad,], + Self::ElectricCharge => vec![Atom::Coulomb, Atom::ElementaryCharge,], + Self::ElectricConductance => vec![Atom::Mho, Atom::Siemens,], + Self::ElectricCurrent => vec![Atom::Ampere, Atom::Biot,], + Self::ElectricPermittivity => vec![Atom::PermittivityOfVacuum,], + Self::ElectricPotential => vec![Atom::Volt,], Self::ElectricPotentialLevel => { vec![ + Atom::Bel10Nanovolt, Atom::BelMicrovolt, Atom::BelMillivolt, Atom::BelVolt, - Atom::BelMillivolt, - Atom::BelMicrovolt, - Atom::Bel10Nanovolt, - ] - }, - Self::ElectricResistance => { - vec![ - Atom::Ohm, ] - }, + } + Self::ElectricResistance => vec![Atom::Ohm,], Self::Energy => { vec![ - Atom::Joule, - Atom::Electronvolt, - Atom::Erg, - Atom::CalorieAt15C, - Atom::CalorieAt20C, - Atom::MeanCalorie, - Atom::InternationalTableCalorie, - Atom::ThermochemicalCalorie, - Atom::Calorie, - Atom::NutritionLabelCalories, - Atom::BritishThermalUnitAt39F, - Atom::BritishThermalUnitAt59F, - Atom::BritishThermalUnitAt60F, - Atom::MeanBritishThermalUnit, + Atom::BritishThermalUnit, Atom::BritishThermalUnitAt39F, + Atom::BritishThermalUnitAt59F, Atom::BritishThermalUnitAt60F, + Atom::Calorie, Atom::CalorieAt15C, Atom::CalorieAt20C, + Atom::Electronvolt, Atom::Erg, Atom::InternationalTableBritishThermalUnit, - Atom::ThermochemicalBritishThermalUnit, - Atom::BritishThermalUnit, - ] - }, - Self::EnergyDose => { - vec![ - Atom::Gray, - Atom::RadiationAbsorbedDose, + Atom::InternationalTableCalorie, Atom::Joule, + Atom::MeanBritishThermalUnit, Atom::MeanCalorie, + Atom::NutritionLabelCalories, Atom::ThermochemicalBritishThermalUnit, + Atom::ThermochemicalCalorie, ] - }, + } + Self::EnergyDose => vec![Atom::Gray, Atom::RadiationAbsorbedDose,], Self::FluidResistance => { - vec![ - Atom::PeripheralVascularResistanceUnit, - Atom::WoodUnit, - ] - }, + vec![Atom::PeripheralVascularResistanceUnit, Atom::WoodUnit,] + } Self::FluidVolume => { vec![ - Atom::QueenAnnesWineGallonUS, - Atom::BarrelUS, - Atom::QuartUS, - Atom::PintUS, - Atom::GillUS, - Atom::FluidOunceUS, - Atom::FluidDramUS, - Atom::MinimUS, - Atom::CordUS, - Atom::MetricFluidOunce, - ] - }, - Self::FluxOfMagneticInduction => { - vec![ - Atom::Maxwell, + Atom::BarrelUS, Atom::CordUS, Atom::FluidDramUS, Atom::FluidOunceUS, + Atom::GillUS, Atom::MetricFluidOunce, Atom::MinimUS, Atom::PintUS, + Atom::QuartUS, Atom::QueenAnnesWineGallonUS, ] - }, + } + Self::FluxOfMagneticInduction => vec![Atom::Maxwell,], Self::Force => { vec![ - Atom::Newton, - Atom::GramForce, + Atom::Dyne, Atom::GramForce, Atom::Newton, Atom::PoundForceAvoirdupois, - Atom::Dyne, ] - }, + } Self::Fraction => { vec![ - Atom::Percent, - Atom::PartsPerThousand, - Atom::PartsPerMillion, - Atom::PartsPerBillion, - Atom::PartsPerTrillion, - ] - }, - Self::Frequency => { - vec![ - Atom::Hertz, + Atom::PartsPerBillion, Atom::PartsPerMillion, Atom::PartsPerThousand, + Atom::PartsPerTrillion, Atom::Percent, ] - }, - Self::GaugeOfCatheters => { - vec![ - Atom::Charriere, - ] - }, - Self::HeightOfHorses => { - vec![ - Atom::HandInternational, - ] - }, + } + Self::Frequency => vec![Atom::Hertz,], + Self::GaugeOfCatheters => vec![Atom::Charriere,], + Self::HeightOfHorses => vec![Atom::HandInternational,], Self::HomeopathicPotencyHahnemann => { vec![ - Atom::HomeopathicPotencyOfDecimalHahnemannianSeries, Atom::HomeopathicPotencyOfCentesimalHahnemannianSeries, + Atom::HomeopathicPotencyOfDecimalHahnemannianSeries, Atom::HomeopathicPotencyOfMillesimalHahnemannianSeries, Atom::HomeopathicPotencyOfQuintamillesimalHahnemannianSeries, ] - }, + } Self::HomeopathicPotencyKorsakov => { vec![ - Atom::HomeopathicPotencyOfDecimalKorsakovianSeries, Atom::HomeopathicPotencyOfCentesimalKorsakovianSeries, + Atom::HomeopathicPotencyOfDecimalKorsakovianSeries, Atom::HomeopathicPotencyOfMillesimalKorsakovianSeries, Atom::HomeopathicPotencyOfQuintamillesimalKorsakovianSeries, ] - }, + } Self::HomeopathicPotencyRetired => { vec![ - Atom::HomeopathicPotencyOfDecimalSeriesRetired, Atom::HomeopathicPotencyOfCentesimalSeriesRetired, + Atom::HomeopathicPotencyOfDecimalSeriesRetired, Atom::HomeopathicPotencyOfMillesimalSeriesRetired, Atom::HomeopathicPotencyOfQuintamillesimalSeriesRetired, ] - }, - Self::Illuminance => { - vec![ - Atom::Lux, - Atom::Phot, - ] - }, - Self::Inductance => { - vec![ - Atom::Henry, - ] - }, - Self::IonDose => { - vec![ - Atom::Roentgen, - ] - }, - Self::KinematicViscosity => { - vec![ - Atom::Stokes, - ] - }, + } + Self::Illuminance => vec![Atom::Lux, Atom::Phot,], + Self::Inductance => vec![Atom::Henry,], + Self::IonDose => vec![Atom::Roentgen,], + Self::KinematicViscosity => vec![Atom::Stokes,], Self::Length => { vec![ - Atom::Meter, - Atom::AstronomicUnit, - Atom::Parsec, - Atom::LightYear, - Atom::InchInternational, - Atom::FootInternational, - Atom::YardInternational, - Atom::MileInternational, - Atom::NauticalMileInternational, - Atom::MilInternational, - Atom::FootUS, + Atom::Angstrom, Atom::AstronomicUnit, Atom::Cicero, Atom::Didot, + Atom::FathomBritish, Atom::FathomUS, Atom::FootBritish, + Atom::FootInternational, Atom::FootUS, Atom::FurlongUS, + Atom::GuntersChainBritish, Atom::GuntersChainUS, Atom::InchBritish, + Atom::InchInternational, Atom::InchUS, Atom::LightYear, Atom::Ligne, + Atom::Line, Atom::LinkForGuntersChainBritish, + Atom::LinkForGuntersChainUS, Atom::LinkForRamdensChainUS, + Atom::Meter, Atom::MilInternational, Atom::MilUS, Atom::MileBritish, + Atom::MileInternational, Atom::MileUS, Atom::NauticalMileBritish, + Atom::NauticalMileInternational, Atom::PaceBritish, Atom::Parsec, + Atom::Pica, Atom::Pied, Atom::Point, Atom::Pouce, Atom::PrintersPica, + Atom::PrintersPoint, Atom::RamdensChainUS, Atom::RodBritish, + Atom::RodUS, Atom::Smoot, Atom::YardBritish, Atom::YardInternational, Atom::YardUS, - Atom::InchUS, - Atom::RodUS, - Atom::GuntersChainUS, - Atom::LinkForGuntersChainUS, - Atom::RamdensChainUS, - Atom::LinkForRamdensChainUS, - Atom::FathomUS, - Atom::FurlongUS, - Atom::MileUS, - Atom::MilUS, - Atom::InchBritish, - Atom::FootBritish, - Atom::RodBritish, - Atom::GuntersChainBritish, - Atom::LinkForGuntersChainBritish, - Atom::FathomBritish, - Atom::PaceBritish, - Atom::YardBritish, - Atom::MileBritish, - Atom::NauticalMileBritish, - Atom::Line, - Atom::Point, - Atom::Pica, - Atom::PrintersPoint, - Atom::PrintersPica, - Atom::Pied, - Atom::Pouce, - Atom::Ligne, - Atom::Didot, - Atom::Cicero, - Atom::Angstrom, - Atom::Smoot, - ] - }, - Self::Level => { - vec![ - Atom::Neper, - Atom::Bel, - ] - }, - Self::LinearMassDensityOfTextileThread => { - vec![ - Atom::Tex, - Atom::Denier, - ] - }, - Self::LineicNumber => { - vec![ - Atom::Kayser, - Atom::MeshInternational, - ] - }, - Self::LumIntensityDensity => { - vec![ - Atom::Stilb, - ] - }, - Self::LuminousFlux => { - vec![ - Atom::Lumen, - ] - }, - Self::LuminousIntensity => { - vec![ - Atom::Candela, - ] - }, - Self::MagneticFieldIntensity => { - vec![ - Atom::Oersted, - ] - }, - Self::MagneticFlux => { - vec![ - Atom::Weber, - ] - }, - Self::MagneticFluxDensity => { - vec![ - Atom::Tesla, - Atom::Gauss, - ] - }, - Self::MagneticPermeability => { - vec![ - Atom::PermeabilityOfVacuum, - ] - }, - Self::MagneticTension => { - vec![ - Atom::Gilbert, ] - }, + } + Self::Level => vec![Atom::Bel, Atom::Neper,], + Self::LinearMassDensityOfTextileThread => vec![Atom::Denier, Atom::Tex,], + Self::LineicNumber => vec![Atom::Kayser, Atom::MeshInternational,], + Self::LumIntensityDensity => vec![Atom::Stilb,], + Self::LuminousFlux => vec![Atom::Lumen,], + Self::LuminousIntensity => vec![Atom::Candela,], + Self::MagneticFieldIntensity => vec![Atom::Oersted,], + Self::MagneticFlux => vec![Atom::Weber,], + Self::MagneticFluxDensity => vec![Atom::Gauss, Atom::Tesla,], + Self::MagneticPermeability => vec![Atom::PermeabilityOfVacuum,], + Self::MagneticTension => vec![Atom::Gilbert,], Self::Mass => { vec![ - Atom::Gram, - Atom::Tonne, + Atom::DramApothecaries, Atom::DramAvoirdupois, Atom::ElectronMass, + Atom::Grain, Atom::Gram, Atom::LongHunderdweightAvoirdupois, + Atom::LongTonAvoirdupois, Atom::MetricCarat, Atom::MetricOunce, + Atom::OunceApothecaries, Atom::OunceAvoirdupois, Atom::OunceTroy, + Atom::PennyweightTroy, Atom::PoundApothecaries, + Atom::PoundAvoirdupois, Atom::PoundTroy, Atom::ProtonMass, + Atom::ScrupleApothecaries, Atom::ShortHundredweightAvoirdupois, + Atom::ShortTonAvoirdupois, Atom::StoneAvoirdupois, Atom::Tonne, Atom::UnifiedAtomicMassUnit, - Atom::ElectronMass, - Atom::ProtonMass, - Atom::Grain, - Atom::PoundAvoirdupois, - Atom::OunceAvoirdupois, - Atom::DramAvoirdupois, - Atom::ShortHundredweightAvoirdupois, - Atom::LongHunderdweightAvoirdupois, - Atom::ShortTonAvoirdupois, - Atom::LongTonAvoirdupois, - Atom::StoneAvoirdupois, - Atom::PennyweightTroy, - Atom::OunceTroy, - Atom::PoundTroy, - Atom::ScrupleApothecaries, - Atom::DramApothecaries, - Atom::OunceApothecaries, - Atom::PoundApothecaries, - Atom::MetricOunce, - Atom::MetricCarat, ] - }, - Self::MassConcentration => { - vec![ - Atom::GramPercent, - ] - }, - Self::MassFraction => { - vec![ - Atom::CaratOfGoldAlloys, - ] - }, - Self::MetabolicCostOfPhysicalActivity => { - vec![ - Atom::MetabolicEquivalent, - ] - }, + } + Self::MassConcentration => vec![Atom::GramPercent,], + Self::MassFraction => vec![Atom::CaratOfGoldAlloys,], + Self::MetabolicCostOfPhysicalActivity => vec![Atom::MetabolicEquivalent,], Self::Number => { vec![ + Atom::TheNumberPi, Atom::TheNumberTenForArbitraryPowersCaret, Atom::TheNumberTenForArbitraryPowersStar, - Atom::TheNumberTenForArbitraryPowersCaret, - Atom::TheNumberPi, ] - }, + } Self::PlaneAngle => { vec![ - Atom::Radian, - Atom::Gon, - Atom::Degree, - Atom::MinuteAngle, - Atom::SecondAngle, - Atom::Circle, + Atom::Circle, Atom::Degree, Atom::Gon, Atom::MinuteAngle, + Atom::Radian, Atom::SecondAngle, ] - }, - Self::Power => { - vec![ - Atom::Watt, - Atom::Horsepower, - ] - }, - Self::PowerLevel => { - vec![ - Atom::BelWatt, - Atom::BelKilowatt, - ] - }, + } + Self::Power => vec![Atom::Horsepower, Atom::Watt,], + Self::PowerLevel => vec![Atom::BelKilowatt, Atom::BelWatt,], Self::Pressure => { vec![ - Atom::Pascal, - Atom::Bar, - Atom::StandardAtmosphere, - Atom::MeterOfWaterColumn, - Atom::MeterOfMercuryColumn, - Atom::InchOfWaterColumn, - Atom::InchOfMercuryColumn, + Atom::Bar, Atom::InchOfMercuryColumn, Atom::InchOfWaterColumn, + Atom::MeterOfMercuryColumn, Atom::MeterOfWaterColumn, Atom::Pascal, + Atom::PoundPerSqareInch, Atom::StandardAtmosphere, Atom::TechnicalAtmosphere, - Atom::PoundPerSqareInch, ] - }, - Self::PressureLevel => { - vec![ - Atom::BelSoundPressure, - ] - }, + } + Self::PressureLevel => vec![Atom::BelSoundPressure,], Self::ProcedureDefinedAmountOfAPoliomyelitisDAntigenSubstance => { - vec![ - Atom::DAntigenUnit, - ] - }, + vec![Atom::DAntigenUnit,] + } Self::ProcedureDefinedAmountOfAProteinSubstance => { - vec![ - Atom::ProteinNitrogenUnit, - ] - }, + vec![Atom::ProteinNitrogenUnit,] + } Self::ProcedureDefinedAmountOfAnAllergenUsingSomeReferenceStandard => { - vec![ - Atom::AllergenUnit, - ] - }, + vec![Atom::AllergenUnit,] + } Self::ProcedureDefinedAmountOfAnAntigenSubstance => { - vec![ - Atom::LimitOfFlocculation, - ] - }, + vec![Atom::LimitOfFlocculation,] + } Self::ProcedureDefinedAmountOfTheMajorAllergenOfRagweed => { - vec![ - Atom::AllergenUnitForAmbrosiaArtemisiifolia, - ] - }, - Self::Radioactivity => { - vec![ - Atom::Becquerel, - Atom::Curie, - ] - }, - Self::RefractionOfALens => { - vec![ - Atom::Diopter, - ] - }, - Self::RefractionOfAPrism => { - vec![ - Atom::PrismDiopter, - ] - }, - Self::SedimentationCoefficient => { - vec![ - Atom::SvedbergUnit, - ] - }, - Self::SignalTransmissionRate => { - vec![ - Atom::Baud, - ] - }, - Self::Slope => { - vec![ - Atom::PercentOfSlope, - ] - }, - Self::SolidAngle => { - vec![ - Atom::Steradian, - Atom::Spere, - ] - }, + vec![Atom::AllergenUnitForAmbrosiaArtemisiifolia,] + } + Self::Radioactivity => vec![Atom::Becquerel, Atom::Curie,], + Self::RefractionOfALens => vec![Atom::Diopter,], + Self::RefractionOfAPrism => vec![Atom::PrismDiopter,], + Self::SedimentationCoefficient => vec![Atom::SvedbergUnit,], + Self::SignalTransmissionRate => vec![Atom::Baud,], + Self::Slope => vec![Atom::PercentOfSlope,], + Self::SolidAngle => vec![Atom::Spere, Atom::Steradian,], Self::Temperature => { vec![ - Atom::Kelvin, - Atom::DegreeCelsius, - Atom::DegreeFahrenheit, - Atom::DegreeRankine, - Atom::DegreeReaumur, + Atom::DegreeCelsius, Atom::DegreeFahrenheit, Atom::DegreeRankine, + Atom::DegreeReaumur, Atom::Kelvin, ] - }, + } Self::Time => { vec![ - Atom::Second, - Atom::Minute, - Atom::Hour, - Atom::Day, - Atom::TropicalYear, - Atom::MeanJulianYear, - Atom::MeanGregorianYear, - Atom::Year, - Atom::Week, - Atom::SynodalMonth, - Atom::MeanJulianMonth, - Atom::MeanGregorianMonth, - Atom::Month, + Atom::Day, Atom::Hour, Atom::MeanGregorianMonth, + Atom::MeanGregorianYear, Atom::MeanJulianMonth, Atom::MeanJulianYear, + Atom::Minute, Atom::Month, Atom::Second, Atom::SynodalMonth, + Atom::TropicalYear, Atom::Week, Atom::Year, ] - }, + } Self::Unclassified => { - vec![ - Atom::BoltzmannConstant, - Atom::NewtonianConstantOfGravitation, - ] - }, + vec![Atom::BoltzmannConstant, Atom::NewtonianConstantOfGravitation,] + } Self::Velocity => { - vec![ - Atom::VelocityOfLight, - Atom::KnotInternational, - Atom::KnotBritish, - ] - }, + vec![Atom::KnotBritish, Atom::KnotInternational, Atom::VelocityOfLight,] + } Self::ViewAreaInMicroscope => { - vec![ - Atom::HighPowerField, - Atom::LowPowerField, - ] - }, + vec![Atom::HighPowerField, Atom::LowPowerField,] + } Self::Volume => { vec![ - Atom::Liter, - Atom::LiterSecondary, - Atom::CubicInchInternational, - Atom::CubicFootInternational, - Atom::CubicYardInternational, - Atom::BoardFootInternational, - Atom::CordInternational, - Atom::TablespoonUS, - Atom::TeaspoonUS, - Atom::CupUS, - Atom::MetricCup, - Atom::MetricTeaspoon, - Atom::MetricTablespoon, - Atom::GallonBritish, - Atom::PeckBritish, - Atom::BushelBritish, - Atom::QuartBritish, - Atom::PintBritish, - Atom::GillBritish, - Atom::FluidOunceBritish, - Atom::FluidDramBritish, - Atom::MinimBritish, - Atom::Drop, - Atom::Stere, - ] - }, - Self::XRayAttenuation => { - vec![ - Atom::HounsfieldUnit, - ] - }, + Atom::BoardFootInternational, Atom::BushelBritish, + Atom::CordInternational, Atom::CubicFootInternational, + Atom::CubicInchInternational, Atom::CubicYardInternational, + Atom::CupUS, Atom::Drop, Atom::FluidDramBritish, + Atom::FluidOunceBritish, Atom::GallonBritish, Atom::GillBritish, + Atom::Liter, Atom::LiterSecondary, Atom::MetricCup, + Atom::MetricTablespoon, Atom::MetricTeaspoon, Atom::MinimBritish, + Atom::PeckBritish, Atom::PintBritish, Atom::QuartBritish, + Atom::Stere, Atom::TablespoonUS, Atom::TeaspoonUS, + ] + } + Self::XRayAttenuation => vec![Atom::HounsfieldUnit,], } } } - impl Default for Property { fn default() -> Self { Self::Unclassified } } - impl fmt::Display for Property { + #[allow(clippy::too_many_lines)] fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { let string = match self { - Self::Acceleration => { - "Acceleration" - }, - Self::Acidity => { - "Acidity" - }, - Self::Action => { - "Action" - }, - Self::ActionArea => { - "ActionArea" - }, - Self::AmountOfAProliferatingOrganism => { - "AmountOfAProliferatingOrganism" - }, + Self::Acceleration => "Acceleration", + Self::Acidity => "Acidity", + Self::Action => "Action", + Self::ActionArea => "ActionArea", + Self::AmountOfAProliferatingOrganism => "AmountOfAProliferatingOrganism", Self::AmountOfAnAllergenCallibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters => { "AmountOfAnAllergenCallibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters" - }, + } Self::AmountOfAnAllergenCallibratedThroughInVivoTestingUsingTheStallergenesMethod => { "AmountOfAnAllergenCallibratedThroughInVivoTestingUsingTheStallergenesMethod" - }, - Self::AmountOfAnInfectiousAgent => { - "AmountOfAnInfectiousAgent" - }, + } + Self::AmountOfAnInfectiousAgent => "AmountOfAnInfectiousAgent", Self::AmountOfFibrinogenBrokenDownIntoTheMeasuredDDimers => { "AmountOfFibrinogenBrokenDownIntoTheMeasuredDDimers" - }, - Self::AmountOfInformation => { - "AmountOfInformation" - }, - Self::AmountOfSubstance => { - "AmountOfSubstance" - }, + } + Self::AmountOfInformation => "AmountOfInformation", + Self::AmountOfSubstance => "AmountOfSubstance", Self::AmountOfSubstanceDissolvedParticles => { "AmountOfSubstanceDissolvedParticles" - }, - Self::AmplitudeSpectralDensity => { - "AmplitudeSpectralDensity" - }, - Self::Arbitrary => { - "Arbitrary" - }, - Self::ArbitraryBiologicActivity => { - "ArbitraryBiologicActivity" - }, - Self::ArbitraryElisaUnit => { - "ArbitraryElisaUnit" - }, - Self::Area => { - "Area" - }, + } + Self::AmplitudeSpectralDensity => "AmplitudeSpectralDensity", + Self::Arbitrary => "Arbitrary", + Self::ArbitraryBiologicActivity => "ArbitraryBiologicActivity", + Self::ArbitraryElisaUnit => "ArbitraryElisaUnit", + Self::Area => "Area", Self::BiologicActivityAntistreptolysinO => { "BiologicActivityAntistreptolysinO" - }, + } Self::BiologicActivityInfectivityOfAnInfectiousAgentPreparation => { "BiologicActivityInfectivityOfAnInfectiousAgentPreparation" - }, - Self::BiologicActivityOfAmylase => { - "BiologicActivityOfAmylase" - }, + } + Self::BiologicActivityOfAmylase => "BiologicActivityOfAmylase", Self::BiologicActivityOfAnticardiolipinIgA => { "BiologicActivityOfAnticardiolipinIgA" - }, + } Self::BiologicActivityOfAnticardiolipinIgG => { "BiologicActivityOfAnticardiolipinIgG" - }, + } Self::BiologicActivityOfAnticardiolipinIgM => { "BiologicActivityOfAnticardiolipinIgM" - }, + } Self::BiologicActivityOfFactorViiiInhibitor => { "BiologicActivityOfFactorViiiInhibitor" - }, + } Self::BiologicActivityOfFactorXaInhibitorHeparin => { "BiologicActivityOfFactorXaInhibitorHeparin" - }, - Self::BiologicActivityOfPhosphatase => { - "BiologicActivityOfPhosphatase" - }, - Self::BiologicActivityOfTuberculin => { - "BiologicActivityOfTuberculin" - }, - Self::Brightness => { - "Brightness" - }, - Self::CatalyticActivity => { - "CatalyticActivity" - }, - Self::DepthOfWater => { - "DepthOfWater" - }, - Self::DoseEquivalent => { - "DoseEquivalent" - }, - Self::DryVolume => { - "DryVolume" - }, - Self::DynamicViscosity => { - "DynamicViscosity" - }, - Self::EhrlichUnit => { - "EhrlichUnit" - }, - Self::ElectricCapacitance => { - "ElectricCapacitance" - }, - Self::ElectricCharge => { - "ElectricCharge" - }, - Self::ElectricConductance => { - "ElectricConductance" - }, - Self::ElectricCurrent => { - "ElectricCurrent" - }, - Self::ElectricPermittivity => { - "ElectricPermittivity" - }, - Self::ElectricPotential => { - "ElectricPotential" - }, - Self::ElectricPotentialLevel => { - "ElectricPotentialLevel" - }, - Self::ElectricResistance => { - "ElectricResistance" - }, - Self::Energy => { - "Energy" - }, - Self::EnergyDose => { - "EnergyDose" - }, - Self::FluidResistance => { - "FluidResistance" - }, - Self::FluidVolume => { - "FluidVolume" - }, - Self::FluxOfMagneticInduction => { - "FluxOfMagneticInduction" - }, - Self::Force => { - "Force" - }, - Self::Fraction => { - "Fraction" - }, - Self::Frequency => { - "Frequency" - }, - Self::GaugeOfCatheters => { - "GaugeOfCatheters" - }, - Self::HeightOfHorses => { - "HeightOfHorses" - }, - Self::HomeopathicPotencyHahnemann => { - "HomeopathicPotencyHahnemann" - }, - Self::HomeopathicPotencyKorsakov => { - "HomeopathicPotencyKorsakov" - }, - Self::HomeopathicPotencyRetired => { - "HomeopathicPotencyRetired" - }, - Self::Illuminance => { - "Illuminance" - }, - Self::Inductance => { - "Inductance" - }, - Self::IonDose => { - "IonDose" - }, - Self::KinematicViscosity => { - "KinematicViscosity" - }, - Self::Length => { - "Length" - }, - Self::Level => { - "Level" - }, - Self::LinearMassDensityOfTextileThread => { - "LinearMassDensityOfTextileThread" - }, - Self::LineicNumber => { - "LineicNumber" - }, - Self::LumIntensityDensity => { - "LumIntensityDensity" - }, - Self::LuminousFlux => { - "LuminousFlux" - }, - Self::LuminousIntensity => { - "LuminousIntensity" - }, - Self::MagneticFieldIntensity => { - "MagneticFieldIntensity" - }, - Self::MagneticFlux => { - "MagneticFlux" - }, - Self::MagneticFluxDensity => { - "MagneticFluxDensity" - }, - Self::MagneticPermeability => { - "MagneticPermeability" - }, - Self::MagneticTension => { - "MagneticTension" - }, - Self::Mass => { - "Mass" - }, - Self::MassConcentration => { - "MassConcentration" - }, - Self::MassFraction => { - "MassFraction" - }, - Self::MetabolicCostOfPhysicalActivity => { - "MetabolicCostOfPhysicalActivity" - }, - Self::Number => { - "Number" - }, - Self::PlaneAngle => { - "PlaneAngle" - }, - Self::Power => { - "Power" - }, - Self::PowerLevel => { - "PowerLevel" - }, - Self::Pressure => { - "Pressure" - }, - Self::PressureLevel => { - "PressureLevel" - }, + } + Self::BiologicActivityOfPhosphatase => "BiologicActivityOfPhosphatase", + Self::BiologicActivityOfTuberculin => "BiologicActivityOfTuberculin", + Self::Brightness => "Brightness", + Self::CatalyticActivity => "CatalyticActivity", + Self::DepthOfWater => "DepthOfWater", + Self::DoseEquivalent => "DoseEquivalent", + Self::DryVolume => "DryVolume", + Self::DynamicViscosity => "DynamicViscosity", + Self::EhrlichUnit => "EhrlichUnit", + Self::ElectricCapacitance => "ElectricCapacitance", + Self::ElectricCharge => "ElectricCharge", + Self::ElectricConductance => "ElectricConductance", + Self::ElectricCurrent => "ElectricCurrent", + Self::ElectricPermittivity => "ElectricPermittivity", + Self::ElectricPotential => "ElectricPotential", + Self::ElectricPotentialLevel => "ElectricPotentialLevel", + Self::ElectricResistance => "ElectricResistance", + Self::Energy => "Energy", + Self::EnergyDose => "EnergyDose", + Self::FluidResistance => "FluidResistance", + Self::FluidVolume => "FluidVolume", + Self::FluxOfMagneticInduction => "FluxOfMagneticInduction", + Self::Force => "Force", + Self::Fraction => "Fraction", + Self::Frequency => "Frequency", + Self::GaugeOfCatheters => "GaugeOfCatheters", + Self::HeightOfHorses => "HeightOfHorses", + Self::HomeopathicPotencyHahnemann => "HomeopathicPotencyHahnemann", + Self::HomeopathicPotencyKorsakov => "HomeopathicPotencyKorsakov", + Self::HomeopathicPotencyRetired => "HomeopathicPotencyRetired", + Self::Illuminance => "Illuminance", + Self::Inductance => "Inductance", + Self::IonDose => "IonDose", + Self::KinematicViscosity => "KinematicViscosity", + Self::Length => "Length", + Self::Level => "Level", + Self::LinearMassDensityOfTextileThread => "LinearMassDensityOfTextileThread", + Self::LineicNumber => "LineicNumber", + Self::LumIntensityDensity => "LumIntensityDensity", + Self::LuminousFlux => "LuminousFlux", + Self::LuminousIntensity => "LuminousIntensity", + Self::MagneticFieldIntensity => "MagneticFieldIntensity", + Self::MagneticFlux => "MagneticFlux", + Self::MagneticFluxDensity => "MagneticFluxDensity", + Self::MagneticPermeability => "MagneticPermeability", + Self::MagneticTension => "MagneticTension", + Self::Mass => "Mass", + Self::MassConcentration => "MassConcentration", + Self::MassFraction => "MassFraction", + Self::MetabolicCostOfPhysicalActivity => "MetabolicCostOfPhysicalActivity", + Self::Number => "Number", + Self::PlaneAngle => "PlaneAngle", + Self::Power => "Power", + Self::PowerLevel => "PowerLevel", + Self::Pressure => "Pressure", + Self::PressureLevel => "PressureLevel", Self::ProcedureDefinedAmountOfAPoliomyelitisDAntigenSubstance => { "ProcedureDefinedAmountOfAPoliomyelitisDAntigenSubstance" - }, + } Self::ProcedureDefinedAmountOfAProteinSubstance => { "ProcedureDefinedAmountOfAProteinSubstance" - }, + } Self::ProcedureDefinedAmountOfAnAllergenUsingSomeReferenceStandard => { "ProcedureDefinedAmountOfAnAllergenUsingSomeReferenceStandard" - }, + } Self::ProcedureDefinedAmountOfAnAntigenSubstance => { "ProcedureDefinedAmountOfAnAntigenSubstance" - }, + } Self::ProcedureDefinedAmountOfTheMajorAllergenOfRagweed => { "ProcedureDefinedAmountOfTheMajorAllergenOfRagweed" - }, - Self::Radioactivity => { - "Radioactivity" - }, - Self::RefractionOfALens => { - "RefractionOfALens" - }, - Self::RefractionOfAPrism => { - "RefractionOfAPrism" - }, - Self::SedimentationCoefficient => { - "SedimentationCoefficient" - }, - Self::SignalTransmissionRate => { - "SignalTransmissionRate" - }, - Self::Slope => { - "Slope" - }, - Self::SolidAngle => { - "SolidAngle" - }, - Self::Temperature => { - "Temperature" - }, - Self::Time => { - "Time" - }, - Self::Unclassified => { - "Unclassified" - }, - Self::Velocity => { - "Velocity" - }, - Self::ViewAreaInMicroscope => { - "ViewAreaInMicroscope" - }, - Self::Volume => { - "Volume" - }, - Self::XRayAttenuation => { - "XRayAttenuation" - }, + } + Self::Radioactivity => "Radioactivity", + Self::RefractionOfALens => "RefractionOfALens", + Self::RefractionOfAPrism => "RefractionOfAPrism", + Self::SedimentationCoefficient => "SedimentationCoefficient", + Self::SignalTransmissionRate => "SignalTransmissionRate", + Self::Slope => "Slope", + Self::SolidAngle => "SolidAngle", + Self::Temperature => "Temperature", + Self::Time => "Time", + Self::Unclassified => "Unclassified", + Self::Velocity => "Velocity", + Self::ViewAreaInMicroscope => "ViewAreaInMicroscope", + Self::Volume => "Volume", + Self::XRayAttenuation => "XRayAttenuation", }; - write!(formatter, "{string}") } } - #[cfg(test)] mod tests { use super::*; - #[test] fn validate_display() { let a = format!("{}", Property::Acceleration); diff --git a/api/src/parser/symbols/mapper.rs b/api/src/parser/symbols/mapper.rs index 48c3ead4..f7adb7cb 100644 --- a/api/src/parser/symbols/mapper.rs +++ b/api/src/parser/symbols/mapper.rs @@ -1,8 +1,3 @@ -//----------------------------------------------------------------------------- -// DO NOT EDIT THIS FILE! -// This is generated by wise_units-atom_generator. -//----------------------------------------------------------------------------- - use crate::parser::{ symbols::{symbol_parser::Rule, Symbol}, Error, Visit, diff --git a/api/src/parser/symbols/symbol.pest b/api/src/parser/symbols/symbol.pest index 143e1595..d8549108 100644 --- a/api/src/parser/symbols/symbol.pest +++ b/api/src/parser/symbols/symbol.pest @@ -381,7 +381,6 @@ pri_atom = { | pri_unified_atomic_mass_unit } - pri_meter_per_square_seconds_per_square_root_of_hertz = { "[m/s2/Hz^(1/2)]" } pri_allergen_unit_for_ambrosia_artemisiifolia = { "[Amb'a'1'U]" } pri_anti_factor_xa_unit = { "[anti'Xa'U]" } @@ -1063,7 +1062,6 @@ sec_atom = { | sec_watt } - sec_meter_per_square_seconds_per_square_root_of_hertz = { "[M/S2/HZ^(1/2)]" } sec_allergen_unit_for_ambrosia_artemisiifolia = { "[AMB'A'1'U]" } sec_anti_factor_xa_unit = { "[ANTI'XA'U]" } diff --git a/atom_generator/Cargo.toml b/atom_generator/Cargo.toml index 25e34435..874a72c5 100644 --- a/atom_generator/Cargo.toml +++ b/atom_generator/Cargo.toml @@ -10,6 +10,11 @@ handlebars = "4.0" heck = "0.4" lazy_static.workspace = true log = "0.4" +maplit = "1.0" +prettyplease = "0.2" +proc-macro2 = "1.0" +quote = "1.0" regex = "1.0" serde.workspace = true +syn = "2.0" toml = "0.7" diff --git a/atom_generator/src/from_toml.rs b/atom_generator/src/from_toml.rs index 8ad87fe5..99d6a1ba 100644 --- a/atom_generator/src/from_toml.rs +++ b/atom_generator/src/from_toml.rs @@ -27,6 +27,8 @@ use crate::{ toml_structs::{TomlAtom, TomlBaseUnit, TomlUnit}, }; use heck::ToUpperCamelCase; +use proc_macro2::TokenStream; +use quote::quote; pub(crate) mod atoms; pub(crate) mod custom_atoms; @@ -40,7 +42,7 @@ fn transform_base_units(atom_list_base_units: &[TomlBaseUnit]) -> Vec type_name: bu.type_name(), classification: "Si".to_string(), dim: Some(bu.dim.clone()), - definition_signature: "Ok(Definition::default())".to_string(), + definition_signature: quote! { Ok(Definition::default()) }, primary_code: bu.primary_code.clone(), print_symbol: Some(bu.print_symbol.clone()), property: bu.property.clone(), @@ -66,25 +68,27 @@ fn transform_units(atom_list_units: &[TomlUnit]) -> Vec { }; let function = u.definition.function.clone().unwrap(); - let function_set_string = build_function_set_string(&function_set); + let function_set_ts = build_function_set_ts(function_set); - format!( - "Definition::new({:?}, \"{}\", Some({}))", - function.value, function.unit, function_set_string - ) + let value = function.value; + let unit = &function.unit; + + quote! { + Definition::new(#value, #unit, Some(#function_set_ts)) + } } else if &u.primary_code == "[pi]" { - format!( - "Definition::new(::std::f64::consts::PI, \"{}\", None)", - u.definition.unit.clone() - ) + let unit = &u.definition.unit; + + quote! { + Definition::new(::std::f64::consts::PI, #unit, None) + } } else if u.definition.value.eq(&1.0_f64) && &u.definition.unit == "1" { - "Ok(Definition::default())".to_string() + quote! { Ok(Definition::default()) } } else { - format!( - "Definition::new({:?}, \"{}\", None)", - u.definition.value, - u.definition.unit.clone() - ) + let value = u.definition.value; + let unit = &u.definition.unit; + + quote! { Definition::new(#value, #unit, None) } }; RustAtom { @@ -108,27 +112,52 @@ fn transform_units(atom_list_units: &[TomlUnit]) -> Vec { /// Determines which function to generate for converting *from* the unit with /// `primary_code` to its base unit. /// -fn build_scalar_function(primary_code: &str) -> String { +fn build_scalar_function(primary_code: &str) -> TokenStream { match primary_code { - "B" | "B[W]" | "B[kW]" => "|value: f64| 10_f64.powf(value)", - "B[SPL]" | "B[V]" | "B[mV]" | "B[uV]" | "B[10.nV]" => { - "|value: f64| 10_f64.powf(value / 2.0)" - } - "bit_s" => "|value: f64| value.exp2()", - "Cel" => "|value: f64| value + 273.15", - "Np" => "|value: f64| value.exp()", - "%[slope]" | "[p'diop]" => "|value: f64| value.tan() * 100.0", - "[hp'_X]" => "|value: f64| 10_f64.powf(-value)", - "[hp'_C]" => "|value: f64| 100_f64.powf(-value)", - "[hp'_M]" => "|value: f64| 1_000_f64.powf(-value)", - "[hp'_Q]" => "|value: f64| 50_000_f64.powf(-value)", - "[m/s2/Hz^(1/2)]" => "|value: f64| value * value", - "[pH]" => "|value: f64| -value.log10()", - "[degF]" => "|value: f64| 5.0 / 9.0 * (value + 459.67)", - "[degRe]" => "|value: f64| (value / 0.8) + 273.15", + "B" | "B[W]" | "B[kW]" => quote! { + |value: f64| 10_f64.powf(value) + }, + "B[SPL]" | "B[V]" | "B[mV]" | "B[uV]" | "B[10.nV]" => quote! { + |value: f64| 10_f64.powf(value / 2.0) + }, + "bit_s" => quote! { + f64::exp2 + }, + "Cel" => quote! { + |value: f64| value + 273.15 + }, + "Np" => quote! { + f64::exp + }, + "%[slope]" | "[p'diop]" => quote! { + |value: f64| value.tan() * 100.0 + }, + "[hp'_X]" => quote! { + |value: f64| 10_f64.powf(-value) + }, + "[hp'_C]" => quote! { + |value: f64| 100_f64.powf(-value) + }, + "[hp'_M]" => quote! { + |value: f64| 1_000_f64.powf(-value) + }, + "[hp'_Q]" => quote! { + |value: f64| 50_000_f64.powf(-value) + }, + "[m/s2/Hz^(1/2)]" => quote! { + |value: f64| value * value + }, + "[pH]" => quote! { + |value: f64| -value.log10() + }, + "[degF]" => quote! { + |value: f64| 5.0 / 9.0 * (value + 459.67) + }, + "[degRe]" => quote! { + |value: f64| (value / 0.8) + 273.15 + }, _ => panic!("Unknown primary code on special unit: {primary_code}"), } - .to_string() } /// Determines which function to generate for converting *to* the unit with @@ -138,30 +167,59 @@ fn build_scalar_function(primary_code: &str) -> String { /// manually updated here, and support for custom special units does not yet /// exist. /// -fn build_magnitude_function(primary_code: &str) -> String { +fn build_magnitude_function(primary_code: &str) -> TokenStream { match primary_code { - "B" | "B[W]" | "B[kW]" => "|value: f64| value.log10()", - "B[SPL]" | "B[V]" | "B[mV]" | "B[uV]" | "B[10.nV]" => "|value: f64| 2.0 * value.log10()", - "bit_s" => "|value: f64| value.log2()", - "Cel" => "|value: f64| value - 273.15", - "Np" => "|value: f64| value.ln()", - "%[slope]" | "[p'diop]" => "|value: f64| (value / 100.0).atan()", - "[hp'_X]" => "|value: f64| -value.log10()", - "[hp'_C]" => "|value: f64| -value.ln() / 100_f64.ln()", - "[hp'_M]" => "|value: f64| -value.ln() / 1_000_f64.ln()", - "[hp'_Q]" => "|value: f64| -value.ln() / 50_000_f64.ln()", - "[m/s2/Hz^(1/2)]" => "|value: f64| value.sqrt()", - "[pH]" => "|value: f64| 10.0_f64.powf(-value)", - "[degF]" => "|value: f64| 9.0 * value / 5.0 - 459.67", - "[degRe]" => "|value: f64| (value - 273.15) * 0.8", + "B" | "B[W]" | "B[kW]" => quote! { + f64::log10 + }, + "B[SPL]" | "B[V]" | "B[mV]" | "B[uV]" | "B[10.nV]" => quote! { + |value: f64| 2.0 * value.log10() + }, + "bit_s" => quote! { + f64::log2 + }, + "Cel" => quote! { + |value: f64| value - 273.15 + }, + "Np" => quote! { + f64::ln + }, + "%[slope]" | "[p'diop]" => quote! { + |value: f64| (value / 100.0).atan() + }, + "[hp'_X]" => quote! { + |value: f64| -value.log10() + }, + "[hp'_C]" => quote! { + |value: f64| -value.ln() / 100_f64.ln() + }, + "[hp'_M]" => quote! { + |value: f64| -value.ln() / 1_000_f64.ln() + }, + "[hp'_Q]" => quote! { + |value: f64| -value.ln() / 50_000_f64.ln() + }, + "[m/s2/Hz^(1/2)]" => quote! { + f64::sqrt + }, + "[pH]" => quote! { + |value: f64| 10.0_f64.powf(-value) + }, + "[degF]" => quote! { + |value: f64| 9.0 * value / 5.0 - 459.67 + }, + "[degRe]" => quote! { + |value: f64| (value - 273.15) * 0.8 + }, _ => panic!("Unknown primary code on special unit: {primary_code}"), } - .to_string() } -fn build_function_set_string(rust_function_set: &RustFunctionSet) -> String { - format!( - "FunctionSet {{ convert_from: {}, convert_to: {} }}", - rust_function_set.convert_from, rust_function_set.convert_to - ) +fn build_function_set_ts(rust_function_set: RustFunctionSet) -> TokenStream { + let from = rust_function_set.convert_from; + let to = rust_function_set.convert_to; + + quote! { + FunctionSet { convert_from: #from, convert_to: #to }, + } } diff --git a/atom_generator/src/from_toml/atoms.rs b/atom_generator/src/from_toml/atoms.rs index 22336e6e..4025bb64 100644 --- a/atom_generator/src/from_toml/atoms.rs +++ b/atom_generator/src/from_toml/atoms.rs @@ -1,4 +1,4 @@ -use crate::{rust_structs::RustAtomList, toml_structs::TomlAtomList}; +use crate::{rust_structs::rust_atom_list::RustAtomList, toml_structs::TomlAtomList}; use std::str::FromStr; static ATOMS_FILE: &str = include_str!("../../Atoms.toml"); diff --git a/atom_generator/src/from_toml/custom_atoms.rs b/atom_generator/src/from_toml/custom_atoms.rs index 40609164..aca8918e 100644 --- a/atom_generator/src/from_toml/custom_atoms.rs +++ b/atom_generator/src/from_toml/custom_atoms.rs @@ -2,7 +2,7 @@ use std::{env, fs::File, io::Read, path::Path, str::FromStr}; use log::debug; -use crate::{rust_structs::RustAtomList, toml_structs::TomlCustomAtomList}; +use crate::{rust_structs::rust_atom_list::RustAtomList, toml_structs::TomlCustomAtomList}; static CUSTOM_ATOMS_FILE_NAME: &str = "CustomAtoms.toml"; diff --git a/atom_generator/src/generator.rs b/atom_generator/src/generator.rs index b1a68040..e42ee007 100644 --- a/atom_generator/src/generator.rs +++ b/atom_generator/src/generator.rs @@ -9,19 +9,29 @@ pub(self) mod atom; pub(self) mod classification; pub(self) mod handlebars; -pub(self) mod mapper; pub(self) mod property; pub(self) mod symbol_grammar; +use proc_macro2::TokenStream; + pub(self) use self::handlebars::HANDLEBARS; use crate::rust_structs::RustAtomList; use std::{ fs::File, - io::Write, + io::{self, Write}, path::{Path, PathBuf}, + process::Command, }; +pub(self) const BANNER: &str = + "//----------------------------------------------------------------------------- +// DO NOT EDIT THIS FILE! +// This is generated by wise_units-atom_generator. +//----------------------------------------------------------------------------- + +"; + /// Main function for generating all files that need to be generated from a /// `RustAtomList`. /// @@ -30,37 +40,30 @@ pub(crate) fn generate_files(rust_atom_list: &RustAtomList) { generate_property_file(rust_atom_list); generate_atom_file(rust_atom_list); generate_symbol_grammar_file(rust_atom_list); - generate_mapper_file(rust_atom_list); } fn generate_classification_file(rust_atom_list: &RustAtomList) { let file_body = self::classification::generate_file_body(rust_atom_list); let file_path = build_file_path("parser/classification.rs"); - write_project_file(&file_path, &file_body); + write_project_file(&file_path, &file_body, true); } fn generate_property_file(rust_atom_list: &RustAtomList) { let file_body = self::property::generate_file_body(rust_atom_list); let file_path = build_file_path("parser/property.rs"); - write_project_file(&file_path, &file_body); + write_project_file(&file_path, &file_body, true); } fn generate_atom_file(rust_atom_list: &RustAtomList) { let file_body = self::atom::generate_file_body(rust_atom_list); let file_path = build_file_path("parser/atom.rs"); - write_project_file(&file_path, &file_body); + write_project_file(&file_path, &file_body, true); } fn generate_symbol_grammar_file(rust_atom_list: &RustAtomList) { let file_body = self::symbol_grammar::generate_file_body(rust_atom_list); let file_path = build_file_path("parser/symbols/symbol.pest"); - write_project_file(&file_path, &file_body); -} - -fn generate_mapper_file(rust_atom_list: &RustAtomList) { - let file_body = self::mapper::generate_file_body(rust_atom_list); - let file_path = build_file_path("parser/symbols/mapper.rs"); - write_project_file(&file_path, &file_body); + write_project_file(&file_path, &file_body, false); } fn build_file_path(file_name: &str) -> PathBuf { @@ -69,9 +72,33 @@ fn build_file_path(file_name: &str) -> PathBuf { Path::new(&dest_dir).join(file_name) } -fn write_project_file(file_path: &Path, file_body: &str) { +fn write_project_file(file_path: &Path, file_body: &str, do_format: bool) { let mut f = File::create(file_path).unwrap(); f.write_all(file_body.as_bytes()) .expect("Problem writing the file"); + + if do_format { + // Now call `rustfmt` on it. + let output = Command::new("rustfmt") + .arg(file_path) + .output() + .unwrap_or_else(|_| panic!("`rustfmt` failed on file {}", file_path.display())); + + io::stderr().write_all(&output.stderr).unwrap(); + } +} + +pub(self) fn pretty_format(token_stream: &TokenStream) -> String { + let token_string = token_stream.to_string(); + + // Run the output through `prettyplease`. This should catch some syntactical mess-ups. + // + let syn_file = syn::parse_file(&token_string).unwrap(); + let mut code = prettyplease::unparse(&syn_file); + + // Insert the "don't edit me" banner. + code.insert_str(0, BANNER); + + code } diff --git a/atom_generator/src/generator/atom.rs b/atom_generator/src/generator/atom.rs index b0bd2939..3ee3ae8d 100644 --- a/atom_generator/src/generator/atom.rs +++ b/atom_generator/src/generator/atom.rs @@ -1,10 +1,87 @@ -use crate::rust_structs::RustAtomList; +use quote::quote; -pub(super) static HBS_TEMPLATE: &str = include_str!("../templates/atom.rs.hbs"); +use crate::rust_structs::rust_atom_list::RustAtomList; /// Uses the associated handlebars template to generate the Rust code for the /// `Atom` enum. /// pub(super) fn generate_file_body(atom_list: &RustAtomList) -> String { - super::HANDLEBARS.render("atom", atom_list).unwrap() + let atom_enum = atom_list.atom_enum(); + let definition_method = atom_list.definition_method(); + let property_method = atom_list.property_method(); + + let classification_method = atom_list.classification_method(); + let names_method = atom_list.names_method(); + let primary_code_method = atom_list.primary_code_method(); + let print_symbol_method = atom_list.print_symbol_method(); + let secondary_code_method = atom_list.secondary_code_method(); + + let is_arbitrary_method = atom_list.is_arbitrary_method(); + let is_special_method = atom_list.is_special_method(); + let is_metric_method = atom_list.is_metric_method(); + + let tokens = quote! { + mod composable; + mod display; + mod hash; + mod partial_eq; + mod reducible; + + use crate::{ + is_compatible_with::DefaultCompatibility, + parser::{ + definition::Definition, function_set::FunctionSet, Classification, Property, UcumSymbol, + }, + reducible::Reducible, + UcumUnit, Unit, + }; + + #atom_enum + + impl Atom { + #definition_method + + #property_method + } + + impl UcumSymbol for Atom { + #classification_method + + #names_method + + #primary_code_method + + #print_symbol_method + + #secondary_code_method + + fn definition_value(&self) -> f64 { + self.definition().value() + } + + fn definition_unit(&self) -> Unit { + Unit::new(self.definition().terms().clone()) + } + } + + impl UcumUnit for Atom { + fn scalar(&self) -> f64 { + self.reduce_value(1.0) + } + + fn magnitude(&self) -> f64 { + self.calculate_magnitude(self.scalar()) + } + + #is_arbitrary_method + + #is_special_method + + #is_metric_method + } + + impl DefaultCompatibility for Atom {} + }; + + super::pretty_format(&tokens) } diff --git a/atom_generator/src/generator/classification.rs b/atom_generator/src/generator/classification.rs index 69cdb156..f901ee58 100644 --- a/atom_generator/src/generator/classification.rs +++ b/atom_generator/src/generator/classification.rs @@ -1,14 +1,96 @@ -use crate::rust_structs::{RustAtomList, RustClassificationList}; +use quote::{format_ident, quote}; -pub(super) static HBS_TEMPLATE: &str = include_str!("../templates/classification.rs.hbs"); +use crate::rust_structs::{RustAtomList, RustClassificationList}; /// Uses the associated handlebars template to generate the Rust code for the /// `Classification` enum. /// pub(super) fn generate_file_body(atom_list: &RustAtomList) -> String { let classification_list = RustClassificationList::from(atom_list); + let variants: Vec<_> = classification_list + .type_names + .iter() + .map(|tn| format_ident!("{tn}")) + .collect(); + + let tokens = quote! { + /// Classification signifies the system of units from which a unit is defined + /// in. + /// + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum Classification { + #(#variants),* + } + + impl Default for Classification { + fn default() -> Self { + Self::Si + } + } + + impl std::fmt::Display for Classification { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let s = match self { + Self::Apoth => "Apoth", + Self::Avoirdupois => "Avoirdupois", + Self::BritLength => "BritLength", + Self::BritVolumes => "BritVolumes", + Self::Cgs => "Cgs", + Self::Chemical => "Chemical", + Self::Clinical => "Clinical", + Self::Const => "Const", + Self::Dimless => "Dimless", + Self::Heat => "Heat", + Self::Infotech => "Infotech", + Self::Intcust => "Intcust", + Self::Iso1000 => "Iso1000", + Self::Levels => "Levels", + Self::Misc => "Misc", + Self::Si => "Si", + Self::Troy => "Troy", + Self::Typeset => "Typeset", + Self::UsLengths => "UsLengths", + Self::UsVolumes => "UsVolumes", + }; + + f.write_str(s) + } + } + }; + + super::pretty_format(&tokens) +} + +#[cfg(test)] +mod tests { + use proc_macro2::TokenStream; + + use crate::rust_structs::RustAtom; + + use super::*; + + #[test] + fn render_test() { + let rust_atom_list = RustAtomList { + atoms: vec![RustAtom { + type_name: String::new(), + classification: "CoolBeans".to_string(), + dim: None, + definition_signature: TokenStream::new(), + primary_code: String::new(), + print_symbol: None, + property: String::new(), + names: vec![], + secondary_code: None, + is_arbitrary: false, + is_metric: false, + is_special: false, + }], + }; + + let output = generate_file_body(&rust_atom_list); - super::HANDLEBARS - .render("classification", &classification_list) - .unwrap() + assert_eq!(&output[0..4], "//--"); + assert_eq!(output.lines().count(), 44); + } } diff --git a/atom_generator/src/generator/handlebars.rs b/atom_generator/src/generator/handlebars.rs index 25815490..86e88437 100644 --- a/atom_generator/src/generator/handlebars.rs +++ b/atom_generator/src/generator/handlebars.rs @@ -2,7 +2,7 @@ use handlebars::{handlebars_helper, Handlebars}; use heck::ToUpperCamelCase; use lazy_static::lazy_static; -use super::{atom, classification, mapper, property, symbol_grammar}; +use super::symbol_grammar; handlebars_helper!(camel_case_helper: |word: str| word.to_upper_camel_case()); @@ -12,21 +12,9 @@ lazy_static! { handlebars.register_escape_fn(::handlebars::no_escape); handlebars.register_helper("camelCase", Box::new(camel_case_helper)); - handlebars - .register_template_string("atom", atom::HBS_TEMPLATE) - .unwrap(); - handlebars - .register_template_string("classification", classification::HBS_TEMPLATE) - .unwrap(); - handlebars - .register_template_string("property", property::HBS_TEMPLATE) - .unwrap(); handlebars .register_template_string("symbol_grammar", symbol_grammar::HBS_TEMPLATE) .unwrap(); - handlebars - .register_template_string("mapper", mapper::HBS_TEMPLATE) - .unwrap(); handlebars }; diff --git a/atom_generator/src/generator/mapper.rs b/atom_generator/src/generator/mapper.rs deleted file mode 100644 index 53ef6727..00000000 --- a/atom_generator/src/generator/mapper.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::rust_structs::{RustAtomList, RustMapperList}; - -pub(super) static HBS_TEMPLATE: &str = include_str!("../templates/mapper.rs.hbs"); - -/// Uses the associated handlebars template to generate the Rust code for the -/// `mapper` module. -/// -pub(super) fn generate_file_body(atom_list: &RustAtomList) -> String { - let mapper_list = RustMapperList::from(atom_list); - - super::HANDLEBARS.render("mapper", &mapper_list).unwrap() -} diff --git a/atom_generator/src/generator/property.rs b/atom_generator/src/generator/property.rs index bcfd756a..742078ff 100644 --- a/atom_generator/src/generator/property.rs +++ b/atom_generator/src/generator/property.rs @@ -1,14 +1,76 @@ -use crate::rust_structs::{RustAtomList, RustPropertyList}; +use quote::quote; -pub(super) static HBS_TEMPLATE: &str = include_str!("../templates/property.rs.hbs"); +use crate::rust_structs::{RustAtomList, RustPropertyList}; /// Uses the associated handlebars template to generate the Rust code for the /// `Property` enum. /// pub(super) fn generate_file_body(atom_list: &RustAtomList) -> String { let property_list = RustPropertyList::from(atom_list); + let variants = property_list.variants(); + let atoms = property_list.atoms(); + let display = property_list.display(); + + let tokens = quote! { + use crate::parser::Atom; + use std::fmt; + + /// Property categorizes the unit by use. Not much mention of it in the UCUM + /// HTML spec, but is used throughout the + /// [XML description](http://unitsofmeasure.org/ucum-essence.xml). + /// + #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] + pub enum Property { + #(#variants),* + } + + impl Property { + /// All `Atom`s that match the `Property` variant. + /// + /// ``` + /// extern crate wise_units; + /// use wise_units::{Atom, Property}; + /// + /// assert_eq!(Property::Acidity.atoms(), vec![Atom::PH]); + /// ``` + /// + #[allow(clippy::too_many_lines)] + #[must_use] + pub fn atoms(self) -> Vec { + match self { + #atoms + } + } + } + + impl Default for Property { + fn default() -> Self { + Self::Unclassified + } + } + + impl fmt::Display for Property { + #[allow(clippy::too_many_lines)] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + let string = match self { + #display + }; + + write!(formatter, "{string}") + } + } + + #[cfg(test)] + mod tests { + use super::*; + + #[test] + fn validate_display() { + let a = format!("{}", Property::Acceleration); + assert_eq!(&a, "Acceleration"); + } + } + }; - super::HANDLEBARS - .render("property", &property_list) - .unwrap() + super::pretty_format(&tokens) } diff --git a/atom_generator/src/rust_structs.rs b/atom_generator/src/rust_structs.rs index aeaa277d..e4fdea83 100644 --- a/atom_generator/src/rust_structs.rs +++ b/atom_generator/src/rust_structs.rs @@ -1,25 +1,13 @@ pub(crate) mod pest_symbol_list; -pub(crate) mod rust_atom; +pub(crate) mod rust_atom_list; pub(crate) mod rust_classification_list; pub(crate) mod rust_function_set; -pub(crate) mod rust_mapper_list; pub(crate) mod rust_property_list; pub(crate) use self::{ - pest_symbol_list::PestSymbolList, rust_atom::RustAtom, - rust_classification_list::RustClassificationList, rust_function_set::RustFunctionSet, - rust_mapper_list::RustMapperList, rust_property_list::RustPropertyList, + pest_symbol_list::PestSymbolList, + rust_atom_list::{RustAtom, RustAtomList}, + rust_classification_list::RustClassificationList, + rust_function_set::RustFunctionSet, + rust_property_list::RustPropertyList, }; - -use heck::ToSnakeCase; - -#[derive(Debug, serde::Serialize)] -pub(crate) struct RustAtomList { - pub(crate) atoms: Vec, -} - -pub(self) fn build_pest_rule_name(prefix: &str, symbol: &str) -> String { - let symbol = symbol.to_snake_case(); - - format!("{prefix}_{symbol}") -} diff --git a/atom_generator/src/rust_structs/pest_symbol_list.rs b/atom_generator/src/rust_structs/pest_symbol_list.rs index 7b97ce7b..f2c992c3 100644 --- a/atom_generator/src/rust_structs/pest_symbol_list.rs +++ b/atom_generator/src/rust_structs/pest_symbol_list.rs @@ -1,6 +1,8 @@ +use heck::ToSnakeCase; + use serde::Serialize; -use super::RustAtomList; +use super::rust_atom_list::RustAtomList; #[derive(Debug, Serialize)] pub(crate) struct PestSymbolList { @@ -17,7 +19,7 @@ impl<'a> From<&'a RustAtomList> for PestSymbolList { let s = a.type_name.clone(); let code = a.primary_code.clone(); - PestSymbol::new(super::build_pest_rule_name("pri", &s), code) + PestSymbol::new(build_pest_rule_name("pri", &s), code) }) .collect::>(); @@ -31,7 +33,7 @@ impl<'a> From<&'a RustAtomList> for PestSymbolList { let code = secondary_code.clone(); let s = atom.type_name.clone(); - PestSymbol::new(super::build_pest_rule_name("sec", &s), code) + PestSymbol::new(build_pest_rule_name("sec", &s), code) }) }) .collect::>(); @@ -51,6 +53,11 @@ fn sort_symbols(symbols: &mut [PestSymbol]) { symbols.sort_by(|a, b| b.code.len().cmp(&a.code.len())); } +fn build_pest_rule_name(prefix: &str, symbol: &str) -> String { + let symbol = symbol.to_snake_case(); + + format!("{prefix}_{symbol}") +} #[derive(Debug, Serialize)] pub(crate) struct PestSymbol { pub(crate) rule_name: String, diff --git a/atom_generator/src/rust_structs/rust_atom.rs b/atom_generator/src/rust_structs/rust_atom.rs deleted file mode 100644 index ca2fc3e7..00000000 --- a/atom_generator/src/rust_structs/rust_atom.rs +++ /dev/null @@ -1,15 +0,0 @@ -#[derive(Debug, serde::Serialize)] -pub(crate) struct RustAtom { - pub(crate) type_name: String, - pub(crate) classification: String, - pub(crate) dim: Option, - pub(crate) definition_signature: String, - pub(crate) primary_code: String, - pub(crate) print_symbol: Option, - pub(crate) property: String, - pub(crate) names: Vec, - pub(crate) secondary_code: Option, - pub(crate) is_arbitrary: bool, - pub(crate) is_metric: bool, - pub(crate) is_special: bool, -} diff --git a/atom_generator/src/rust_structs/rust_atom_list.rs b/atom_generator/src/rust_structs/rust_atom_list.rs new file mode 100644 index 00000000..5b05f447 --- /dev/null +++ b/atom_generator/src/rust_structs/rust_atom_list.rs @@ -0,0 +1,251 @@ +use std::collections::BTreeSet; + +use heck::ToUpperCamelCase; +use proc_macro2::TokenStream; +use quote::{format_ident, quote}; + +#[derive(Debug)] +pub(crate) struct RustAtomList { + pub(crate) atoms: Vec, +} + +impl RustAtomList { + pub(crate) fn atom_enum(&self) -> TokenStream { + let variants = self + .atoms + .iter() + .map(|atom| format_ident!("{}", &atom.type_name)); + + quote! { + #[derive(Clone, Copy, Debug, Eq, PartialOrd, Ord)] + pub enum Atom { + #(#variants),* + } + } + } + + /// Emits the Rust code for defining `Atom::definition()`. + /// + pub(crate) fn definition_method(&self) -> TokenStream { + let definitions = self.atoms.iter().map(RustAtom::definition_ts); + + quote! { + pub(crate) fn definition(self) -> Definition { + let result = match self { + #(#definitions),* + }; + + result.expect("BUG! Bad Atom -> Definition mapping!") + } + } + } + + /// Emits the Rust code for defining `Atom::property()`. + /// + pub(crate) fn property_method(&self) -> TokenStream { + let properties = self.atoms.iter().map(RustAtom::property_ts); + + quote! { + #[must_use] + pub const fn property(self) -> Property { + match self { + #(#properties),* + } + } + } + } + + pub(crate) fn classification_method(&self) -> TokenStream { + let classifications = self.atoms.iter().map(RustAtom::classification_ts); + + quote! { + fn classification(&self) -> Classification { + match *self { + #(#classifications),* + } + } + } + } + + pub(crate) fn names_method(&self) -> TokenStream { + let names = self.atoms.iter().map(RustAtom::names_ts); + + quote! { + fn names(&self) -> Vec<&'static str> { + match *self { + #(#names),* + } + } + } + } + + pub(crate) fn primary_code_method(&self) -> TokenStream { + let primary_codes = self.atoms.iter().map(RustAtom::primary_code_ts); + + quote! { + fn primary_code(&self) -> &'static str { + match *self { + #(#primary_codes),* + } + } + } + } + + pub(crate) fn print_symbol_method(&self) -> TokenStream { + let print_symbols = self.atoms.iter().filter_map(RustAtom::print_symbol_ts); + + quote! { + fn print_symbol(&self) -> Option<&'static str> { + match *self { + #(#print_symbols),*, + _ => None, + } + } + } + } + + pub(crate) fn secondary_code_method(&self) -> TokenStream { + let secondary_codes = self.atoms.iter().map(RustAtom::secondary_code_ts); + + quote! { + fn secondary_code(&self) -> Option<&'static str> { + match *self { + #(#secondary_codes),*, + } + } + } + } + + pub(crate) fn is_arbitrary_method(&self) -> TokenStream { + let true_variants: BTreeSet<_> = self + .atoms + .iter() + .filter(|atom| atom.is_arbitrary) + .map(|atom| format_ident!("{}", atom.type_name)) + .collect(); + + let true_parts = true_variants.into_iter().map(|atom_variant| { + quote! { Self::#atom_variant } + }); + + quote! { + fn is_arbitrary(&self) -> bool { + matches!(*self, #(#true_parts) |*) + } + } + } + + pub(crate) fn is_special_method(&self) -> TokenStream { + let true_variants: BTreeSet<_> = self + .atoms + .iter() + .filter(|atom| atom.is_special) + .map(|atom| format_ident!("{}", atom.type_name)) + .collect(); + + let true_parts = true_variants.into_iter().map(|atom_variant| { + quote! { Self::#atom_variant } + }); + + quote! { + fn is_special(&self) -> bool { + matches!(*self, #(#true_parts) |*) + } + } + } + + pub(crate) fn is_metric_method(&self) -> TokenStream { + let true_variants: BTreeSet<_> = self + .atoms + .iter() + .filter(|atom| atom.is_metric) + .map(|atom| format_ident!("{}", atom.type_name)) + .collect(); + + let true_parts = true_variants.into_iter().map(|atom_variant| { + quote! { Self::#atom_variant } + }); + + quote! { + fn is_metric(&self) -> bool { + matches!(*self, #(#true_parts) |*) + } + } + } +} + +#[derive(Debug)] +pub(crate) struct RustAtom { + pub(crate) type_name: String, + pub(crate) classification: String, + pub(crate) dim: Option, + pub(crate) definition_signature: TokenStream, + pub(crate) primary_code: String, + pub(crate) print_symbol: Option, + pub(crate) property: String, + pub(crate) names: Vec, + pub(crate) secondary_code: Option, + pub(crate) is_arbitrary: bool, + pub(crate) is_metric: bool, + pub(crate) is_special: bool, +} + +impl RustAtom { + pub(crate) fn definition_ts(&self) -> TokenStream { + let atom_variant = format_ident!("{}", self.type_name); + let rhs = &self.definition_signature; + + quote!(Self::#atom_variant => #rhs ) + } + + pub(crate) fn property_ts(&self) -> TokenStream { + let atom_variant = format_ident!("{}", self.type_name); + let property_variant = format_ident!("{}", self.property.to_upper_camel_case()); + + quote! { Self::#atom_variant => Property::#property_variant } + } + + pub(crate) fn classification_ts(&self) -> TokenStream { + let atom_variant = format_ident!("{}", self.type_name); + let classification_variant = format_ident!("{}", self.classification.to_upper_camel_case()); + + quote! { Self::#atom_variant => Classification::#classification_variant } + } + + pub(crate) fn names_ts(&self) -> TokenStream { + let atom_variant = format_ident!("{}", self.type_name); + let names = &self.names; + + quote! { + Self::#atom_variant => vec![#(#names),*] + } + } + + pub(crate) fn primary_code_ts(&self) -> TokenStream { + let atom_variant = format_ident!("{}", self.type_name); + let primary_code = &self.primary_code; + + quote! { Self::#atom_variant => #primary_code } + } + + pub(crate) fn print_symbol_ts(&self) -> Option { + let print_symbol = self.print_symbol.as_ref()?; + + let atom_variant = format_ident!("{}", self.type_name); + + Some(quote! { Self::#atom_variant => Some(#print_symbol) }) + } + + pub(crate) fn secondary_code_ts(&self) -> TokenStream { + let atom_variant = format_ident!("{}", self.type_name); + + match self.secondary_code.as_ref() { + Some(secondary_code) => { + quote! { Self::#atom_variant => Some(#secondary_code) } + } + None => { + quote! { Self::#atom_variant => None } + } + } + } +} diff --git a/atom_generator/src/rust_structs/rust_function_set.rs b/atom_generator/src/rust_structs/rust_function_set.rs index 2398ef64..2e60849b 100644 --- a/atom_generator/src/rust_structs/rust_function_set.rs +++ b/atom_generator/src/rust_structs/rust_function_set.rs @@ -1,8 +1,12 @@ -#[derive(Debug, serde::Serialize)] +use proc_macro2::TokenStream; + +#[derive(Debug)] pub(crate) struct RustFunctionSet { - // AKA "calculate_magnitude" - pub(crate) convert_from: String, + /// The function to use to convert from a unit to this one. + /// + pub(crate) convert_from: TokenStream, - // AKA "reduce_value" - pub(crate) convert_to: String, + /// The function to use to convert to a unit from this one. + /// + pub(crate) convert_to: TokenStream, } diff --git a/atom_generator/src/rust_structs/rust_mapper_list.rs b/atom_generator/src/rust_structs/rust_mapper_list.rs deleted file mode 100644 index 64392b82..00000000 --- a/atom_generator/src/rust_structs/rust_mapper_list.rs +++ /dev/null @@ -1,42 +0,0 @@ -use serde::Serialize; - -use super::RustAtomList; -use std::collections::HashMap; - -type AtomTypeName = String; - -#[derive(Debug, Serialize)] -pub(crate) struct RustMapperList { - pub(crate) mappings: HashMap, -} - -impl<'a> From<&'a RustAtomList> for RustMapperList { - fn from(atom_list: &'a RustAtomList) -> Self { - let mut mappings: HashMap = HashMap::new(); - - for rust_unit in &atom_list.atoms { - let key = rust_unit.type_name.clone(); - let primary_rule_name = super::build_pest_rule_name("pri", &key); - - let secondary_rule_name = rust_unit - .secondary_code - .as_ref() - .map(|_sc| super::build_pest_rule_name("sec", &key)); - - let mapping_value = RustMappingValue { - primary_rule_name, - secondary_rule_name, - }; - - let _ = mappings.entry(key).or_insert(mapping_value); - } - - Self { mappings } - } -} - -#[derive(Debug, Serialize)] -pub(crate) struct RustMappingValue { - pub(crate) primary_rule_name: String, - pub(crate) secondary_rule_name: Option, -} diff --git a/atom_generator/src/rust_structs/rust_property_list.rs b/atom_generator/src/rust_structs/rust_property_list.rs index 107faa04..1144e5ca 100644 --- a/atom_generator/src/rust_structs/rust_property_list.rs +++ b/atom_generator/src/rust_structs/rust_property_list.rs @@ -1,33 +1,85 @@ -use super::RustAtomList; +use std::collections::{BTreeMap, BTreeSet}; + use heck::ToUpperCamelCase; +use maplit::btreeset; +use proc_macro2::{Ident, TokenStream}; +use quote::{format_ident, quote}; use serde::Serialize; -use std::collections::HashMap; + +use super::RustAtomList; type PropertyTypeName = String; #[derive(Debug, Serialize)] pub(crate) struct RustPropertyList { - pub(crate) properties: HashMap, + pub(crate) properties: BTreeMap, +} + +impl RustPropertyList { + pub(crate) fn variants(&self) -> impl Iterator + '_ { + self.properties.keys().map(|key| format_ident!("{key}")) + } + + pub(crate) fn atoms(&self) -> TokenStream { + self.properties + .iter() + .map(|(k, v)| { + let variant = format_ident!("{k}"); + let atoms = v.atoms(); + + quote! { + Self::#variant => vec![ + #atoms + ], + } + }) + .collect() + } + + pub(crate) fn display(&self) -> TokenStream { + self.properties + .keys() + .map(|key| { + let variant = format_ident!("{key}"); + quote! { Self::#variant => #key, } + }) + .collect() + } } #[derive(Debug, Serialize)] pub(crate) struct RustProperty { - pub(crate) atom_type_names: Vec, + // Using BTreeSet here just for sorting. + pub(crate) atom_type_names: BTreeSet, pub(crate) description: String, } +impl RustProperty { + fn atoms(&self) -> TokenStream { + self.atom_type_names + .iter() + .map(|name| { + let name = format_ident!("{name}"); + quote! { Atom::#name, } + }) + .collect() + } +} + impl<'a> From<&'a RustAtomList> for RustPropertyList { fn from(atom_list: &'a RustAtomList) -> Self { - let mut properties: HashMap = HashMap::new(); + let mut properties: BTreeMap = BTreeMap::new(); for atom in &atom_list.atoms { let key = atom.property.to_upper_camel_case(); let _ = properties .entry(key) - .and_modify(|entry| entry.atom_type_names.push(atom.type_name.clone())) + .and_modify(|entry| { + let _ = entry.atom_type_names.insert(atom.type_name.clone()); + }) .or_insert_with(|| RustProperty { - atom_type_names: vec![atom.type_name.clone()], + atom_type_names: btreeset![atom.type_name.clone()], description: atom.property.clone(), }); } diff --git a/atom_generator/src/templates/atom.rs.hbs b/atom_generator/src/templates/atom.rs.hbs deleted file mode 100644 index fb727761..00000000 --- a/atom_generator/src/templates/atom.rs.hbs +++ /dev/null @@ -1,178 +0,0 @@ -//----------------------------------------------------------------------------- -// DO NOT EDIT THIS FILE! -// This is generated by wise_units-atom_generator. -//----------------------------------------------------------------------------- - -use crate::{ - is_compatible_with::{DefaultCompatibility, IsCompatibleWith}, - parser::{ - definition::Definition, function_set::FunctionSet, Classification, Composable, Composition, - Dimension, Property, UcumSymbol, - }, - reducible::Reducible, - UcumUnit, Unit, -}; -use std::fmt; - -#[derive(Clone, Copy, Debug, Eq, PartialOrd, Ord)] -pub enum Atom { - {{~ #each atoms }} - {{ type_name }},{{ /each }} -} - -impl Atom { - pub(crate) fn definition(self) -> Definition { - let result = match self { - {{~ #each atoms }} - Self::{{ type_name }} => {{ definition_signature }},{{ /each }} - }; - - result.expect("BUG! Bad Atom -> Definition mapping!") - } - - #[must_use] - pub const fn property(self) -> Property { - match self { - {{~ #each atoms }} - Self::{{ type_name }} => Property::{{ camelCase property }},{{ /each }} - } - } -} - -impl UcumSymbol for Atom { - fn classification(&self) -> Classification { - match *self { - {{~ #each atoms }} - Self::{{ type_name }} => Classification::{{ classification }},{{ /each }} - } - } - - fn names(&self) -> Vec<&'static str> { - match *self { - {{~ #each atoms }} - Self::{{ type_name }} => vec![{{ #each names }}"{{ this }}",{{ /each}}],{{ /each }} - } - } - - fn primary_code(&self) -> &'static str { - match *self { - {{~ #each atoms }} - Self::{{ type_name }} => "{{ primary_code }}",{{ /each }} - } - } - - fn print_symbol(&self) -> Option<&'static str> { - match *self { - {{~ #each atoms }} - {{~ #if print_symbol }} - Self::{{ type_name }} => Some("{{ print_symbol }}"), - {{~ /if}}{{ /each }} - _ => None, - } - } - - fn secondary_code(&self) -> Option<&'static str> { - match *self { - {{~ #each atoms }} - {{~ #if secondary_code }} - Self::{{ type_name }} => Some("{{ secondary_code }}"), - {{~ /if ~}}{{ /each }} - _ => None, - } - } - - fn definition_value(&self) -> f64 { - self.definition().value() - } - - fn definition_unit(&self) -> Unit { - Unit::from(self.definition().terms().clone()) - } -} - -impl UcumUnit for Atom { - fn scalar(&self) -> f64 { - self.reduce_value(1.0) - } - - fn magnitude(&self) -> f64 { - self.calculate_magnitude(self.scalar()) - } - - fn is_arbitrary(&self) -> bool { - match *self { - {{~ #each atoms }} - {{~ #if is_arbitrary }} - Self::{{ type_name }} => true, - {{~ /if}}{{ /each }} - _ => false, - } - } - - fn is_special(&self) -> bool { - match *self { - {{~ #each atoms }} - {{~ #if is_special }} - Self::{{ type_name }} => true, - {{~ /if}}{{ /each }} - _ => false, - } - } - - fn is_metric(&self) -> bool { - match *self { - {{~ #each atoms }} - {{~ #if is_metric }} - Self::{{ type_name }} => true, - {{~ /if}}{{ /each }} - _ => false, - } - } -} - -impl Reducible for Atom { - fn reduce_value(&self, value: f64) -> f64 { - self.definition().reduce_value(value) - } - - fn calculate_magnitude(&self, value: f64) -> f64 { - if self.is_special() { - self.definition().calculate_magnitude(value) - } else { - 1.0 - } - } -} - -impl DefaultCompatibility for Atom {} - -impl Composable for Atom { - fn composition(&self) -> Composition { - match self { - Self::Candela => Composition::new(Dimension::LuminousIntensity, 1), - Self::Coulomb => Composition::new(Dimension::ElectricCharge, 1), - Self::Gram => Composition::new(Dimension::Mass, 1), - Self::Kelvin => Composition::new(Dimension::Temperature, 1), - Self::Meter => Composition::new(Dimension::Length, 1), - Self::Radian => Composition::new(Dimension::PlaneAngle, 1), - Self::Second => Composition::new(Dimension::Time, 1), - _ => self.definition().terms().composition(), - } - } -} - -impl PartialEq for Atom { - fn eq(&self, other: &Self) -> bool { - if !self.is_compatible_with(other) { - return false; - } - - self.scalar() == other.scalar() - } -} - -impl fmt::Display for Atom { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.primary_code()) - } -} diff --git a/atom_generator/src/templates/classification.rs.hbs b/atom_generator/src/templates/classification.rs.hbs deleted file mode 100644 index 135177f9..00000000 --- a/atom_generator/src/templates/classification.rs.hbs +++ /dev/null @@ -1,19 +0,0 @@ -//----------------------------------------------------------------------------- -// DO NOT EDIT THIS FILE! -// This is generated by wise_units-atom_generator. -//----------------------------------------------------------------------------- - -/// Classification signifies the system of units from which a unit is defined -/// in. -/// -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] -pub enum Classification { - {{~ #each type_names as |type_name| }} - {{ type_name }},{{ /each }} -} - -impl Default for Classification { - fn default() -> Self { - Self::Si - } -} diff --git a/atom_generator/src/templates/mapper.rs.hbs b/atom_generator/src/templates/mapper.rs.hbs deleted file mode 100644 index 598a76e2..00000000 --- a/atom_generator/src/templates/mapper.rs.hbs +++ /dev/null @@ -1,21 +0,0 @@ -//----------------------------------------------------------------------------- -// DO NOT EDIT THIS FILE! -// This is generated by wise_units-atom_generator. -//----------------------------------------------------------------------------- - -use crate::parser::{ - symbols::{symbol_parser::Rule, Symbol}, - Error, Visit, -}; -use pest::iterators::Pair; - -pub(in super::super) fn map(pair: Pair<'_, Rule>) -> Result { - if let Rule::symbol = pair.as_rule() { - Ok(Symbol::visit(pair)?) - } else { - Err(Error::BadFragment { - fragment: pair.as_str().to_string(), - position: pair.as_span().start(), - }) - } -} diff --git a/atom_generator/src/templates/property.rs.hbs b/atom_generator/src/templates/property.rs.hbs deleted file mode 100644 index 3ac8f768..00000000 --- a/atom_generator/src/templates/property.rs.hbs +++ /dev/null @@ -1,71 +0,0 @@ -//----------------------------------------------------------------------------- -// DO NOT EDIT THIS FILE! -// This is generated by wise_units-atom_generator. -//----------------------------------------------------------------------------- - -use crate::parser::Atom; -use std::fmt; - -/// Property categorizes the unit by use. Not much mention of it in the UCUM -/// HTML spec, but is used throughout the -/// [XML description](http://unitsofmeasure.org/ucum-essence.xml). -/// -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub enum Property { - {{~ #each properties }} - {{ @key }},{{ /each }} -} - -impl Property { - /// All `Atom`s that match the `Property` variant. - /// - /// ``` - /// extern crate wise_units; - /// use wise_units::{Atom, Property}; - /// - /// assert_eq!(Property::Acidity.atoms(), vec![Atom::PH]); - /// ``` - /// - #[must_use] - pub fn atoms(self) -> Vec { - match self { - {{~ #each properties }} - Self::{{ @key }} => { - vec![ - {{~ #each this.atom_type_names }} - Atom::{{ this }},{{ /each }} - ] - },{{ /each }} - } - } -} - -impl Default for Property { - fn default() -> Self { - Self::Unclassified - } -} - -impl fmt::Display for Property { - fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - let string = match self { - {{~ #each properties as |key value| }} - Self::{{ @key }} => { - "{{ @key }}" - },{{ /each }} - }; - - write!(formatter, "{}", string) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn validate_display() { - let a = format!("{}", Property::Acceleration); - assert_eq!(&a, "Acceleration"); - } -} diff --git a/atom_generator/src/templates/symbol.pest.hbs b/atom_generator/src/templates/symbol.pest.hbs index af4bcf78..12c3fed4 100644 --- a/atom_generator/src/templates/symbol.pest.hbs +++ b/atom_generator/src/templates/symbol.pest.hbs @@ -16,7 +16,13 @@ secondary_symbol = _{ } pri_prefix = { - pri_yotta + pri_gibi + | pri_mebi + | pri_kibi + | pri_tebi + | pri_deka + + | pri_yotta | pri_zetta | pri_exa | pri_peta @@ -25,7 +31,6 @@ pri_prefix = { | pri_mega | pri_kilo | pri_hecto - | pri_deka | pri_deci | pri_centi | pri_milli @@ -36,10 +41,6 @@ pri_prefix = { | pri_atto | pri_zepto | pri_yocto - | pri_kibi - | pri_mebi - | pri_gibi - | pri_tebi } pri_atto = { "a" } @@ -68,28 +69,38 @@ pri_zetta = { "Z" } pri_zepto = { "z" } pri_atom = { - {{~ #each primary_rule_names }} - {{ #unless @first }} | {{ /unless }}{{ rule_name }}{{ /each }} + {{ #each primary_rule_names }} + {{ #unless @first }} | {{ /unless }}{{ rule_name }} + {{ /each }} } {{ #each primary_rule_names }} -{{ rule_name }} = { "{{ code }}" }{{ /each }} +{{ rule_name }} = { "{{ code }}" } +{{ /each }} //----------------------------------------------------------------------------- // Secondary stuff //----------------------------------------------------------------------------- sec_prefix = { - sec_yotta - | sec_zetta + sec_gibi + | sec_kibi + | sec_mebi + | sec_tebi + + | sec_deka | sec_exa - | sec_peta - | sec_tera | sec_giga | sec_mega + | sec_peta + | sec_tera + | sec_yotta + | sec_yocto + | sec_zetta + | sec_zepto + | sec_kilo | sec_hecto - | sec_deka | sec_deci | sec_centi | sec_milli @@ -98,12 +109,6 @@ sec_prefix = { | sec_pico | sec_femto | sec_atto - | sec_zepto - | sec_yocto - | sec_kibi - | sec_mebi - | sec_gibi - | sec_tebi } sec_atto = { "A" } @@ -132,11 +137,13 @@ sec_zetta = { "ZA" } sec_zepto = { "ZO" } sec_atom = { - {{~ #each secondary_rule_names }} - {{ #unless @first }} | {{ /unless }}{{ rule_name }}{{ /each }} + {{ #each secondary_rule_names }} + {{ #unless @first }} | {{ /unless }}{{ rule_name }} + {{ /each }} } {{ #each secondary_rule_names }} -{{ rule_name }} = { "{{ code }}" }{{ /each }} +{{ rule_name }} = { "{{ code }}" } +{{ /each }} // vim:ft=rust From 18ccc4a8ea0e7b851a906f5bbefe73600a408e6c Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Wed, 5 Jul 2023 10:50:43 -0700 Subject: [PATCH 17/80] Add dependabot.yml for main crate --- .github/dependabot.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e8d486ab..2c8d9f7b 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,7 +5,7 @@ version: 2 updates: - - package-ecosystem: "cargo" # See documentation for possible values - directory: "/" # Location of package manifests + - package-ecosystem: "cargo" + directory: "api" # Location of package manifests schedule: interval: "weekly" From 16d101faa212b48b84c75351b2dacaa407117ca0 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 17 Jul 2023 14:49:06 -0700 Subject: [PATCH 18/80] PCC-228 Add cargo-audit to CI --- .github/workflows/security-audit.yml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .github/workflows/security-audit.yml diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml new file mode 100644 index 00000000..017ac52b --- /dev/null +++ b/.github/workflows/security-audit.yml @@ -0,0 +1,26 @@ +--- +name: Security audit + +on: + push: + paths: + - "**/Cargo.toml" + - "**/Cargo.lock" + workflow_dispatch: + inputs: + tags: + required: false + description: "Security audit" + +env: + CARGO_TERM_COLOR: always + +jobs: + security-audit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Security audit + uses: actions-rs/audit-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} From 2735d1289db04bb2e73361f836a7df6371dd9e96 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 17 Jul 2023 14:52:59 -0700 Subject: [PATCH 19/80] Only run tests if Rust files change --- .github/workflows/rust-ci.yml | 6 ++++++ .github/workflows/security-audit.yml | 1 + 2 files changed, 7 insertions(+) diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index 74f8b28f..e4746a9f 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -1,7 +1,13 @@ +--- name: Continuous Integration on: push: + paths: + - "**/*.rs" + - "**/Cargo.toml" + - "**/Cargo.lock" + - ".github/workflows/rust-ci.yml" env: CARGO_TERM_COLOR: always diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml index 017ac52b..4578a195 100644 --- a/.github/workflows/security-audit.yml +++ b/.github/workflows/security-audit.yml @@ -6,6 +6,7 @@ on: paths: - "**/Cargo.toml" - "**/Cargo.lock" + - ".github/workflows/security-audit.yml" workflow_dispatch: inputs: tags: From 9b146ac9aaa064713ae9e1526439ed2efc335feb Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 17 Jul 2023 16:31:21 -0700 Subject: [PATCH 20/80] PCC-231 CI: Disable iOS for now --- .github/workflows/rust-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index e4746a9f..8b7f3cc3 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -42,7 +42,8 @@ jobs: check-ios: name: Test (x86_64-apple-ios) - runs-on: macos-10.15 + runs-on: [self-hosted, macOS, xcode13] + if: ${{ false }} # Disabling till PCC-221 env: DYLD_ROOT_PATH: "/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app" steps: From 2f2d8d46f25e4e8fa936c6e70e3cd5720a012950 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 17 Jul 2023 16:31:46 -0700 Subject: [PATCH 21/80] PCC-231 CI: Update upload-release to use proper SSH key --- .github/workflows/upload-release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/upload-release.yml b/.github/workflows/upload-release.yml index 90c289e8..95bcb41e 100644 --- a/.github/workflows/upload-release.yml +++ b/.github/workflows/upload-release.yml @@ -1,13 +1,14 @@ +--- name: Upload release on: push: tags: - - '*' + - "*" workflow_dispatch: inputs: tag: - description: 'Git tag' + description: "Git tag" required: true env: @@ -24,8 +25,7 @@ jobs: uses: webfactory/ssh-agent@ee29fafb6aa450493bac9136b346e51ea60a8b5e with: ssh-private-key: | - ${{ secrets.MAC_OS_BUILD_AGENT_PRIVATE_KEY }} - ${{ secrets.SSH_PRIVATE_KEY }} + ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - name: Checkout code uses: actions/checkout@v2 with: From 99f0c2e833f6bb95552d43ab00ba6e69d137279e Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 17 Jul 2023 16:42:28 -0700 Subject: [PATCH 22/80] PCC-231 Update old GH actions --- .github/workflows/rust-ci.yml | 44 +++++++++++++--------------- .github/workflows/upload-release.yml | 22 +++++++------- 2 files changed, 30 insertions(+), 36 deletions(-) diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index 8b7f3cc3..cf6eca85 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -19,21 +19,19 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup SSH - uses: webfactory/ssh-agent@ee29fafb6aa450493bac9136b346e51ea60a8b5e + uses: webfactory/ssh-agent@v0.8 with: - ssh-private-key: | - ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - - uses: actions/checkout@v2 - - uses: actions/cache@v2 + ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} + - uses: actions/checkout@v3 + - uses: actions/cache@v3 with: path: | - ~/.cargo/registry - ~/.cargo/git - target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} - restore-keys: | - ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} - ${{ runner.os }}-cargo + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: cargo test all uses: actions-rs/cargo@v1 with: @@ -48,21 +46,19 @@ jobs: DYLD_ROOT_PATH: "/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app" steps: - name: Setup SSH - uses: webfactory/ssh-agent@ee29fafb6aa450493bac9136b346e51ea60a8b5e + uses: webfactory/ssh-agent@v0.8 with: - ssh-private-key: | - ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - - uses: actions/checkout@v2 - - uses: actions/cache@v2 + ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} + - uses: actions/checkout@v3 + - uses: actions/cache@v3 with: path: | - ~/.cargo/registry - ~/.cargo/git - target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} - restore-keys: | - ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} - ${{ runner.os }}-cargo + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - uses: actions-rs/toolchain@v1 with: profile: minimal diff --git a/.github/workflows/upload-release.yml b/.github/workflows/upload-release.yml index 95bcb41e..a6be13f4 100644 --- a/.github/workflows/upload-release.yml +++ b/.github/workflows/upload-release.yml @@ -22,24 +22,22 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup SSH - uses: webfactory/ssh-agent@ee29fafb6aa450493bac9136b346e51ea60a8b5e + uses: webfactory/ssh-agent@v0.8 with: - ssh-private-key: | - ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} + ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: ref: ${{ env.TAG }} - - uses: actions/cache@v2 + - uses: actions/cache@v3 with: path: | - ~/.cargo/registry - ~/.cargo/git - target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} - restore-keys: | - ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.toml') }} - ${{ runner.os }}-cargo + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Build wise_units-ffi run: cargo build --release --package wise_units-ffi - name: Create Release From 2f4f5695e9ffb04040d6146f6bf150b7e98cf212 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 17 Jul 2023 16:42:49 -0700 Subject: [PATCH 23/80] PCC-231 Enable weekly dependabot GH action check --- .github/dependabot.yml | 12 ++++++------ .github/workflows/rust-ci.yml | 4 ++-- .github/workflows/upload-release.yml | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 2c8d9f7b..24af1349 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,11 +1,11 @@ -# To get started with Dependabot version updates, you'll need to specify which -# package ecosystems to update and where the package manifests are located. -# Please see the documentation for all configuration options: -# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates - +--- version: 2 updates: - package-ecosystem: "cargo" - directory: "api" # Location of package manifests + directory: "api" + schedule: + interval: "weekly" + - package-ecosystem: "github-actions" + directory: "/" schedule: interval: "weekly" diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index cf6eca85..c4056933 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup SSH - uses: webfactory/ssh-agent@v0.8 + uses: webfactory/ssh-agent@v0.8.0 with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - uses: actions/checkout@v3 @@ -46,7 +46,7 @@ jobs: DYLD_ROOT_PATH: "/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app" steps: - name: Setup SSH - uses: webfactory/ssh-agent@v0.8 + uses: webfactory/ssh-agent@v0.8.0 with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - uses: actions/checkout@v3 diff --git a/.github/workflows/upload-release.yml b/.github/workflows/upload-release.yml index a6be13f4..5f0cdd62 100644 --- a/.github/workflows/upload-release.yml +++ b/.github/workflows/upload-release.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup SSH - uses: webfactory/ssh-agent@v0.8 + uses: webfactory/ssh-agent@v0.8.0 with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - name: Checkout code From 9afe06db8c56b52a7b145ecf9020566bac27f4ff Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 20:26:17 +0000 Subject: [PATCH 24/80] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/rust-ci.yml | 4 ++-- .github/workflows/security-audit.yml | 2 +- .github/workflows/upload-release.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index c4056933..94a6f376 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -22,7 +22,7 @@ jobs: uses: webfactory/ssh-agent@v0.8.0 with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/cache@v3 with: path: | @@ -49,7 +49,7 @@ jobs: uses: webfactory/ssh-agent@v0.8.0 with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/cache@v3 with: path: | diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml index 4578a195..a4d80d87 100644 --- a/.github/workflows/security-audit.yml +++ b/.github/workflows/security-audit.yml @@ -20,7 +20,7 @@ jobs: security-audit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Security audit uses: actions-rs/audit-check@v1 with: diff --git a/.github/workflows/upload-release.yml b/.github/workflows/upload-release.yml index 5f0cdd62..f46f80df 100644 --- a/.github/workflows/upload-release.yml +++ b/.github/workflows/upload-release.yml @@ -26,7 +26,7 @@ jobs: with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - name: Checkout code - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: ref: ${{ env.TAG }} - uses: actions/cache@v3 From 713494ee1f68a61aec44c2b8fa8781f35b90e3f7 Mon Sep 17 00:00:00 2001 From: Gretchen Reeves Date: Tue, 10 Oct 2023 14:21:32 -0400 Subject: [PATCH 25/80] Updated cbindgen to latest version (which doesn't appear to use ansi-term) --- ffi/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffi/Cargo.toml b/ffi/Cargo.toml index 4be88185..979ddc21 100644 --- a/ffi/Cargo.toml +++ b/ffi/Cargo.toml @@ -13,7 +13,7 @@ ffi_common.workspace = true wise_units = { version = "0.22", registry = "crates-registry" } [build-dependencies] -cbindgen = "0.24" +cbindgen = "0.26.0" [dev-dependencies] approx.workspace = true From ef4308464973ab43c337adb58f10f4ef2d2bdbee Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Tue, 10 Oct 2023 13:56:45 -0700 Subject: [PATCH 26/80] ci: Rename crates-registry -> agrian-registry I'd renamed this to `crates-registry` since that's the name of the backing git repo, yet didn't change the env vars for the GH actions to match. Reverting these instead of renaming the related GH secret for now. Update security-audit.yml Update security-audit.yml --- .cargo/config.toml | 2 +- .github/workflows/security-audit.yml | 5 +++++ Cargo.toml | 2 +- api/Cargo.toml | 2 +- ffi/Cargo.toml | 4 ++-- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 092e6109..f3f0bdb8 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,2 +1,2 @@ [registries] -crates-registry = { index = "ssh://git@github.com/telus-agcg/crates-registry.git" } +agrian-registry = { index = "ssh://git@github.com/telus-agcg/crates-registry.git" } diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml index 4578a195..bee30c02 100644 --- a/.github/workflows/security-audit.yml +++ b/.github/workflows/security-audit.yml @@ -15,11 +15,16 @@ on: env: CARGO_TERM_COLOR: always + CARGO_REGISTRIES_AGRIAN_REGISTRY_INDEX: ${{ secrets.AGRIAN_CRATES_REGISTRY }} jobs: security-audit: runs-on: ubuntu-latest steps: + - name: Setup SSH + uses: webfactory/ssh-agent@v0.8.0 + with: + ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - uses: actions/checkout@v3 - name: Security audit uses: actions-rs/audit-check@v1 diff --git a/Cargo.toml b/Cargo.toml index 6fc93ec8..b5b6ca78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,6 @@ rust-version = "1.64.0" [workspace.dependencies] approx = "0.5" -ffi_common = { version = "0.7", registry = "crates-registry" } +ffi_common = { version = "0.7", registry = "agrian-registry" } lazy_static = "1.4" serde = { version = "1.0", features = ["derive"] } diff --git a/api/Cargo.toml b/api/Cargo.toml index 41c0deb2..521e4e3c 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/agrian-inc/wise_units" license = "MIT" authors = ["Steve Loveless "] edition = "2021" -publish = ["crates-registry"] +publish = ["agrian-registry"] [dependencies] approx.workspace = true diff --git a/ffi/Cargo.toml b/ffi/Cargo.toml index 979ddc21..98ffc138 100644 --- a/ffi/Cargo.toml +++ b/ffi/Cargo.toml @@ -6,11 +6,11 @@ repository = "https://github.com/agrian-inc/wise_units" license = "MIT" authors = ["Nicholas Smillie "] edition = "2021" -publish = ["crates-registry"] +publish = ["agrian-registry"] [dependencies] ffi_common.workspace = true -wise_units = { version = "0.22", registry = "crates-registry" } +wise_units = { version = "0.22", registry = "agrian-registry" } [build-dependencies] cbindgen = "0.26.0" From 2cc8ebd759fef013fa8b77a160ebfcef93e29ff8 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Tue, 10 Oct 2023 13:57:44 -0700 Subject: [PATCH 27/80] ci: Add cache step for security-audit flow --- .github/workflows/security-audit.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml index bee30c02..9534a75c 100644 --- a/.github/workflows/security-audit.yml +++ b/.github/workflows/security-audit.yml @@ -26,6 +26,15 @@ jobs: with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - uses: actions/checkout@v3 + - uses: actions/cache@v3 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} - name: Security audit uses: actions-rs/audit-check@v1 with: From fa82f1fb761f6f2c39b89a4f14ea2cdcb7655427 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Thu, 1 Feb 2024 15:45:03 -0800 Subject: [PATCH 28/80] Fix benchmarks Resolver = 2 --- Cargo.toml | 1 + api/benches/common.rs | 4 +- api/benches/measurements_benchmarks.rs | 73 ++++++++++++-------- api/benches/unit_benchmarks.rs | 95 +++++++++++++++++--------- 4 files changed, 111 insertions(+), 62 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b5b6ca78..0957a575 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,6 @@ [workspace] members = ["api", "atom_generator", "definition_fetcher", "ffi"] +resolver = "2" [workspace.package] rust-version = "1.64.0" diff --git a/api/benches/common.rs b/api/benches/common.rs index c0a0eedd..055d01be 100644 --- a/api/benches/common.rs +++ b/api/benches/common.rs @@ -1,4 +1,4 @@ -pub static UNIT_STRINGS: [&str; 25] = [ +pub const UNIT_STRINGS: [&str; 25] = [ // The unity "1", // base, factor*base, factor*base^exponent @@ -39,7 +39,7 @@ pub static UNIT_STRINGS: [&str; 25] = [ "10m3/5s2", ]; -pub static UNIT_PAIRS: [(&str, &str); 19] = [ +pub const UNIT_PAIRS: [(&str, &str); 19] = [ ("m", "m"), ("m", "cm"), ("m", "[in_i]"), diff --git a/api/benches/measurements_benchmarks.rs b/api/benches/measurements_benchmarks.rs index b652aeb6..0a252079 100644 --- a/api/benches/measurements_benchmarks.rs +++ b/api/benches/measurements_benchmarks.rs @@ -4,46 +4,64 @@ extern crate wise_units; mod common; -use criterion::Criterion; +use criterion::{BenchmarkId, Criterion}; use std::str::FromStr; use wise_units::{Convertible, Measurement, Unit}; fn new_group(c: &mut Criterion) { - c.bench_function_over_inputs( - "Measurement::try_new", - |b, &unit_string| { - b.iter(|| Measurement::try_new(1.0, unit_string)); - }, - &common::UNIT_STRINGS, - ); + let mut group = c.benchmark_group("Measurement::try_new"); + + for unit_string in common::UNIT_STRINGS { + group.bench_with_input( + BenchmarkId::new("try_new", unit_string), + unit_string, + |b, unit_string| { + b.iter(|| Measurement::try_new(1.0, unit_string)); + }, + ); + } + + group.finish() } //----------------------------------------------------------------------------- // impl Convertible //----------------------------------------------------------------------------- fn convert_to_str_group(c: &mut Criterion) { - c.bench_function_over_inputs( - "Measurement::convert_to(str)", - |b, &(lhs_string, rhs_string)| { - let lhs = Measurement::try_new(2.0, lhs_string).unwrap(); - - b.iter(|| lhs.convert_to(*rhs_string)); - }, - &common::UNIT_PAIRS, - ); + let mut group = c.benchmark_group("Measurement::convert_to"); + + for pair in common::UNIT_PAIRS { + group.bench_with_input( + BenchmarkId::new("convert_to", format!("{}->{}", pair.0, pair.1)), + &pair, + |b, (lhs_string, rhs_string)| { + let lhs = Measurement::try_new(2.0, *lhs_string).unwrap(); + + b.iter(|| lhs.convert_to(*rhs_string)); + }, + ); + } + + group.finish() } fn convert_to_unit_group(c: &mut Criterion) { - c.bench_function_over_inputs( - "Measurement::convert_to(Unit)", - |b, &(lhs_string, rhs_string)| { - let lhs = Measurement::try_new(2.0, lhs_string).unwrap(); - let rhs = &Unit::from_str(rhs_string).unwrap(); - - b.iter(|| lhs.convert_to(rhs)); - }, - &common::UNIT_PAIRS, - ); + let mut group = c.benchmark_group("Measurement::convert_to"); + + for pair in common::UNIT_PAIRS { + group.bench_with_input( + BenchmarkId::new("convert_to", format!("{}->{}", pair.0, pair.1)), + &pair, + |b, (lhs_string, rhs_string)| { + let lhs = Measurement::try_new(2.0, *lhs_string).unwrap(); + let rhs = &Unit::from_str(rhs_string).unwrap(); + + b.iter(|| lhs.convert_to(rhs)); + }, + ); + } + + group.finish() } criterion_group!( @@ -53,3 +71,4 @@ criterion_group!( convert_to_unit_group, ); criterion_main!(measurement_benches); + diff --git a/api/benches/unit_benchmarks.rs b/api/benches/unit_benchmarks.rs index be5820d1..360151a0 100644 --- a/api/benches/unit_benchmarks.rs +++ b/api/benches/unit_benchmarks.rs @@ -4,22 +4,28 @@ extern crate wise_units; mod common; -use criterion::Criterion; +use criterion::{BenchmarkId, Criterion}; use std::str::FromStr; use wise_units::{Composable, IsCompatibleWith, UcumUnit, Unit}; macro_rules! bench_over_inputs_method { ($function_name:ident, $test_name:expr, $method_name:ident) => { fn $function_name(c: &mut Criterion) { - c.bench_function_over_inputs( - $test_name, - |b, &unit_string| { - let unit = Unit::from_str(unit_string).unwrap(); - - b.iter(|| unit.$method_name()); - }, - &common::UNIT_STRINGS, - ); + let mut group = c.benchmark_group($test_name); + + for unit_string in common::UNIT_STRINGS { + group.bench_with_input( + BenchmarkId::new(stringify!($method_name), &unit_string), + unit_string, + |b, unit_string| { + let unit = Unit::from_str(unit_string).unwrap(); + + b.iter(|| unit.$method_name()); + }, + ); + } + + group.finish() } }; } @@ -27,12 +33,22 @@ macro_rules! bench_over_inputs_method { macro_rules! bench_over_inputs_math { ($function_name:ident, $test_name:expr, $method_name:tt) => { fn $function_name(c: &mut Criterion) { - c.bench_function_over_inputs($test_name, |b, &(lhs_string, rhs_string)| { - let lhs = &Unit::from_str(lhs_string).unwrap(); - let rhs = &Unit::from_str(rhs_string).unwrap(); - - b.iter(|| lhs $method_name rhs); - }, &common::UNIT_PAIRS); + let mut group = c.benchmark_group($test_name); + + for pair in common::UNIT_PAIRS { + group.bench_with_input( + BenchmarkId::new(stringify!($method_name), format!("{}->{}", pair.0, pair.1)), + &pair, + |b, (lhs_string, rhs_string)| { + let lhs = &Unit::from_str(lhs_string).unwrap(); + let rhs = &Unit::from_str(rhs_string).unwrap(); + + b.iter(|| lhs $method_name rhs); + }, + ); + } + + group.finish() } }; } @@ -54,16 +70,22 @@ bench_over_inputs_method!( bench_over_inputs_method!(composition_group, "Unit::composition()", composition); fn is_compatible_with_group(c: &mut Criterion) { - c.bench_function_over_inputs( - "Unit::is_compatible_with()", - |b, &(lhs_string, rhs_string)| { - let lhs = &Unit::from_str(lhs_string).unwrap(); - let rhs = &Unit::from_str(rhs_string).unwrap(); - - b.iter(|| lhs.is_compatible_with(rhs)); - }, - &common::UNIT_PAIRS, - ); + let mut group = c.benchmark_group("Unit::is_compatible_with()"); + + for pair in common::UNIT_PAIRS { + group.bench_with_input( + BenchmarkId::new("is_compatible_with", format!("{}->{}", pair.0, pair.1)), + &pair, + |b, (lhs_string, rhs_string)| { + let lhs = &Unit::from_str(lhs_string).unwrap(); + let rhs = &Unit::from_str(rhs_string).unwrap(); + + b.iter(|| lhs.is_compatible_with(rhs)); + }, + ); + } + + group.finish() } //----------------------------------------------------------------------------- @@ -75,13 +97,19 @@ bench_over_inputs_method!(display_group, "Unit::to_string()", to_string); // impl FromStr //----------------------------------------------------------------------------- fn from_str_group(c: &mut Criterion) { - c.bench_function_over_inputs( - "Unit::from_str()", - |b, &unit_string| { - b.iter(|| Unit::from_str(unit_string)); - }, - &common::UNIT_STRINGS, - ); + let mut group = c.benchmark_group("Unit::from_str()"); + + for unit_string in common::UNIT_STRINGS { + group.bench_with_input( + BenchmarkId::new("from_str", unit_string), + unit_string, + |b, unit_string| { + b.iter(|| Unit::from_str(unit_string)); + }, + ); + } + + group.finish() } //----------------------------------------------------------------------------- @@ -121,3 +149,4 @@ criterion_group!( partial_ord_gt_group, ); criterion_main!(unit_benches); + From 2e2a201d0ae7de5cabcec366acf598705c7084a9 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 2 Feb 2024 12:17:39 -0800 Subject: [PATCH 29/80] IsCompatibleWith impls should use the least common denominator impl --- api/src/measurement/is_compatible_with.rs | 2 +- api/src/unit/is_compatible_with.rs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/api/src/measurement/is_compatible_with.rs b/api/src/measurement/is_compatible_with.rs index 64bf0125..1fc93689 100644 --- a/api/src/measurement/is_compatible_with.rs +++ b/api/src/measurement/is_compatible_with.rs @@ -11,7 +11,7 @@ impl IsCompatibleWith for Measurement { impl IsCompatibleWith for Measurement { #[inline] fn is_compatible_with(&self, rhs: &Unit) -> bool { - self.unit.terms().is_compatible_with(rhs.terms()) + self.unit.is_compatible_with(rhs) } } diff --git a/api/src/unit/is_compatible_with.rs b/api/src/unit/is_compatible_with.rs index 4a48b083..30d4faf2 100644 --- a/api/src/unit/is_compatible_with.rs +++ b/api/src/unit/is_compatible_with.rs @@ -2,24 +2,24 @@ use crate::{ is_compatible_with::IsCompatibleWith, measurement::Measurement, parser::Term, unit::Unit, }; -impl IsCompatibleWith> for Unit { - fn is_compatible_with(&self, rhs: &Vec) -> bool { - self.terms.is_compatible_with(rhs) - } -} - #[cfg_attr(feature = "cffi", ffi_common::derive::expose_impl)] impl IsCompatibleWith for Unit { #[inline] fn is_compatible_with(&self, rhs: &Self) -> bool { - self.is_compatible_with(rhs.terms()) + self.is_compatible_with(&rhs.terms) + } +} + +impl IsCompatibleWith> for Unit { + fn is_compatible_with(&self, rhs: &Vec) -> bool { + self.terms.is_compatible_with(rhs) } } impl IsCompatibleWith for Unit { #[inline] fn is_compatible_with(&self, rhs: &Measurement) -> bool { - (*self).is_compatible_with(rhs.unit().terms()) + self.is_compatible_with(rhs.unit()) } } From fee497ac20fb9504ad1e1db75e04c6d3db5efb8d Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 2 Feb 2024 16:53:24 -0800 Subject: [PATCH 30/80] Refactor Definition to Definition, Unit internals --- api/Cargo.toml | 1 + api/src/macros.rs | 7 + api/src/measurement/reducible.rs | 2 +- api/src/parser.rs | 2 +- api/src/parser/atom.rs | 820 +++++++++++----------- api/src/parser/atom/reducible.rs | 2 +- api/src/parser/atom_test.rs | 19 +- api/src/parser/definition.rs | 127 ++-- api/src/parser/function_set.rs | 8 +- api/src/parser/prefix.rs | 11 +- api/src/parser/term.rs | 4 + api/src/parser/term/composable.rs | 7 +- api/src/parser/term/invert.rs | 29 +- api/src/parser/term/is_compatible_with.rs | 24 +- api/src/parser/term/reducible.rs | 9 +- api/src/reducible.rs | 6 +- api/src/unit.rs | 29 +- api/src/unit/deref.rs | 2 +- api/src/unit/is_compatible_with.rs | 6 +- api/src/unit/reducible.rs | 2 +- 20 files changed, 618 insertions(+), 499 deletions(-) diff --git a/api/Cargo.toml b/api/Cargo.toml index 521e4e3c..2530ef28 100644 --- a/api/Cargo.toml +++ b/api/Cargo.toml @@ -11,6 +11,7 @@ publish = ["agrian-registry"] [dependencies] approx.workspace = true ffi_common = { workspace = true, optional = true } +num-traits = "0.2.17" pest = "^2.1" pest_derive = "^2.1" serde = { workspace = true, optional = true } diff --git a/api/src/macros.rs b/api/src/macros.rs index baba07f8..3079f10c 100644 --- a/api/src/macros.rs +++ b/api/src/macros.rs @@ -53,6 +53,13 @@ macro_rules! term { }; } +#[macro_export] +macro_rules! terms { + ($($term:expr),*) => { + std::borrow::Cow::<[Term]>::Owned(vec![$($term)*]) + }; +} + #[cfg(test)] mod tests { use crate::parser::{Atom, Prefix, Term}; diff --git a/api/src/measurement/reducible.rs b/api/src/measurement/reducible.rs index 1f18eb21..7ba57993 100644 --- a/api/src/measurement/reducible.rs +++ b/api/src/measurement/reducible.rs @@ -1,6 +1,6 @@ use crate::{measurement::Measurement, reducible::Reducible, ucum_unit::UcumUnit}; -impl Reducible for Measurement { +impl Reducible for Measurement { fn reduce_value(&self, value: f64) -> f64 { if self.is_special() { self.unit.reduce_value(value) diff --git a/api/src/parser.rs b/api/src/parser.rs index 62417f25..14a3af33 100644 --- a/api/src/parser.rs +++ b/api/src/parser.rs @@ -29,7 +29,7 @@ mod dimension; mod error; mod function_set; mod prefix; -mod term; +pub(crate) mod term; mod terms; mod ucum_symbol; diff --git a/api/src/parser/atom.rs b/api/src/parser/atom.rs index c765eb76..e8404490 100644 --- a/api/src/parser/atom.rs +++ b/api/src/parser/atom.rs @@ -330,481 +330,519 @@ pub enum Atom { Baud, } impl Atom { - pub(crate) fn definition(self) -> Definition { + pub(crate) fn definition(self) -> Definition { let result = match self { - Self::Meter => Ok(Definition::default()), - Self::Second => Ok(Definition::default()), - Self::Gram => Ok(Definition::default()), - Self::Radian => Ok(Definition::default()), - Self::Kelvin => Ok(Definition::default()), - Self::Coulomb => Ok(Definition::default()), - Self::Candela => Ok(Definition::default()), - Self::TheNumberTenForArbitraryPowersStar => Definition::new(10f64, "1", None), - Self::TheNumberTenForArbitraryPowersCaret => Definition::new(10f64, "1", None), - Self::TheNumberPi => Definition::new(::std::f64::consts::PI, "1", None), - Self::Percent => Definition::new(1f64, "10*-2", None), - Self::PartsPerThousand => Definition::new(1f64, "10*-3", None), - Self::PartsPerMillion => Definition::new(1f64, "10*-6", None), - Self::PartsPerBillion => Definition::new(1f64, "10*-9", None), - Self::PartsPerTrillion => Definition::new(1f64, "10*-12", None), - Self::Mole => Definition::new(6.0221367f64, "10*23", None), - Self::Steradian => Definition::new(1f64, "rad2", None), - Self::Hertz => Definition::new(1f64, "s-1", None), - Self::Newton => Definition::new(1f64, "kg.m/s2", None), - Self::Pascal => Definition::new(1f64, "N/m2", None), - Self::Joule => Definition::new(1f64, "N.m", None), - Self::Watt => Definition::new(1f64, "J/s", None), - Self::Ampere => Definition::new(1f64, "C/s", None), - Self::Volt => Definition::new(1f64, "J/C", None), - Self::Farad => Definition::new(1f64, "C/V", None), - Self::Ohm => Definition::new(1f64, "V/A", None), - Self::Siemens => Definition::new(1f64, "Ohm-1", None), - Self::Weber => Definition::new(1f64, "V.s", None), - Self::DegreeCelsius => Definition::new( + Self::Meter => Ok(Definition::Base), + Self::Second => Ok(Definition::Base), + Self::Gram => Ok(Definition::Base), + Self::Radian => Ok(Definition::Base), + Self::Kelvin => Ok(Definition::Base), + Self::Coulomb => Ok(Definition::Base), + Self::Candela => Ok(Definition::Base), + Self::TheNumberTenForArbitraryPowersStar => Ok(Definition::NonDimensional(10f64)), + Self::TheNumberTenForArbitraryPowersCaret => Ok(Definition::NonDimensional(10f64)), + Self::TheNumberPi => Ok(Definition::NonDimensional(::std::f64::consts::PI)), + Self::Percent => Ok(Definition::NonDimensional(0.01)), + Self::PartsPerThousand => Definition::try_new_dimensional(1f64, "10*-3"), + Self::PartsPerMillion => Definition::try_new_dimensional(1f64, "10*-6"), + Self::PartsPerBillion => Definition::try_new_dimensional(1f64, "10*-9"), + Self::PartsPerTrillion => Definition::try_new_dimensional(1f64, "10*-12"), + Self::Mole => Definition::try_new_dimensional(6.0221367f64, "10*23"), + Self::Steradian => Definition::try_new_dimensional(1f64, "rad2"), + Self::Hertz => Definition::try_new_dimensional(1f64, "s-1"), + Self::Newton => Definition::try_new_dimensional(1f64, "kg.m/s2"), + Self::Pascal => Definition::try_new_dimensional(1f64, "N/m2"), + Self::Joule => Definition::try_new_dimensional(1f64, "N.m"), + Self::Watt => Definition::try_new_dimensional(1f64, "J/s"), + Self::Ampere => Definition::try_new_dimensional(1f64, "C/s"), + Self::Volt => Definition::try_new_dimensional(1f64, "J/C"), + Self::Farad => Definition::try_new_dimensional(1f64, "C/V"), + Self::Ohm => Definition::try_new_dimensional(1f64, "V/A"), + Self::Siemens => Definition::try_new_dimensional(1f64, "Ohm-1"), + Self::Weber => Definition::try_new_dimensional(1f64, "V.s"), + Self::DegreeCelsius => Definition::try_new_dimensional_special( 1f64, "K", - Some(FunctionSet { + FunctionSet { convert_from: |value: f64| value - 273.15, convert_to: |value: f64| value + 273.15, - }), + }, ), - Self::Tesla => Definition::new(1f64, "Wb/m2", None), - Self::Henry => Definition::new(1f64, "Wb/A", None), - Self::Lumen => Definition::new(1f64, "cd.sr", None), - Self::Lux => Definition::new(1f64, "lm/m2", None), - Self::Becquerel => Definition::new(1f64, "s-1", None), - Self::Gray => Definition::new(1f64, "J/kg", None), - Self::Sievert => Definition::new(1f64, "J/kg", None), - Self::Gon => Definition::new(0.9f64, "deg", None), - Self::Degree => Definition::new(2f64, "[pi].rad/360", None), - Self::MinuteAngle => Definition::new(1f64, "deg/60", None), - Self::SecondAngle => Definition::new(1f64, "'/60", None), - Self::Liter => Definition::new(1f64, "dm3", None), - Self::LiterSecondary => Definition::new(1f64, "l", None), - Self::Are => Definition::new(100f64, "m2", None), - Self::Minute => Definition::new(60f64, "s", None), - Self::Hour => Definition::new(60f64, "min", None), - Self::Day => Definition::new(24f64, "h", None), - Self::TropicalYear => Definition::new(365.24219f64, "d", None), - Self::MeanJulianYear => Definition::new(365.25f64, "d", None), - Self::MeanGregorianYear => Definition::new(365.2425f64, "d", None), - Self::Year => Definition::new(1f64, "a_j", None), - Self::Week => Definition::new(7f64, "d", None), - Self::SynodalMonth => Definition::new(29.53059f64, "d", None), - Self::MeanJulianMonth => Definition::new(1f64, "a_j/12", None), - Self::MeanGregorianMonth => Definition::new(1f64, "a_g/12", None), - Self::Month => Definition::new(1f64, "mo_j", None), - Self::Tonne => Definition::new(1000f64, "kg", None), - Self::Bar => Definition::new(100000f64, "Pa", None), + Self::Tesla => Definition::try_new_dimensional(1f64, "Wb/m2"), + Self::Henry => Definition::try_new_dimensional(1f64, "Wb/A"), + Self::Lumen => Definition::try_new_dimensional(1f64, "cd.sr"), + Self::Lux => Definition::try_new_dimensional(1f64, "lm/m2"), + Self::Becquerel => Definition::try_new_dimensional(1f64, "s-1"), + Self::Gray => Definition::try_new_dimensional(1f64, "J/kg"), + Self::Sievert => Definition::try_new_dimensional(1f64, "J/kg"), + Self::Gon => Definition::try_new_dimensional(0.9f64, "deg"), + Self::Degree => Definition::try_new_dimensional(2f64, "[pi].rad/360"), + Self::MinuteAngle => Definition::try_new_dimensional(1f64, "deg/60"), + Self::SecondAngle => Definition::try_new_dimensional(1f64, "'/60"), + Self::Liter => Definition::try_new_dimensional(1f64, "dm3"), + Self::LiterSecondary => Definition::try_new_dimensional(1f64, "l"), + Self::Are => Definition::try_new_dimensional(100f64, "m2"), + Self::Minute => Definition::try_new_dimensional(60f64, "s"), + Self::Hour => Definition::try_new_dimensional(60f64, "min"), + Self::Day => Definition::try_new_dimensional(24f64, "h"), + Self::TropicalYear => Definition::try_new_dimensional(365.24219f64, "d"), + Self::MeanJulianYear => Definition::try_new_dimensional(365.25f64, "d"), + Self::MeanGregorianYear => Definition::try_new_dimensional(365.2425f64, "d"), + Self::Year => Definition::try_new_dimensional(1f64, "a_j"), + Self::Week => Definition::try_new_dimensional(7f64, "d"), + Self::SynodalMonth => Definition::try_new_dimensional(29.53059f64, "d"), + Self::MeanJulianMonth => Definition::try_new_dimensional(1f64, "a_j/12"), + Self::MeanGregorianMonth => Definition::try_new_dimensional(1f64, "a_g/12"), + Self::Month => Definition::try_new_dimensional(1f64, "mo_j"), + Self::Tonne => Definition::try_new_dimensional(1000f64, "kg"), + Self::Bar => Definition::try_new_dimensional(100000f64, "Pa"), Self::UnifiedAtomicMassUnit => { - Definition::new(0.0000000000000000000000016605402f64, "g", None) - } - Self::Electronvolt => Definition::new(1f64, "[e].V", None), - Self::AstronomicUnit => Definition::new(149597.870691f64, "Mm", None), - Self::Parsec => Definition::new(30856780000000000f64, "m", None), - Self::VelocityOfLight => Definition::new(299792458f64, "m/s", None), - Self::PlanckConstant => { - Definition::new(0.00000000000000000000000000000000066260755f64, "J.s", None) + Definition::try_new_dimensional(0.0000000000000000000000016605402f64, "g") } + Self::Electronvolt => Definition::try_new_dimensional(1f64, "[e].V"), + Self::AstronomicUnit => Definition::try_new_dimensional(149597.870691f64, "Mm"), + Self::Parsec => Definition::try_new_dimensional(30856780000000000f64, "m"), + Self::VelocityOfLight => Definition::try_new_dimensional(299792458f64, "m/s"), + Self::PlanckConstant => Definition::try_new_dimensional( + 0.00000000000000000000000000000000066260755f64, + "J.s", + ), Self::BoltzmannConstant => { - Definition::new(0.00000000000000000000001380658f64, "J/K", None) + Definition::try_new_dimensional(0.00000000000000000000001380658f64, "J/K") + } + Self::PermittivityOfVacuum => { + Definition::try_new_dimensional(0.000000000008854187817f64, "F/m") + } + Self::PermeabilityOfVacuum => { + Definition::try_new_dimensional(1f64, "4.[pi].10*-7.N/A2") + } + Self::ElementaryCharge => { + Definition::try_new_dimensional(0.000000000000000000160217733f64, "C") } - Self::PermittivityOfVacuum => Definition::new(0.000000000008854187817f64, "F/m", None), - Self::PermeabilityOfVacuum => Definition::new(1f64, "4.[pi].10*-7.N/A2", None), - Self::ElementaryCharge => Definition::new(0.000000000000000000160217733f64, "C", None), Self::ElectronMass => { - Definition::new(0.00000000000000000000000000091093897f64, "g", None) + Definition::try_new_dimensional(0.00000000000000000000000000091093897f64, "g") + } + Self::ProtonMass => { + Definition::try_new_dimensional(0.0000000000000000000000016726231f64, "g") } - Self::ProtonMass => Definition::new(0.0000000000000000000000016726231f64, "g", None), Self::NewtonianConstantOfGravitation => { - Definition::new(0.0000000000667259f64, "m3.kg-1.s-2", None) - } - Self::StandardAccelerationOfFreeFall => Definition::new(9.80665f64, "m/s2", None), - Self::StandardAtmosphere => Definition::new(101325f64, "Pa", None), - Self::LightYear => Definition::new(1f64, "[c].a_j", None), - Self::GramForce => Definition::new(1f64, "g.[g]", None), - Self::PoundForceAvoirdupois => Definition::new(1f64, "[lb_av].[g]", None), - Self::Kayser => Definition::new(1f64, "cm-1", None), - Self::Gal => Definition::new(1f64, "cm/s2", None), - Self::Dyne => Definition::new(1f64, "g.cm/s2", None), - Self::Erg => Definition::new(1f64, "dyn.cm", None), - Self::Poise => Definition::new(1f64, "dyn.s/cm2", None), - Self::Biot => Definition::new(10f64, "A", None), - Self::Stokes => Definition::new(1f64, "cm2/s", None), - Self::Maxwell => Definition::new(0.00000001f64, "Wb", None), - Self::Gauss => Definition::new(0.0001f64, "T", None), - Self::Oersted => Definition::new(250f64, "/[pi].A/m", None), - Self::Gilbert => Definition::new(1f64, "Oe.cm", None), - Self::Stilb => Definition::new(1f64, "cd/cm2", None), - Self::Lambert => Definition::new(1f64, "cd/cm2/[pi]", None), - Self::Phot => Definition::new(0.0001f64, "lx", None), - Self::Curie => Definition::new(37000000000f64, "Bq", None), - Self::Roentgen => Definition::new(0.000258f64, "C/kg", None), - Self::RadiationAbsorbedDose => Definition::new(100f64, "erg/g", None), - Self::RadiationEquivalentMan => Definition::new(1f64, "RAD", None), - Self::InchInternational => Definition::new(2.54f64, "cm", None), - Self::FootInternational => Definition::new(12f64, "[in_i]", None), - Self::YardInternational => Definition::new(3f64, "[ft_i]", None), - Self::MileInternational => Definition::new(5280f64, "[ft_i]", None), - Self::FathomInternational => Definition::new(6f64, "[ft_i]", None), - Self::NauticalMileInternational => Definition::new(1852f64, "m", None), - Self::KnotInternational => Definition::new(1f64, "[nmi_i]/h", None), - Self::SquareInchInternational => Definition::new(1f64, "[in_i]2", None), - Self::SquareFootInternational => Definition::new(1f64, "[ft_i]2", None), - Self::SquareYardInternational => Definition::new(1f64, "[yd_i]2", None), - Self::CubicInchInternational => Definition::new(1f64, "[in_i]3", None), - Self::CubicFootInternational => Definition::new(1f64, "[ft_i]3", None), - Self::CubicYardInternational => Definition::new(1f64, "[yd_i]3", None), - Self::BoardFootInternational => Definition::new(144f64, "[in_i]3", None), - Self::CordInternational => Definition::new(128f64, "[ft_i]3", None), - Self::MilInternational => Definition::new(0.001f64, "[in_i]", None), - Self::CircularMilInternational => Definition::new(1f64, "[pi]/4.[mil_i]2", None), - Self::HandInternational => Definition::new(4f64, "[in_i]", None), - Self::FootUS => Definition::new(1200f64, "m/3937", None), - Self::YardUS => Definition::new(3f64, "[ft_us]", None), - Self::InchUS => Definition::new(1f64, "[ft_us]/12", None), - Self::RodUS => Definition::new(16.5f64, "[ft_us]", None), - Self::GuntersChainUS => Definition::new(4f64, "[rd_us]", None), - Self::LinkForGuntersChainUS => Definition::new(1f64, "[ch_us]/100", None), - Self::RamdensChainUS => Definition::new(100f64, "[ft_us]", None), - Self::LinkForRamdensChainUS => Definition::new(1f64, "[rch_us]/100", None), - Self::FathomUS => Definition::new(6f64, "[ft_us]", None), - Self::FurlongUS => Definition::new(40f64, "[rd_us]", None), - Self::MileUS => Definition::new(8f64, "[fur_us]", None), - Self::AcreUS => Definition::new(160f64, "[rd_us]2", None), - Self::SquareRodUS => Definition::new(1f64, "[rd_us]2", None), - Self::SquareMileUS => Definition::new(1f64, "[mi_us]2", None), - Self::Section => Definition::new(1f64, "[mi_us]2", None), - Self::Township => Definition::new(36f64, "[sct]", None), - Self::MilUS => Definition::new(0.001f64, "[in_us]", None), - Self::InchBritish => Definition::new(2.539998f64, "cm", None), - Self::FootBritish => Definition::new(12f64, "[in_br]", None), - Self::RodBritish => Definition::new(16.5f64, "[ft_br]", None), - Self::GuntersChainBritish => Definition::new(4f64, "[rd_br]", None), - Self::LinkForGuntersChainBritish => Definition::new(1f64, "[ch_br]/100", None), - Self::FathomBritish => Definition::new(6f64, "[ft_br]", None), - Self::PaceBritish => Definition::new(2.5f64, "[ft_br]", None), - Self::YardBritish => Definition::new(3f64, "[ft_br]", None), - Self::MileBritish => Definition::new(5280f64, "[ft_br]", None), - Self::NauticalMileBritish => Definition::new(6080f64, "[ft_br]", None), - Self::KnotBritish => Definition::new(1f64, "[nmi_br]/h", None), - Self::AcreBritish => Definition::new(4840f64, "[yd_br]2", None), - Self::QueenAnnesWineGallonUS => Definition::new(231f64, "[in_i]3", None), - Self::BarrelUS => Definition::new(42f64, "[gal_us]", None), - Self::QuartUS => Definition::new(1f64, "[gal_us]/4", None), - Self::PintUS => Definition::new(1f64, "[qt_us]/2", None), - Self::GillUS => Definition::new(1f64, "[pt_us]/4", None), - Self::FluidOunceUS => Definition::new(1f64, "[gil_us]/4", None), - Self::FluidDramUS => Definition::new(1f64, "[foz_us]/8", None), - Self::MinimUS => Definition::new(1f64, "[fdr_us]/60", None), - Self::CordUS => Definition::new(128f64, "[ft_i]3", None), - Self::BushelUS => Definition::new(2150.42f64, "[in_i]3", None), - Self::HistoricalWinchesterGallon => Definition::new(1f64, "[bu_us]/8", None), - Self::PeckUS => Definition::new(1f64, "[bu_us]/4", None), - Self::DryQuartUS => Definition::new(1f64, "[pk_us]/8", None), - Self::DryPintUS => Definition::new(1f64, "[dqt_us]/2", None), - Self::TablespoonUS => Definition::new(1f64, "[foz_us]/2", None), - Self::TeaspoonUS => Definition::new(1f64, "[tbs_us]/3", None), - Self::CupUS => Definition::new(16f64, "[tbs_us]", None), - Self::MetricFluidOunce => Definition::new(30f64, "mL", None), - Self::MetricCup => Definition::new(240f64, "mL", None), - Self::MetricTeaspoon => Definition::new(5f64, "mL", None), - Self::MetricTablespoon => Definition::new(15f64, "mL", None), - Self::GallonBritish => Definition::new(4.54609f64, "l", None), - Self::PeckBritish => Definition::new(2f64, "[gal_br]", None), - Self::BushelBritish => Definition::new(4f64, "[pk_br]", None), - Self::QuartBritish => Definition::new(1f64, "[gal_br]/4", None), - Self::PintBritish => Definition::new(1f64, "[qt_br]/2", None), - Self::GillBritish => Definition::new(1f64, "[pt_br]/4", None), - Self::FluidOunceBritish => Definition::new(1f64, "[gil_br]/5", None), - Self::FluidDramBritish => Definition::new(1f64, "[foz_br]/8", None), - Self::MinimBritish => Definition::new(1f64, "[fdr_br]/60", None), - Self::Grain => Definition::new(64.79891f64, "mg", None), - Self::PoundAvoirdupois => Definition::new(7000f64, "[gr]", None), - Self::OunceAvoirdupois => Definition::new(1f64, "[lb_av]/16", None), - Self::DramAvoirdupois => Definition::new(1f64, "[oz_av]/16", None), - Self::ShortHundredweightAvoirdupois => Definition::new(100f64, "[lb_av]", None), - Self::LongHunderdweightAvoirdupois => Definition::new(112f64, "[lb_av]", None), - Self::ShortTonAvoirdupois => Definition::new(20f64, "[scwt_av]", None), - Self::LongTonAvoirdupois => Definition::new(20f64, "[lcwt_av]", None), - Self::StoneAvoirdupois => Definition::new(14f64, "[lb_av]", None), - Self::PennyweightTroy => Definition::new(24f64, "[gr]", None), - Self::OunceTroy => Definition::new(20f64, "[pwt_tr]", None), - Self::PoundTroy => Definition::new(12f64, "[oz_tr]", None), - Self::ScrupleApothecaries => Definition::new(20f64, "[gr]", None), - Self::DramApothecaries => Definition::new(3f64, "[sc_ap]", None), - Self::OunceApothecaries => Definition::new(8f64, "[dr_ap]", None), - Self::PoundApothecaries => Definition::new(12f64, "[oz_ap]", None), - Self::MetricOunce => Definition::new(28f64, "g", None), - Self::Line => Definition::new(1f64, "[in_i]/12", None), - Self::Point => Definition::new(1f64, "[lne]/6", None), - Self::Pica => Definition::new(12f64, "[pnt]", None), - Self::PrintersPoint => Definition::new(0.013837f64, "[in_i]", None), - Self::PrintersPica => Definition::new(12f64, "[pnt_pr]", None), - Self::Pied => Definition::new(32.48f64, "cm", None), - Self::Pouce => Definition::new(1f64, "[pied]/12", None), - Self::Ligne => Definition::new(1f64, "[pouce]/12", None), - Self::Didot => Definition::new(1f64, "[ligne]/6", None), - Self::Cicero => Definition::new(12f64, "[didot]", None), - Self::DegreeFahrenheit => Definition::new( + Definition::try_new_dimensional(0.0000000000667259f64, "m3.kg-1.s-2") + } + Self::StandardAccelerationOfFreeFall => { + Definition::try_new_dimensional(9.80665f64, "m/s2") + } + Self::StandardAtmosphere => Definition::try_new_dimensional(101325f64, "Pa"), + Self::LightYear => Definition::try_new_dimensional(1f64, "[c].a_j"), + Self::GramForce => Definition::try_new_dimensional(1f64, "g.[g]"), + Self::PoundForceAvoirdupois => Definition::try_new_dimensional(1f64, "[lb_av].[g]"), + Self::Kayser => Definition::try_new_dimensional(1f64, "cm-1"), + Self::Gal => Definition::try_new_dimensional(1f64, "cm/s2"), + Self::Dyne => Definition::try_new_dimensional(1f64, "g.cm/s2"), + Self::Erg => Definition::try_new_dimensional(1f64, "dyn.cm"), + Self::Poise => Definition::try_new_dimensional(1f64, "dyn.s/cm2"), + Self::Biot => Definition::try_new_dimensional(10f64, "A"), + Self::Stokes => Definition::try_new_dimensional(1f64, "cm2/s"), + Self::Maxwell => Definition::try_new_dimensional(0.00000001f64, "Wb"), + Self::Gauss => Definition::try_new_dimensional(0.0001f64, "T"), + Self::Oersted => Definition::try_new_dimensional(250f64, "/[pi].A/m"), + Self::Gilbert => Definition::try_new_dimensional(1f64, "Oe.cm"), + Self::Stilb => Definition::try_new_dimensional(1f64, "cd/cm2"), + Self::Lambert => Definition::try_new_dimensional(1f64, "cd/cm2/[pi]"), + Self::Phot => Definition::try_new_dimensional(0.0001f64, "lx"), + Self::Curie => Definition::try_new_dimensional(37000000000f64, "Bq"), + Self::Roentgen => Definition::try_new_dimensional(0.000258f64, "C/kg"), + Self::RadiationAbsorbedDose => Definition::try_new_dimensional(100f64, "erg/g"), + Self::RadiationEquivalentMan => Definition::try_new_dimensional(1f64, "RAD"), + Self::InchInternational => Definition::try_new_dimensional(2.54f64, "cm"), + Self::FootInternational => Definition::try_new_dimensional(12f64, "[in_i]"), + Self::YardInternational => Definition::try_new_dimensional(3f64, "[ft_i]"), + Self::MileInternational => Definition::try_new_dimensional(5280f64, "[ft_i]"), + Self::FathomInternational => Definition::try_new_dimensional(6f64, "[ft_i]"), + Self::NauticalMileInternational => Definition::try_new_dimensional(1852f64, "m"), + Self::KnotInternational => Definition::try_new_dimensional(1f64, "[nmi_i]/h"), + Self::SquareInchInternational => Definition::try_new_dimensional(1f64, "[in_i]2"), + Self::SquareFootInternational => Definition::try_new_dimensional(1f64, "[ft_i]2"), + Self::SquareYardInternational => Definition::try_new_dimensional(1f64, "[yd_i]2"), + Self::CubicInchInternational => Definition::try_new_dimensional(1f64, "[in_i]3"), + Self::CubicFootInternational => Definition::try_new_dimensional(1f64, "[ft_i]3"), + Self::CubicYardInternational => Definition::try_new_dimensional(1f64, "[yd_i]3"), + Self::BoardFootInternational => Definition::try_new_dimensional(144f64, "[in_i]3"), + Self::CordInternational => Definition::try_new_dimensional(128f64, "[ft_i]3"), + Self::MilInternational => Definition::try_new_dimensional(0.001f64, "[in_i]"), + Self::CircularMilInternational => { + Definition::try_new_dimensional(1f64, "[pi]/4.[mil_i]2") + } + Self::HandInternational => Definition::try_new_dimensional(4f64, "[in_i]"), + Self::FootUS => Definition::try_new_dimensional(1200f64, "m/3937"), + Self::YardUS => Definition::try_new_dimensional(3f64, "[ft_us]"), + Self::InchUS => Definition::try_new_dimensional(1f64, "[ft_us]/12"), + Self::RodUS => Definition::try_new_dimensional(16.5f64, "[ft_us]"), + Self::GuntersChainUS => Definition::try_new_dimensional(4f64, "[rd_us]"), + Self::LinkForGuntersChainUS => Definition::try_new_dimensional(1f64, "[ch_us]/100"), + Self::RamdensChainUS => Definition::try_new_dimensional(100f64, "[ft_us]"), + Self::LinkForRamdensChainUS => Definition::try_new_dimensional(1f64, "[rch_us]/100"), + Self::FathomUS => Definition::try_new_dimensional(6f64, "[ft_us]"), + Self::FurlongUS => Definition::try_new_dimensional(40f64, "[rd_us]"), + Self::MileUS => Definition::try_new_dimensional(8f64, "[fur_us]"), + Self::AcreUS => Definition::try_new_dimensional(160f64, "[rd_us]2"), + Self::SquareRodUS => Definition::try_new_dimensional(1f64, "[rd_us]2"), + Self::SquareMileUS => Definition::try_new_dimensional(1f64, "[mi_us]2"), + Self::Section => Definition::try_new_dimensional(1f64, "[mi_us]2"), + Self::Township => Definition::try_new_dimensional(36f64, "[sct]"), + Self::MilUS => Definition::try_new_dimensional(0.001f64, "[in_us]"), + Self::InchBritish => Definition::try_new_dimensional(2.539998f64, "cm"), + Self::FootBritish => Definition::try_new_dimensional(12f64, "[in_br]"), + Self::RodBritish => Definition::try_new_dimensional(16.5f64, "[ft_br]"), + Self::GuntersChainBritish => Definition::try_new_dimensional(4f64, "[rd_br]"), + Self::LinkForGuntersChainBritish => { + Definition::try_new_dimensional(1f64, "[ch_br]/100") + } + Self::FathomBritish => Definition::try_new_dimensional(6f64, "[ft_br]"), + Self::PaceBritish => Definition::try_new_dimensional(2.5f64, "[ft_br]"), + Self::YardBritish => Definition::try_new_dimensional(3f64, "[ft_br]"), + Self::MileBritish => Definition::try_new_dimensional(5280f64, "[ft_br]"), + Self::NauticalMileBritish => Definition::try_new_dimensional(6080f64, "[ft_br]"), + Self::KnotBritish => Definition::try_new_dimensional(1f64, "[nmi_br]/h"), + Self::AcreBritish => Definition::try_new_dimensional(4840f64, "[yd_br]2"), + Self::QueenAnnesWineGallonUS => Definition::try_new_dimensional(231f64, "[in_i]3"), + Self::BarrelUS => Definition::try_new_dimensional(42f64, "[gal_us]"), + Self::QuartUS => Definition::try_new_dimensional(1f64, "[gal_us]/4"), + Self::PintUS => Definition::try_new_dimensional(1f64, "[qt_us]/2"), + Self::GillUS => Definition::try_new_dimensional(1f64, "[pt_us]/4"), + Self::FluidOunceUS => Definition::try_new_dimensional(1f64, "[gil_us]/4"), + Self::FluidDramUS => Definition::try_new_dimensional(1f64, "[foz_us]/8"), + Self::MinimUS => Definition::try_new_dimensional(1f64, "[fdr_us]/60"), + Self::CordUS => Definition::try_new_dimensional(128f64, "[ft_i]3"), + Self::BushelUS => Definition::try_new_dimensional(2150.42f64, "[in_i]3"), + Self::HistoricalWinchesterGallon => Definition::try_new_dimensional(1f64, "[bu_us]/8"), + Self::PeckUS => Definition::try_new_dimensional(1f64, "[bu_us]/4"), + Self::DryQuartUS => Definition::try_new_dimensional(1f64, "[pk_us]/8"), + Self::DryPintUS => Definition::try_new_dimensional(1f64, "[dqt_us]/2"), + Self::TablespoonUS => Definition::try_new_dimensional(1f64, "[foz_us]/2"), + Self::TeaspoonUS => Definition::try_new_dimensional(1f64, "[tbs_us]/3"), + Self::CupUS => Definition::try_new_dimensional(16f64, "[tbs_us]"), + Self::MetricFluidOunce => Definition::try_new_dimensional(30f64, "mL"), + Self::MetricCup => Definition::try_new_dimensional(240f64, "mL"), + Self::MetricTeaspoon => Definition::try_new_dimensional(5f64, "mL"), + Self::MetricTablespoon => Definition::try_new_dimensional(15f64, "mL"), + Self::GallonBritish => Definition::try_new_dimensional(4.54609f64, "l"), + Self::PeckBritish => Definition::try_new_dimensional(2f64, "[gal_br]"), + Self::BushelBritish => Definition::try_new_dimensional(4f64, "[pk_br]"), + Self::QuartBritish => Definition::try_new_dimensional(1f64, "[gal_br]/4"), + Self::PintBritish => Definition::try_new_dimensional(1f64, "[qt_br]/2"), + Self::GillBritish => Definition::try_new_dimensional(1f64, "[pt_br]/4"), + Self::FluidOunceBritish => Definition::try_new_dimensional(1f64, "[gil_br]/5"), + Self::FluidDramBritish => Definition::try_new_dimensional(1f64, "[foz_br]/8"), + Self::MinimBritish => Definition::try_new_dimensional(1f64, "[fdr_br]/60"), + Self::Grain => Definition::try_new_dimensional(64.79891f64, "mg"), + Self::PoundAvoirdupois => Definition::try_new_dimensional(7000f64, "[gr]"), + Self::OunceAvoirdupois => Definition::try_new_dimensional(1f64, "[lb_av]/16"), + Self::DramAvoirdupois => Definition::try_new_dimensional(1f64, "[oz_av]/16"), + Self::ShortHundredweightAvoirdupois => { + Definition::try_new_dimensional(100f64, "[lb_av]") + } + Self::LongHunderdweightAvoirdupois => { + Definition::try_new_dimensional(112f64, "[lb_av]") + } + Self::ShortTonAvoirdupois => Definition::try_new_dimensional(20f64, "[scwt_av]"), + Self::LongTonAvoirdupois => Definition::try_new_dimensional(20f64, "[lcwt_av]"), + Self::StoneAvoirdupois => Definition::try_new_dimensional(14f64, "[lb_av]"), + Self::PennyweightTroy => Definition::try_new_dimensional(24f64, "[gr]"), + Self::OunceTroy => Definition::try_new_dimensional(20f64, "[pwt_tr]"), + Self::PoundTroy => Definition::try_new_dimensional(12f64, "[oz_tr]"), + Self::ScrupleApothecaries => Definition::try_new_dimensional(20f64, "[gr]"), + Self::DramApothecaries => Definition::try_new_dimensional(3f64, "[sc_ap]"), + Self::OunceApothecaries => Definition::try_new_dimensional(8f64, "[dr_ap]"), + Self::PoundApothecaries => Definition::try_new_dimensional(12f64, "[oz_ap]"), + Self::MetricOunce => Definition::try_new_dimensional(28f64, "g"), + Self::Line => Definition::try_new_dimensional(1f64, "[in_i]/12"), + Self::Point => Definition::try_new_dimensional(1f64, "[lne]/6"), + Self::Pica => Definition::try_new_dimensional(12f64, "[pnt]"), + Self::PrintersPoint => Definition::try_new_dimensional(0.013837f64, "[in_i]"), + Self::PrintersPica => Definition::try_new_dimensional(12f64, "[pnt_pr]"), + Self::Pied => Definition::try_new_dimensional(32.48f64, "cm"), + Self::Pouce => Definition::try_new_dimensional(1f64, "[pied]/12"), + Self::Ligne => Definition::try_new_dimensional(1f64, "[pouce]/12"), + Self::Didot => Definition::try_new_dimensional(1f64, "[ligne]/6"), + Self::Cicero => Definition::try_new_dimensional(12f64, "[didot]"), + Self::DegreeFahrenheit => Definition::try_new_dimensional_special( 5f64, "K/9", - Some(FunctionSet { + FunctionSet { convert_from: |value: f64| 9.0 * value / 5.0 - 459.67, convert_to: |value: f64| 5.0 / 9.0 * (value + 459.67), - }), + }, ), - Self::DegreeRankine => Definition::new(5f64, "K/9", None), - Self::DegreeReaumur => Definition::new( + Self::DegreeRankine => Definition::try_new_dimensional(5f64, "K/9"), + Self::DegreeReaumur => Definition::try_new_dimensional_special( 5f64, "K/4", - Some(FunctionSet { + FunctionSet { convert_from: |value: f64| (value - 273.15) * 0.8, convert_to: |value: f64| (value / 0.8) + 273.15, - }), + }, ), - Self::CalorieAt15C => Definition::new(4.1858f64, "J", None), - Self::CalorieAt20C => Definition::new(4.1819f64, "J", None), - Self::MeanCalorie => Definition::new(4.19002f64, "J", None), - Self::InternationalTableCalorie => Definition::new(4.1868f64, "J", None), - Self::ThermochemicalCalorie => Definition::new(4.184f64, "J", None), - Self::Calorie => Definition::new(1f64, "cal_th", None), - Self::NutritionLabelCalories => Definition::new(1f64, "kcal_th", None), - Self::BritishThermalUnitAt39F => Definition::new(1.05967f64, "kJ", None), - Self::BritishThermalUnitAt59F => Definition::new(1.0548f64, "kJ", None), - Self::BritishThermalUnitAt60F => Definition::new(1.05468f64, "kJ", None), - Self::MeanBritishThermalUnit => Definition::new(1.05587f64, "kJ", None), + Self::CalorieAt15C => Definition::try_new_dimensional(4.1858f64, "J"), + Self::CalorieAt20C => Definition::try_new_dimensional(4.1819f64, "J"), + Self::MeanCalorie => Definition::try_new_dimensional(4.19002f64, "J"), + Self::InternationalTableCalorie => Definition::try_new_dimensional(4.1868f64, "J"), + Self::ThermochemicalCalorie => Definition::try_new_dimensional(4.184f64, "J"), + Self::Calorie => Definition::try_new_dimensional(1f64, "cal_th"), + Self::NutritionLabelCalories => Definition::try_new_dimensional(1f64, "kcal_th"), + Self::BritishThermalUnitAt39F => Definition::try_new_dimensional(1.05967f64, "kJ"), + Self::BritishThermalUnitAt59F => Definition::try_new_dimensional(1.0548f64, "kJ"), + Self::BritishThermalUnitAt60F => Definition::try_new_dimensional(1.05468f64, "kJ"), + Self::MeanBritishThermalUnit => Definition::try_new_dimensional(1.05587f64, "kJ"), Self::InternationalTableBritishThermalUnit => { - Definition::new(1.05505585262f64, "kJ", None) - } - Self::ThermochemicalBritishThermalUnit => Definition::new(1.05435f64, "kJ", None), - Self::BritishThermalUnit => Definition::new(1f64, "[Btu_th]", None), - Self::Horsepower => Definition::new(550f64, "[ft_i].[lbf_av]/s", None), - Self::Tex => Definition::new(1f64, "g/km", None), - Self::Denier => Definition::new(1f64, "g/9/km", None), - Self::MeterOfWaterColumn => Definition::new(9.80665f64, "kPa", None), - Self::MeterOfMercuryColumn => Definition::new(133.322f64, "kPa", None), - Self::InchOfWaterColumn => Definition::new(1f64, "m[H2O].[in_i]/m", None), - Self::InchOfMercuryColumn => Definition::new(1f64, "m[Hg].[in_i]/m", None), - Self::PeripheralVascularResistanceUnit => Definition::new(1f64, "mm[Hg].s/ml", None), - Self::WoodUnit => Definition::new(1f64, "mm[Hg].min/L", None), - Self::Diopter => Definition::new(1f64, "/m", None), - Self::PrismDiopter => Definition::new( + Definition::try_new_dimensional(1.05505585262f64, "kJ") + } + Self::ThermochemicalBritishThermalUnit => { + Definition::try_new_dimensional(1.05435f64, "kJ") + } + Self::BritishThermalUnit => Definition::try_new_dimensional(1f64, "[Btu_th]"), + Self::Horsepower => Definition::try_new_dimensional(550f64, "[ft_i].[lbf_av]/s"), + Self::Tex => Definition::try_new_dimensional(1f64, "g/km"), + Self::Denier => Definition::try_new_dimensional(1f64, "g/9/km"), + Self::MeterOfWaterColumn => Definition::try_new_dimensional(9.80665f64, "kPa"), + Self::MeterOfMercuryColumn => Definition::try_new_dimensional(133.322f64, "kPa"), + Self::InchOfWaterColumn => Definition::try_new_dimensional(1f64, "m[H2O].[in_i]/m"), + Self::InchOfMercuryColumn => Definition::try_new_dimensional(1f64, "m[Hg].[in_i]/m"), + Self::PeripheralVascularResistanceUnit => { + Definition::try_new_dimensional(1f64, "mm[Hg].s/ml") + } + Self::WoodUnit => Definition::try_new_dimensional(1f64, "mm[Hg].min/L"), + Self::Diopter => Definition::try_new_dimensional(1f64, "/m"), + Self::PrismDiopter => Definition::try_new_dimensional_special( 1f64, "rad", - Some(FunctionSet { + FunctionSet { convert_from: |value: f64| (value / 100.0).atan(), convert_to: |value: f64| value.tan() * 100.0, - }), + }, ), - Self::PercentOfSlope => Definition::new( + Self::PercentOfSlope => Definition::try_new_dimensional_special( 1f64, "deg", - Some(FunctionSet { + FunctionSet { convert_from: |value: f64| (value / 100.0).atan(), convert_to: |value: f64| value.tan() * 100.0, - }), - ), - Self::MeshInternational => Definition::new(1f64, "/[in_i]", None), - Self::Charriere => Definition::new(1f64, "mm/3", None), - Self::Drop => Definition::new(1f64, "ml/20", None), - Self::HounsfieldUnit => Ok(Definition::default()), - Self::MetabolicEquivalent => Definition::new(3.5f64, "mL/min/kg", None), - Self::HomeopathicPotencyOfDecimalSeriesRetired => Definition::new( - 1f64, - "1", - Some(FunctionSet { - convert_from: |value: f64| -value.log10(), - convert_to: |value: f64| 10_f64.powf(-value), - }), + }, ), - Self::HomeopathicPotencyOfCentesimalSeriesRetired => Definition::new( - 1f64, - "1", - Some(FunctionSet { - convert_from: |value: f64| -value.ln() / 100_f64.ln(), - convert_to: |value: f64| 100_f64.powf(-value), - }), - ), - Self::HomeopathicPotencyOfMillesimalSeriesRetired => Definition::new( - 1f64, - "1", - Some(FunctionSet { - convert_from: |value: f64| -value.ln() / 1_000_f64.ln(), - convert_to: |value: f64| 1_000_f64.powf(-value), - }), - ), - Self::HomeopathicPotencyOfQuintamillesimalSeriesRetired => Definition::new( - 1f64, - "1", - Some(FunctionSet { - convert_from: |value: f64| -value.ln() / 50_000_f64.ln(), - convert_to: |value: f64| 50_000_f64.powf(-value), - }), - ), - Self::HomeopathicPotencyOfDecimalHahnemannianSeries => Ok(Definition::default()), - Self::HomeopathicPotencyOfCentesimalHahnemannianSeries => Ok(Definition::default()), - Self::HomeopathicPotencyOfMillesimalHahnemannianSeries => Ok(Definition::default()), + Self::MeshInternational => Definition::try_new_dimensional(1f64, "/[in_i]"), + Self::Charriere => Definition::try_new_dimensional(1f64, "mm/3"), + Self::Drop => Definition::try_new_dimensional(1f64, "ml/20"), + Self::HounsfieldUnit => Ok(Definition::NonDimensional(1.0)), + Self::MetabolicEquivalent => Definition::try_new_dimensional(3.5f64, "mL/min/kg"), + Self::HomeopathicPotencyOfDecimalSeriesRetired => { + Ok(Definition::NonDimensionalSpecial { + value: 1f64, + function_set: FunctionSet { + convert_from: |value: f64| -value.log10(), + convert_to: |value: f64| 10_f64.powf(-value), + }, + }) + } + Self::HomeopathicPotencyOfCentesimalSeriesRetired => { + Ok(Definition::NonDimensionalSpecial { + value: 1f64, + function_set: FunctionSet { + convert_from: |value: f64| -value.ln() / 100_f64.ln(), + convert_to: |value: f64| 100_f64.powf(-value), + }, + }) + } + Self::HomeopathicPotencyOfMillesimalSeriesRetired => { + Ok(Definition::NonDimensionalSpecial { + value: 1f64, + function_set: FunctionSet { + convert_from: |value: f64| -value.ln() / 1_000_f64.ln(), + convert_to: |value: f64| 1_000_f64.powf(-value), + }, + }) + } + Self::HomeopathicPotencyOfQuintamillesimalSeriesRetired => { + Ok(Definition::NonDimensionalSpecial { + value: 1f64, + function_set: FunctionSet { + convert_from: |value: f64| -value.ln() / 50_000_f64.ln(), + convert_to: |value: f64| 50_000_f64.powf(-value), + }, + }) + } + Self::HomeopathicPotencyOfDecimalHahnemannianSeries => { + Ok(Definition::NonDimensional(1.0)) + } + Self::HomeopathicPotencyOfCentesimalHahnemannianSeries => { + Ok(Definition::NonDimensional(1.0)) + } + Self::HomeopathicPotencyOfMillesimalHahnemannianSeries => { + Ok(Definition::NonDimensional(1.0)) + } Self::HomeopathicPotencyOfQuintamillesimalHahnemannianSeries => { - Ok(Definition::default()) + Ok(Definition::NonDimensional(1.0)) + } + Self::HomeopathicPotencyOfDecimalKorsakovianSeries => { + Ok(Definition::NonDimensional(1.0)) + } + Self::HomeopathicPotencyOfCentesimalKorsakovianSeries => { + Ok(Definition::NonDimensional(1.0)) + } + Self::HomeopathicPotencyOfMillesimalKorsakovianSeries => { + Ok(Definition::NonDimensional(1.0)) } - Self::HomeopathicPotencyOfDecimalKorsakovianSeries => Ok(Definition::default()), - Self::HomeopathicPotencyOfCentesimalKorsakovianSeries => Ok(Definition::default()), - Self::HomeopathicPotencyOfMillesimalKorsakovianSeries => Ok(Definition::default()), Self::HomeopathicPotencyOfQuintamillesimalKorsakovianSeries => { - Ok(Definition::default()) + Ok(Definition::NonDimensional(1.0)) } - Self::Equivalents => Definition::new(1f64, "mol", None), - Self::Osmole => Definition::new(1f64, "mol", None), - Self::PH => Definition::new( + Self::Equivalents => Definition::try_new_dimensional(1f64, "mol"), + Self::Osmole => Definition::try_new_dimensional(1f64, "mol"), + Self::PH => Definition::try_new_dimensional_special( 1f64, "mol/l", - Some(FunctionSet { + FunctionSet { convert_from: |value: f64| 10.0_f64.powf(-value), convert_to: |value: f64| -value.log10(), - }), + }, ), - Self::GramPercent => Definition::new(1f64, "g/dl", None), - Self::SvedbergUnit => Definition::new(1f64, "10*-13.s", None), - Self::HighPowerField => Ok(Definition::default()), - Self::LowPowerField => Definition::new(100f64, "1", None), - Self::Katal => Definition::new(1f64, "mol/s", None), - Self::Unit => Definition::new(1f64, "umol/min", None), - Self::InternationalUnit => Ok(Definition::default()), - Self::InternationalUnitSecondary => Definition::new(1f64, "[iU]", None), - Self::ArbitraryUnit => Ok(Definition::default()), - Self::UnitedStatesPharmacopeiaUnit => Ok(Definition::default()), - Self::GplUnit => Ok(Definition::default()), - Self::MplUnit => Ok(Definition::default()), - Self::AplUnit => Ok(Definition::default()), - Self::BethesdaUnit => Ok(Definition::default()), - Self::AntiFactorXaUnit => Ok(Definition::default()), - Self::ToddUnit => Ok(Definition::default()), - Self::DyeUnit => Ok(Definition::default()), - Self::SomogyiUnit => Ok(Definition::default()), - Self::BodanskyUnit => Ok(Definition::default()), - Self::KingArmstrongUnit => Ok(Definition::default()), - Self::KunkelUnit => Ok(Definition::default()), - Self::MacLaganUnit => Ok(Definition::default()), - Self::TuberculinUnit => Ok(Definition::default()), - Self::CellCultureInfectiousDose => Ok(Definition::default()), - Self::TissueCultureInfectiousDose => Ok(Definition::default()), - Self::EmbryoInfectiousDose => Ok(Definition::default()), - Self::PlaqueFormingUnits => Ok(Definition::default()), - Self::FocusFormingUnits => Ok(Definition::default()), - Self::ColonyFormingUnits => Ok(Definition::default()), - Self::IndexOfReactivity => Ok(Definition::default()), - Self::BioequivalentAllergenUnit => Ok(Definition::default()), - Self::AllergenUnit => Ok(Definition::default()), - Self::AllergenUnitForAmbrosiaArtemisiifolia => Ok(Definition::default()), - Self::ProteinNitrogenUnit => Ok(Definition::default()), - Self::LimitOfFlocculation => Ok(Definition::default()), - Self::DAntigenUnit => Ok(Definition::default()), - Self::FibrinogenEquivalentUnit => Ok(Definition::default()), - Self::ElisaUnit => Ok(Definition::default()), - Self::EhrlichUnit => Ok(Definition::default()), - Self::Neper => Definition::new( - 1f64, - "1", - Some(FunctionSet { + Self::GramPercent => Definition::try_new_dimensional(1f64, "g/dl"), + Self::SvedbergUnit => Definition::try_new_dimensional(1f64, "10*-13.s"), + Self::HighPowerField => Ok(Definition::NonDimensional(1.0)), + Self::LowPowerField => Ok(Definition::NonDimensional(100.0)), + Self::Katal => Definition::try_new_dimensional(1f64, "mol/s"), + Self::Unit => Definition::try_new_dimensional(1f64, "umol/min"), + Self::InternationalUnit => Ok(Definition::NonDimensional(1.0)), + Self::InternationalUnitSecondary => Definition::try_new_dimensional(1f64, "[iU]"), + Self::ArbitraryUnit => Ok(Definition::NonDimensional(1.0)), + Self::UnitedStatesPharmacopeiaUnit => Ok(Definition::NonDimensional(1.0)), + Self::GplUnit => Ok(Definition::NonDimensional(1.0)), + Self::MplUnit => Ok(Definition::NonDimensional(1.0)), + Self::AplUnit => Ok(Definition::NonDimensional(1.0)), + Self::BethesdaUnit => Ok(Definition::NonDimensional(1.0)), + Self::AntiFactorXaUnit => Ok(Definition::NonDimensional(1.0)), + Self::ToddUnit => Ok(Definition::NonDimensional(1.0)), + Self::DyeUnit => Ok(Definition::NonDimensional(1.0)), + Self::SomogyiUnit => Ok(Definition::NonDimensional(1.0)), + Self::BodanskyUnit => Ok(Definition::NonDimensional(1.0)), + Self::KingArmstrongUnit => Ok(Definition::NonDimensional(1.0)), + Self::KunkelUnit => Ok(Definition::NonDimensional(1.0)), + Self::MacLaganUnit => Ok(Definition::NonDimensional(1.0)), + Self::TuberculinUnit => Ok(Definition::NonDimensional(1.0)), + Self::CellCultureInfectiousDose => Ok(Definition::NonDimensional(1.0)), + Self::TissueCultureInfectiousDose => Ok(Definition::NonDimensional(1.0)), + Self::EmbryoInfectiousDose => Ok(Definition::NonDimensional(1.0)), + Self::PlaqueFormingUnits => Ok(Definition::NonDimensional(1.0)), + Self::FocusFormingUnits => Ok(Definition::NonDimensional(1.0)), + Self::ColonyFormingUnits => Ok(Definition::NonDimensional(1.0)), + Self::IndexOfReactivity => Ok(Definition::NonDimensional(1.0)), + Self::BioequivalentAllergenUnit => Ok(Definition::NonDimensional(1.0)), + Self::AllergenUnit => Ok(Definition::NonDimensional(1.0)), + Self::AllergenUnitForAmbrosiaArtemisiifolia => Ok(Definition::NonDimensional(1.0)), + Self::ProteinNitrogenUnit => Ok(Definition::NonDimensional(1.0)), + Self::LimitOfFlocculation => Ok(Definition::NonDimensional(1.0)), + Self::DAntigenUnit => Ok(Definition::NonDimensional(1.0)), + Self::FibrinogenEquivalentUnit => Ok(Definition::NonDimensional(1.0)), + Self::ElisaUnit => Ok(Definition::NonDimensional(1.0)), + Self::EhrlichUnit => Ok(Definition::NonDimensional(1.0)), + Self::Neper => Ok(Definition::NonDimensionalSpecial { + value: 1.0, + function_set: FunctionSet { convert_from: f64::ln, convert_to: f64::exp, - }), - ), - Self::Bel => Definition::new( - 1f64, - "1", - Some(FunctionSet { + }, + }), + Self::Bel => Ok(Definition::NonDimensionalSpecial { + value: 1.0, + function_set: FunctionSet { convert_from: f64::log10, convert_to: |value: f64| 10_f64.powf(value), - }), - ), - Self::BelSoundPressure => Definition::new( + }, + }), + Self::BelSoundPressure => Definition::try_new_dimensional_special( 2f64, "10*-5.Pa", - Some(FunctionSet { + FunctionSet { convert_from: |value: f64| 2.0 * value.log10(), convert_to: |value: f64| 10_f64.powf(value / 2.0), - }), + }, ), - Self::BelVolt => Definition::new( + Self::BelVolt => Definition::try_new_dimensional_special( 1f64, "V", - Some(FunctionSet { + FunctionSet { convert_from: |value: f64| 2.0 * value.log10(), convert_to: |value: f64| 10_f64.powf(value / 2.0), - }), + }, ), - Self::BelMillivolt => Definition::new( + Self::BelMillivolt => Definition::try_new_dimensional_special( 1f64, "mV", - Some(FunctionSet { + FunctionSet { convert_from: |value: f64| 2.0 * value.log10(), convert_to: |value: f64| 10_f64.powf(value / 2.0), - }), + }, ), - Self::BelMicrovolt => Definition::new( + Self::BelMicrovolt => Definition::try_new_dimensional_special( 1f64, "uV", - Some(FunctionSet { + FunctionSet { convert_from: |value: f64| 2.0 * value.log10(), convert_to: |value: f64| 10_f64.powf(value / 2.0), - }), + }, ), - Self::Bel10Nanovolt => Definition::new( + Self::Bel10Nanovolt => Definition::try_new_dimensional_special( 10f64, "nV", - Some(FunctionSet { + FunctionSet { convert_from: |value: f64| 2.0 * value.log10(), convert_to: |value: f64| 10_f64.powf(value / 2.0), - }), + }, ), - Self::BelWatt => Definition::new( + Self::BelWatt => Definition::try_new_dimensional_special( 1f64, "W", - Some(FunctionSet { + FunctionSet { convert_from: f64::log10, convert_to: |value: f64| 10_f64.powf(value), - }), + }, ), - Self::BelKilowatt => Definition::new( + Self::BelKilowatt => Definition::try_new_dimensional_special( 1f64, "kW", - Some(FunctionSet { + FunctionSet { convert_from: f64::log10, convert_to: |value: f64| 10_f64.powf(value), - }), - ), - Self::Stere => Definition::new(1f64, "m3", None), - Self::Angstrom => Definition::new(0.1f64, "nm", None), - Self::Barn => Definition::new(100f64, "fm2", None), - Self::TechnicalAtmosphere => Definition::new(1f64, "kgf/cm2", None), - Self::Mho => Definition::new(1f64, "S", None), - Self::PoundPerSqareInch => Definition::new(1f64, "[lbf_av]/[in_i]2", None), - Self::Circle => Definition::new(2f64, "[pi].rad", None), - Self::Spere => Definition::new(4f64, "[pi].sr", None), - Self::MetricCarat => Definition::new(0.2f64, "g", None), - Self::CaratOfGoldAlloys => Definition::new(1f64, "/24", None), - Self::Smoot => Definition::new(67f64, "[in_i]", None), - Self::MeterPerSquareSecondsPerSquareRootOfHertz => Definition::new( - 1f64, - "m2/s4/Hz", - Some(FunctionSet { - convert_from: f64::sqrt, - convert_to: |value: f64| value * value, - }), + }, ), - Self::BitLogarithmusDualis => Definition::new( - 1f64, - "1", - Some(FunctionSet { + Self::Stere => Definition::try_new_dimensional(1f64, "m3"), + Self::Angstrom => Definition::try_new_dimensional(0.1f64, "nm"), + Self::Barn => Definition::try_new_dimensional(100f64, "fm2"), + Self::TechnicalAtmosphere => Definition::try_new_dimensional(1f64, "kgf/cm2"), + Self::Mho => Definition::try_new_dimensional(1f64, "S"), + Self::PoundPerSqareInch => Definition::try_new_dimensional(1f64, "[lbf_av]/[in_i]2"), + Self::Circle => Definition::try_new_dimensional(2f64, "[pi].rad"), + Self::Spere => Definition::try_new_dimensional(4f64, "[pi].sr"), + Self::MetricCarat => Definition::try_new_dimensional(0.2f64, "g"), + Self::CaratOfGoldAlloys => Definition::try_new_dimensional(1f64, "/24"), + Self::Smoot => Definition::try_new_dimensional(67f64, "[in_i]"), + Self::MeterPerSquareSecondsPerSquareRootOfHertz => { + Definition::try_new_dimensional_special( + 1f64, + "m2/s4/Hz", + FunctionSet { + convert_from: f64::sqrt, + convert_to: |value: f64| value * value, + }, + ) + } + Self::BitLogarithmusDualis => Ok(Definition::NonDimensionalSpecial { + value: 1f64, + function_set: FunctionSet { convert_from: f64::log2, convert_to: f64::exp2, - }), - ), - Self::Bit => Ok(Definition::default()), - Self::Byte => Definition::new(8f64, "bit", None), - Self::Baud => Definition::new(1f64, "/s", None), + }, + }), + Self::Bit => Ok(Definition::NonDimensional(1.0)), + Self::Byte => Definition::try_new_dimensional(8f64, "bit"), + Self::Baud => Definition::try_new_dimensional(1f64, "/s"), }; result.expect("BUG! Bad Atom -> Definition mapping!") } diff --git a/api/src/parser/atom/reducible.rs b/api/src/parser/atom/reducible.rs index bdf4f91a..34d132d5 100644 --- a/api/src/parser/atom/reducible.rs +++ b/api/src/parser/atom/reducible.rs @@ -1,6 +1,6 @@ use crate::{reducible::Reducible, Atom, UcumUnit}; -impl Reducible for Atom { +impl Reducible for Atom { fn reduce_value(&self, value: f64) -> f64 { self.definition().reduce_value(value) } diff --git a/api/src/parser/atom_test.rs b/api/src/parser/atom_test.rs index b57fc125..59ad27e7 100644 --- a/api/src/parser/atom_test.rs +++ b/api/src/parser/atom_test.rs @@ -3,7 +3,10 @@ #![cfg(test)] use crate::{ - parser::{Atom, Classification, Composable, Composition, Dimension, Prefix, Term, UcumSymbol}, + parser::{ + term::UNITY_ARRAY, Atom, Classification, Composable, Composition, Dimension, Prefix, Term, + UcumSymbol, + }, ucum_unit::UcumUnit, }; use approx::{assert_relative_eq, assert_ulps_eq}; @@ -18,11 +21,11 @@ macro_rules! validate_definition { #[test] fn $test_name() { let atom = Atom::$atom_name; - let expected = vec![$($expected_term),+]; + let expected = [$($expected_term),+]; assert_relative_eq!(atom.definition().value(), $expected_value); assert_ulps_eq!(atom.definition().value(), $expected_value); - assert_eq!(atom.definition().terms(), expected.as_slice()); + assert_eq!(*atom.definition().terms(), expected.as_slice()); } }; } @@ -207,12 +210,11 @@ fn validate_definitions_base_atoms() { Atom::Radian, Atom::Second, ]; - let terms = vec![Term::new_unity()]; for base_atom in base_atoms { assert_relative_eq!(base_atom.definition().value(), 1.0); assert_ulps_eq!(base_atom.definition().value(), 1.0); - assert_eq!(base_atom.definition().terms(), terms.as_slice()); + assert_eq!(*base_atom.definition().terms(), UNITY_ARRAY.as_slice()); } } @@ -297,6 +299,13 @@ validate_definition!( 1.0, term!(Deci, Meter, exponent: 3) ); +validate_definition!( + validate_definition_ten_star, + TheNumberTenForArbitraryPowersStar, + 10.0, + term!(factor: 1) +); +validate_definition!(validate_definition_percent, Percent, 0.01, term!(factor: 1)); validate_definition!( validate_definition_mole, Mole, diff --git a/api/src/parser/definition.rs b/api/src/parser/definition.rs index a859d8d4..09d92a3b 100644 --- a/api/src/parser/definition.rs +++ b/api/src/parser/definition.rs @@ -1,86 +1,105 @@ #![allow(clippy::large_enum_variant)] #![allow(clippy::result_large_err)] +use std::borrow::Cow; + +use num_traits::One; + use crate::{ parser::{function_set::FunctionSet, Error, Term}, reducible::Reducible, }; +use super::term; + /// A `Definition` is a slimmed-down version of a `Measurement` that is used to /// define `Atom`s in terms of other `Atom`s (ex. an `"[in_i]"` has a /// `Definition` of 2.54 cm). /// -#[derive(Debug)] -pub(crate) struct Definition { - value: f64, - terms: Vec, - - /// Conversion functions only required for special (non-ratio based) atoms. - function_set: Option, +pub(crate) enum Definition { + Base, + NonDimensional(V), + NonDimensionalSpecial { + value: V, + function_set: FunctionSet, + }, + Dimensional { + value: V, + terms: Cow<'static, [Term]>, + }, + DimensionalSpecial { + value: V, + terms: Cow<'static, [Term]>, + function_set: FunctionSet, + }, } -impl Definition { - pub(crate) fn new( - value: f64, - expression: &str, - function_set: Option, - ) -> Result { - let terms = super::parse(expression)?; - - Ok(Self { +impl Definition { + pub(crate) fn try_new_dimensional(value: V, expression: &'static str) -> Result { + Ok(Self::Dimensional { value, - terms, - function_set, + terms: Cow::Owned(super::parse(expression)?), }) } - pub(crate) const fn value(&self) -> f64 { - self.value + pub(crate) fn try_new_dimensional_special( + value: V, + expression: &'static str, + function_set: FunctionSet, + ) -> Result { + Ok(Self::DimensionalSpecial { + value, + terms: Cow::Owned(super::parse(expression)?), + function_set, + }) } - pub(crate) const fn terms(&self) -> &Vec { - &self.terms + pub(crate) fn value(&self) -> V + where + V: One + Clone, + { + match self { + Self::Base => ::one(), + Self::NonDimensional(value) => value.clone(), + Self::NonDimensionalSpecial { value, .. } + | Self::Dimensional { value, .. } + | Self::DimensionalSpecial { value, .. } => (*value).clone(), + } } - pub(crate) fn is_unity(&self) -> bool { - self.terms.len() == 1 && self.terms[0].is_unity() + pub(crate) const fn terms(&self) -> &Cow<'static, [Term]> { + match self { + Self::Base => &Cow::Borrowed(term::UNITY_ARRAY_REF), + Self::NonDimensional(_) | Self::NonDimensionalSpecial { .. } => { + &Cow::Borrowed(term::UNITY_ARRAY_REF) + } + Self::Dimensional { terms, .. } | Self::DimensionalSpecial { terms, .. } => terms, + } } } -impl Reducible for Definition { +impl Reducible for Definition { fn reduce_value(&self, other_value: f64) -> f64 { - self.function_set.as_ref().map_or_else( - || { - if self.is_unity() { - self.value - } else { - self.value * self.terms.reduce_value(other_value) - } - }, - |f| (f.convert_to)(other_value), - ) + match self { + Self::Base => 1.0, + Self::NonDimensional(value) => *value, + Self::Dimensional { value, terms } => value * terms.reduce_value(other_value), + Self::NonDimensionalSpecial { function_set, .. } + | Self::DimensionalSpecial { function_set, .. } => { + (function_set.convert_to)(other_value) + } + } } fn calculate_magnitude(&self, other_value: f64) -> f64 { - self.function_set.as_ref().map_or_else( - || { - if self.is_unity() { - self.value - } else { - self.value * self.terms.calculate_magnitude(other_value) - } - }, - |f| (f.convert_from)(other_value), - ) - } -} - -impl Default for Definition { - fn default() -> Self { - Self { - value: 1.0, - terms: vec![Term::new_unity()], - function_set: None, + match self { + Self::Base => 1.0, + Self::NonDimensional(value) => *value, + Self::Dimensional { value, terms } => value * terms.calculate_magnitude(other_value), + Self::NonDimensionalSpecial { function_set, .. } + | Self::DimensionalSpecial { function_set, .. } => { + (function_set.convert_from)(other_value) + } } } } diff --git a/api/src/parser/function_set.rs b/api/src/parser/function_set.rs index 0ce52e8b..69826b0a 100644 --- a/api/src/parser/function_set.rs +++ b/api/src/parser/function_set.rs @@ -1,11 +1,11 @@ /// This is a struct to allow for representing functions that special units use /// for converting to and from their base unit. /// -#[derive(Debug, PartialEq)] -pub(crate) struct FunctionSet { +#[derive(Debug, Clone, Copy, PartialEq)] +pub(crate) struct FunctionSet { // AKA "calculate_magnitude" - pub(crate) convert_from: fn(value: f64) -> f64, + pub(crate) convert_from: fn(value: V) -> V, // AKA "reduce_value" - pub(crate) convert_to: fn(value: f64) -> f64, + pub(crate) convert_to: fn(value: V) -> V, } diff --git a/api/src/parser/prefix.rs b/api/src/parser/prefix.rs index e53b4d02..a390c8c1 100644 --- a/api/src/parser/prefix.rs +++ b/api/src/parser/prefix.rs @@ -1,10 +1,7 @@ use super::{Error, Visit}; use crate::{ - parser::{ - definition::Definition, symbols::symbol_parser::Rule, ucum_symbol::UcumSymbol, - Classification, - }, - unit::Unit, + parser::{symbols::symbol_parser::Rule, ucum_symbol::UcumSymbol, Classification}, + unit::{self, Unit}, }; use pest::iterators::Pair; use std::fmt; @@ -201,9 +198,7 @@ impl UcumSymbol for Prefix { } fn definition_unit(&self) -> Unit { - let definition = Definition::default(); - - Unit::new(definition.terms().clone()) + unit::UNITY } } diff --git a/api/src/parser/term.rs b/api/src/parser/term.rs index d3aa44c7..e4d862d3 100644 --- a/api/src/parser/term.rs +++ b/api/src/parser/term.rs @@ -10,6 +10,10 @@ mod ucum_unit; use crate::parser::{Atom, Prefix}; +pub const UNITY: Term = Term::new_unity(); +pub const UNITY_ARRAY: [Term; 1] = [UNITY]; +pub const UNITY_ARRAY_REF: &[Term; 1] = &UNITY_ARRAY; + /// A Term makes up an Atom (at its core) along with any Atom modifiers /// (anything that can change its scalar). It is, however, possible to have an /// Atom-less Term, which would simple be a Factor (with or without an diff --git a/api/src/parser/term/composable.rs b/api/src/parser/term/composable.rs index c90b2be9..47cf8927 100644 --- a/api/src/parser/term/composable.rs +++ b/api/src/parser/term/composable.rs @@ -1,6 +1,9 @@ -use super::Term; +use std::borrow::Cow; + use crate::parser::{Composable, Composition}; +use super::Term; + impl Composable for Term { /// Combines the `Composition` from the `Term`'s `Atom` with its own `exponent` to build a /// `Composition`. If the `Term` has no `Atom`, it has no dimension, thus will have an empty @@ -22,7 +25,7 @@ impl Composable for Term { } } -impl Composable for Vec { +impl<'a> Composable for Cow<'a, [Term]> { fn composition(&self) -> Composition { self.iter() .fold(Composition::default(), |acc, term| acc * term.composition()) diff --git a/api/src/parser/term/invert.rs b/api/src/parser/term/invert.rs index b54f4c49..7c1f3143 100644 --- a/api/src/parser/term/invert.rs +++ b/api/src/parser/term/invert.rs @@ -1,7 +1,11 @@ +use std::borrow::Cow; + use super::Term; use crate::invert::{Invert, ToInverse}; -// Term +// ╭──────╮ +// │ Term │ +// ╰──────╯ impl Invert for &mut Term { fn invert(self) { self.exponent = self.exponent.map_or(Some(-1), |e| match e { @@ -22,7 +26,9 @@ impl ToInverse for Term { } } -// Vec +// ╭───────────╮ +// │ Vec │ +// ╰───────────╯ impl Invert for &mut Vec { fn invert(self) { for term in self.iter_mut() { @@ -39,6 +45,25 @@ impl ToInverse for Vec { } } +// ╭─────────────────╮ +// │ Cow<'a, [Term]> │ +// ╰─────────────────╯ +impl<'a> Invert for &mut Cow<'a, [Term]> { + fn invert(self) { + for term in self.to_mut().iter_mut() { + term.invert(); + } + } +} + +impl<'a> ToInverse for Cow<'a, [Term]> { + type Output = Self; + + fn to_inverse(&self) -> Self::Output { + self.iter().map(ToInverse::to_inverse).collect() + } +} + #[cfg(test)] mod tests { mod term { diff --git a/api/src/parser/term/is_compatible_with.rs b/api/src/parser/term/is_compatible_with.rs index 8e2396ed..3710805a 100644 --- a/api/src/parser/term/is_compatible_with.rs +++ b/api/src/parser/term/is_compatible_with.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use crate::{ is_compatible_with::IsCompatibleWith, parser::{annotation_composition::AnnotationComposable, Composable, Term}, @@ -38,7 +40,7 @@ impl IsCompatibleWith for Term { } } -impl IsCompatibleWith for Vec { +impl<'a> IsCompatibleWith for Cow<'a, [Term]> { fn is_compatible_with(&self, rhs: &Self) -> bool { let lhs_annotation_composition = self.annotation_composition(); let rhs_annotation_composition = rhs.annotation_composition(); @@ -81,22 +83,22 @@ mod tests { #[test] fn validate_terms() { - let lhs = vec![term!(Meter)]; - let rhs = vec![term!(Kilo, Meter)]; + let lhs = terms![term!(Meter)]; + let rhs = terms![term!(Kilo, Meter)]; assert!(lhs.is_compatible_with(&rhs)); } #[test] fn validate_terms_with_factor() { - let lhs = vec![term!(Meter)]; - let rhs = vec![term!(Kilo, Meter, factor: 20)]; + let lhs = terms![term!(Meter)]; + let rhs = terms![term!(Kilo, Meter, factor: 20)]; assert!(lhs.is_compatible_with(&rhs)); } #[test] fn validate_terms_with_factor_and_exponent() { - let lhs = vec![term!(Meter)]; - let rhs = vec![term!(Kilo, Meter, factor: 20, exponent: 2)]; + let lhs = terms![term!(Meter)]; + let rhs = terms![term!(Kilo, Meter, factor: 20, exponent: 2)]; assert!(!lhs.is_compatible_with(&rhs)); } } @@ -121,16 +123,16 @@ mod tests { #[test] fn validate_terms() { - let m = vec![term!(Meter, annotation: "stuff".to_string())]; - let km_stuff = vec![term!(Kilo, Meter, annotation: "stuff".to_string())]; + let m = terms![term!(Meter, annotation: "stuff".to_string())]; + let km_stuff = terms![term!(Kilo, Meter, annotation: "stuff".to_string())]; assert!(m.is_compatible_with(&km_stuff)); // Different annotation - let km_pants = vec![term!(Kilo, Meter, annotation: "pants".to_string())]; + let km_pants = terms![term!(Kilo, Meter, annotation: "pants".to_string())]; assert!(!m.is_compatible_with(&km_pants)); // No annotation - let km_no_annotation = vec![term!(Kilo, Meter)]; + let km_no_annotation = terms![term!(Kilo, Meter)]; assert!(!m.is_compatible_with(&km_no_annotation)); } diff --git a/api/src/parser/term/reducible.rs b/api/src/parser/term/reducible.rs index f373ff2b..6ee1fe5d 100644 --- a/api/src/parser/term/reducible.rs +++ b/api/src/parser/term/reducible.rs @@ -1,10 +1,13 @@ #![allow(clippy::large_enum_variant)] #![allow(clippy::result_large_err)] -use super::Term; +use std::borrow::Cow; + use crate::{parser::ucum_symbol::UcumSymbol, reducible::Reducible}; -impl Reducible for Term { +use super::Term; + +impl Reducible for Term { fn reduce_value(&self, value: f64) -> f64 { let atom_scalar = self.atom.map_or(1.0, |a| a.reduce_value(value)); let prefix_scalar = self.prefix.map_or(1.0, |p| p.definition_value()); @@ -20,7 +23,7 @@ impl Reducible for Term { } } -impl Reducible for Vec { +impl<'a> Reducible for Cow<'a, [Term]> { fn reduce_value(&self, value: f64) -> f64 { self.iter() .fold(1.0, |acc, term| acc * term.reduce_value(value)) diff --git a/api/src/reducible.rs b/api/src/reducible.rs index 7b31dcd7..9dcf427b 100644 --- a/api/src/reducible.rs +++ b/api/src/reducible.rs @@ -1,7 +1,7 @@ -pub(crate) trait Reducible { +pub(crate) trait Reducible { /// Calculates `value` count of `self` in terms of `self`'s base-unit. /// - fn reduce_value(&self, value: f64) -> f64; + fn reduce_value(&self, value: V) -> V; - fn calculate_magnitude(&self, value: f64) -> f64; + fn calculate_magnitude(&self, value: V) -> V; } diff --git a/api/src/unit.rs b/api/src/unit.rs index 4c379635..573c3b43 100644 --- a/api/src/unit.rs +++ b/api/src/unit.rs @@ -21,12 +21,20 @@ pub mod custom_ffi; #[cfg(feature = "serde")] mod serde; -use crate::{parser::Term, Error}; -use std::str::FromStr; +use std::{borrow::Cow, str::FromStr}; #[cfg(feature = "cffi")] use ffi_common::derive::FFI; +use crate::{ + parser::{term, Term}, + Error, +}; + +pub const UNITY: Unit = Unit { + terms: Cow::Borrowed(term::UNITY_ARRAY_REF), +}; + #[cfg_attr( feature = "cffi", derive(FFI), @@ -38,7 +46,7 @@ use ffi_common::derive::FFI; )] #[derive(Clone, Debug)] pub struct Unit { - terms: Vec, + terms: Cow<'static, [Term]>, } /// A `Unit` is the piece of data that represents a *valid* UCUM unit or @@ -71,23 +79,26 @@ impl Unit { /// ``` /// #[must_use] - pub fn new(terms: Vec) -> Self { - Self { terms } + pub fn new(terms: T) -> Self + where + Cow<'static, [Term]>: From, + { + Self { + terms: Cow::from(terms), + } } /// Creates a new `Unit` that's equivalent to "1". /// #[must_use] pub fn new_unity() -> Self { - Self { - terms: vec![Term::new_unity()], - } + UNITY } /// Accessor for the `Term`s used that make up this `Unit`. /// #[must_use] - pub const fn terms(&self) -> &Vec { + pub const fn terms(&self) -> &Cow<'static, [Term]> { &self.terms } diff --git a/api/src/unit/deref.rs b/api/src/unit/deref.rs index 7707a944..9b8e7105 100644 --- a/api/src/unit/deref.rs +++ b/api/src/unit/deref.rs @@ -7,6 +7,6 @@ impl ::std::ops::Deref for Unit { type Target = [Term]; fn deref(&self) -> &[Term] { - self.terms.as_slice() + &*self.terms } } diff --git a/api/src/unit/is_compatible_with.rs b/api/src/unit/is_compatible_with.rs index 30d4faf2..f3eb5a85 100644 --- a/api/src/unit/is_compatible_with.rs +++ b/api/src/unit/is_compatible_with.rs @@ -1,3 +1,5 @@ +use std::borrow::Cow; + use crate::{ is_compatible_with::IsCompatibleWith, measurement::Measurement, parser::Term, unit::Unit, }; @@ -10,8 +12,8 @@ impl IsCompatibleWith for Unit { } } -impl IsCompatibleWith> for Unit { - fn is_compatible_with(&self, rhs: &Vec) -> bool { +impl<'a> IsCompatibleWith> for Unit { + fn is_compatible_with(&self, rhs: &Cow<'a, [Term]>) -> bool { self.terms.is_compatible_with(rhs) } } diff --git a/api/src/unit/reducible.rs b/api/src/unit/reducible.rs index ed442780..e8fae183 100644 --- a/api/src/unit/reducible.rs +++ b/api/src/unit/reducible.rs @@ -3,7 +3,7 @@ use crate::{reducible::Reducible, unit::Unit}; //----------------------------------------------------------------------------- // impl Reducible //----------------------------------------------------------------------------- -impl Reducible for Unit { +impl Reducible for Unit { fn reduce_value(&self, value: f64) -> f64 { self.terms.reduce_value(value) } From c345ad0d8205713ad394b39aad9067fbd93b0931 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 2 Feb 2024 16:53:46 -0800 Subject: [PATCH 31/80] Add bacon.toml --- bacon.toml | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 bacon.toml diff --git a/bacon.toml b/bacon.toml new file mode 100644 index 00000000..dee86246 --- /dev/null +++ b/bacon.toml @@ -0,0 +1,95 @@ +# This is a configuration file for the bacon tool +# +# Bacon repository: https://github.com/Canop/bacon +# Complete help on configuration: https://dystroy.org/bacon/config/ +# You can also check bacon's own bacon.toml file +# as an example: https://github.com/Canop/bacon/blob/main/bacon.toml + +default_job = "check" + +[jobs.check] +command = ["cargo", "check", "--color", "always"] +need_stdout = false + +[jobs.check-all] +command = ["cargo", "check", "--all-targets", "--color", "always"] +need_stdout = false + +[jobs.clippy] +command = ["cargo", "clippy", "--all-targets", "--color", "always"] +need_stdout = false + +# This job lets you run +# - all tests: bacon test +# - a specific test: bacon test -- config::test_default_files +# - the tests of a package: bacon test -- -- -p config +[jobs.test] +command = [ + "cargo", + "test", + "--color", + "always", + "--", + "--color", + "always", # see https://github.com/Canop/bacon/issues/124 +] +need_stdout = true + +[jobs.test-all] +command = [ + "cargo", + "test", + "--all-features", + "--color", + "always", + "--", + "--color", + "always", # see https://github.com/Canop/bacon/issues/124 +] +need_stdout = true + +[jobs.doc] +command = ["cargo", "doc", "--color", "always", "--no-deps"] +need_stdout = false + +# If the doc compiles, then it opens in your browser and bacon switches +# to the previous job +[jobs.doc-open] +command = ["cargo", "doc", "--color", "always", "--no-deps", "--open"] +need_stdout = false +on_success = "back" # so that we don't open the browser at each change + +# You can run your application and have the result displayed in bacon, +# *if* it makes sense for this crate. +# Don't forget the `--color always` part or the errors won't be +# properly parsed. +# If your program never stops (eg a server), you may set `background` +# to false to have the cargo run output immediately displayed instead +# of waiting for program's end. +[jobs.run] +command = [ + "cargo", + "run", + "--color", + "always", + # put launch parameters for your program behind a `--` separator +] +need_stdout = true +allow_warnings = true +background = true + +# This parameterized job runs the example of your choice, as soon +# as the code compiles. +# Call it as +# bacon ex -- my-example +[jobs.ex] +command = ["cargo", "run", "--color", "always", "--example"] +need_stdout = true +allow_warnings = true + +# You may define here keybindings that would be specific to +# a project, for example a shortcut to launch a specific job. +# Shortcuts to internal functions (scrolling, toggling, etc.) +# should go in your personal global prefs.toml file instead. +[keybindings] +# alt-m = "job:my-job" From 97af09f238cbf53e2d6dcf6b137a708ac875f997 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 2 Feb 2024 16:57:45 -0800 Subject: [PATCH 32/80] clippy --- api/benches/measurements_benchmarks.rs | 1 - api/benches/unit_benchmarks.rs | 1 - api/src/parser.rs | 2 +- api/src/parser/terms/mapper.rs | 22 +++++++++++----------- api/src/parser/terms/mapper/ast_term.rs | 2 +- api/src/unit.rs | 5 +++-- api/src/unit/deref.rs | 2 +- api/src/unit/ops.rs | 2 +- 8 files changed, 18 insertions(+), 19 deletions(-) diff --git a/api/benches/measurements_benchmarks.rs b/api/benches/measurements_benchmarks.rs index 0a252079..9cafa4c6 100644 --- a/api/benches/measurements_benchmarks.rs +++ b/api/benches/measurements_benchmarks.rs @@ -71,4 +71,3 @@ criterion_group!( convert_to_unit_group, ); criterion_main!(measurement_benches); - diff --git a/api/benches/unit_benchmarks.rs b/api/benches/unit_benchmarks.rs index 360151a0..5b073e14 100644 --- a/api/benches/unit_benchmarks.rs +++ b/api/benches/unit_benchmarks.rs @@ -149,4 +149,3 @@ criterion_group!( partial_ord_gt_group, ); criterion_main!(unit_benches); - diff --git a/api/src/parser.rs b/api/src/parser.rs index 14a3af33..b8edd2f3 100644 --- a/api/src/parser.rs +++ b/api/src/parser.rs @@ -18,7 +18,7 @@ pub mod composition; #[allow(clippy::non_ascii_literal)] pub mod property; -pub(self) mod symbols; +mod symbols; mod annotation_composition; #[cfg(test)] diff --git a/api/src/parser/terms/mapper.rs b/api/src/parser/terms/mapper.rs index 48da2451..146797c3 100644 --- a/api/src/parser/terms/mapper.rs +++ b/api/src/parser/terms/mapper.rs @@ -3,17 +3,17 @@ // Internal structs for mapping parser Rule data to an intermediate // representation of a Unit. -pub(self) mod annotatable; -pub(self) mod annotation; -pub(self) mod ast_term; -pub(self) mod basic_component; -pub(self) mod component; -pub(self) mod digits; -pub(self) mod exponent; -pub(self) mod factor; -pub(self) mod finishable; -pub(self) mod main_term; -pub(self) mod simple_unit; +mod annotatable; +mod annotation; +mod ast_term; +mod basic_component; +mod component; +mod digits; +mod exponent; +mod factor; +mod finishable; +mod main_term; +mod simple_unit; use self::{ annotatable::Annotatable, annotation::Annotation, ast_term::AstTerm, diff --git a/api/src/parser/terms/mapper/ast_term.rs b/api/src/parser/terms/mapper/ast_term.rs index 27e33b85..b7392a24 100644 --- a/api/src/parser/terms/mapper/ast_term.rs +++ b/api/src/parser/terms/mapper/ast_term.rs @@ -65,7 +65,7 @@ enum SecondToken { impl Finishable for AstTerm { fn finish(self) -> Vec { let mut component_terms = self.component.finish(); - component_terms.extend(self.terms.into_iter()); + component_terms.extend(self.terms); component_terms } diff --git a/api/src/unit.rs b/api/src/unit.rs index 573c3b43..84eb1b9d 100644 --- a/api/src/unit.rs +++ b/api/src/unit.rs @@ -90,8 +90,9 @@ impl Unit { /// Creates a new `Unit` that's equivalent to "1". /// + #[deprecated(since = "0.23.0", note = "Please use unit::UNITY instead")] #[must_use] - pub fn new_unity() -> Self { + pub const fn new_unity() -> Self { UNITY } @@ -178,7 +179,7 @@ mod tests { #[test] fn validate_is_unity() { - let unit = Unit::new_unity(); + let unit = UNITY; assert!(unit.is_unity()); let unit = Unit::new(Vec::new()); diff --git a/api/src/unit/deref.rs b/api/src/unit/deref.rs index 9b8e7105..11263035 100644 --- a/api/src/unit/deref.rs +++ b/api/src/unit/deref.rs @@ -7,6 +7,6 @@ impl ::std::ops::Deref for Unit { type Target = [Term]; fn deref(&self) -> &[Term] { - &*self.terms + &self.terms } } diff --git a/api/src/unit/ops.rs b/api/src/unit/ops.rs index 94ec3b44..0337b545 100644 --- a/api/src/unit/ops.rs +++ b/api/src/unit/ops.rs @@ -9,7 +9,7 @@ fn divide_terms(lhs: &[Term], rhs: &[Term]) -> Vec { let mut terms = Vec::with_capacity(lhs.len() + rhs.len()); terms.extend_from_slice(lhs); - for term in rhs.iter() { + for term in rhs { terms.push(term.to_inverse()); } From f522e753578c09905912578060dba339b2742117 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 5 Feb 2024 11:08:57 -0800 Subject: [PATCH 33/80] PLCC-286 Move crates to crates/ --- Cargo.toml | 2 +- {api => crates/api}/CHANGELOG.md | 0 {api => crates/api}/Cargo.toml | 0 {api => crates/api}/benches/common.rs | 0 {api => crates/api}/benches/measurements_benchmarks.rs | 0 {api => crates/api}/benches/unit_benchmarks.rs | 0 {api => crates/api}/src/as_fraction.rs | 0 {api => crates/api}/src/convertible.rs | 0 {api => crates/api}/src/error.rs | 0 {api => crates/api}/src/field_eq.rs | 0 {api => crates/api}/src/invert.rs | 0 {api => crates/api}/src/is_compatible_with.rs | 0 {api => crates/api}/src/lib.rs | 0 {api => crates/api}/src/macros.rs | 0 {api => crates/api}/src/measurement.rs | 0 {api => crates/api}/src/measurement/composable.rs | 0 {api => crates/api}/src/measurement/convertible.rs | 0 {api => crates/api}/src/measurement/display.rs | 0 {api => crates/api}/src/measurement/field_eq.rs | 0 {api => crates/api}/src/measurement/invert.rs | 0 {api => crates/api}/src/measurement/is_compatible_with.rs | 0 {api => crates/api}/src/measurement/ops.rs | 0 {api => crates/api}/src/measurement/partial_eq.rs | 0 {api => crates/api}/src/measurement/partial_ord.rs | 0 {api => crates/api}/src/measurement/reducible.rs | 0 {api => crates/api}/src/measurement/to_reduced.rs | 0 {api => crates/api}/src/measurement/ucum_unit.rs | 0 {api => crates/api}/src/parser.rs | 0 {api => crates/api}/src/parser/annotation_composition.rs | 0 {api => crates/api}/src/parser/atom.rs | 0 {api => crates/api}/src/parser/atom/composable.rs | 0 {api => crates/api}/src/parser/atom/display.rs | 0 {api => crates/api}/src/parser/atom/hash.rs | 0 {api => crates/api}/src/parser/atom/partial_eq.rs | 0 {api => crates/api}/src/parser/atom/reducible.rs | 0 {api => crates/api}/src/parser/atom_test.rs | 0 {api => crates/api}/src/parser/classification.rs | 0 {api => crates/api}/src/parser/composable.rs | 0 {api => crates/api}/src/parser/composition.rs | 0 {api => crates/api}/src/parser/definition.rs | 0 {api => crates/api}/src/parser/dimension.rs | 0 {api => crates/api}/src/parser/error.rs | 0 {api => crates/api}/src/parser/function_set.rs | 0 {api => crates/api}/src/parser/prefix.rs | 0 {api => crates/api}/src/parser/property.rs | 0 {api => crates/api}/src/parser/symbols.rs | 0 {api => crates/api}/src/parser/symbols/mapper.rs | 0 {api => crates/api}/src/parser/symbols/symbol.pest | 0 {api => crates/api}/src/parser/symbols/symbol.rs | 0 {api => crates/api}/src/parser/symbols/symbol_parser.rs | 0 {api => crates/api}/src/parser/symbols/symbol_parser_test.rs | 0 {api => crates/api}/src/parser/term.rs | 0 {api => crates/api}/src/parser/term/annotation_composable.rs | 0 {api => crates/api}/src/parser/term/composable.rs | 0 {api => crates/api}/src/parser/term/display.rs | 0 {api => crates/api}/src/parser/term/field_eq.rs | 0 {api => crates/api}/src/parser/term/invert.rs | 0 {api => crates/api}/src/parser/term/is_compatible_with.rs | 0 {api => crates/api}/src/parser/term/partial_eq.rs | 0 {api => crates/api}/src/parser/term/reducible.rs | 0 {api => crates/api}/src/parser/term/ucum_unit.rs | 0 {api => crates/api}/src/parser/terms.rs | 0 {api => crates/api}/src/parser/terms/mapper.rs | 0 {api => crates/api}/src/parser/terms/mapper/annotatable.rs | 0 {api => crates/api}/src/parser/terms/mapper/annotation.rs | 0 {api => crates/api}/src/parser/terms/mapper/ast_term.rs | 0 {api => crates/api}/src/parser/terms/mapper/basic_component.rs | 0 {api => crates/api}/src/parser/terms/mapper/component.rs | 0 {api => crates/api}/src/parser/terms/mapper/digits.rs | 0 {api => crates/api}/src/parser/terms/mapper/exponent.rs | 0 {api => crates/api}/src/parser/terms/mapper/factor.rs | 0 {api => crates/api}/src/parser/terms/mapper/finishable.rs | 0 {api => crates/api}/src/parser/terms/mapper/main_term.rs | 0 {api => crates/api}/src/parser/terms/mapper/simple_unit.rs | 0 {api => crates/api}/src/parser/terms/term.pest | 0 {api => crates/api}/src/parser/terms/term_parser.rs | 0 {api => crates/api}/src/parser/ucum_symbol.rs | 0 {api => crates/api}/src/reduce.rs | 0 {api => crates/api}/src/reducible.rs | 0 {api => crates/api}/src/ucum_unit.rs | 0 {api => crates/api}/src/unit.rs | 0 {api => crates/api}/src/unit/as_fraction.rs | 0 {api => crates/api}/src/unit/composable.rs | 0 {api => crates/api}/src/unit/custom_ffi.rs | 0 {api => crates/api}/src/unit/deref.rs | 0 {api => crates/api}/src/unit/display.rs | 0 {api => crates/api}/src/unit/field_eq.rs | 0 {api => crates/api}/src/unit/from_str.rs | 0 {api => crates/api}/src/unit/invert.rs | 0 {api => crates/api}/src/unit/is_compatible_with.rs | 0 {api => crates/api}/src/unit/ops.rs | 0 {api => crates/api}/src/unit/partial_eq.rs | 0 {api => crates/api}/src/unit/partial_ord.rs | 0 {api => crates/api}/src/unit/reducible.rs | 0 {api => crates/api}/src/unit/serde.rs | 0 {api => crates/api}/src/unit/term_reducing.rs | 0 {api => crates/api}/src/unit/to_reduced.rs | 0 {api => crates/api}/src/unit/ucum_unit.rs | 0 {api => crates/api}/tests/measurements_test.rs | 0 {atom_generator => crates/atom_generator}/Atoms.toml | 0 {atom_generator => crates/atom_generator}/Cargo.toml | 0 {atom_generator => crates/atom_generator}/README.md | 0 {atom_generator => crates/atom_generator}/src/from_toml.rs | 0 .../atom_generator}/src/from_toml/atoms.rs | 0 .../atom_generator}/src/from_toml/custom_atoms.rs | 0 {atom_generator => crates/atom_generator}/src/generator.rs | 0 {atom_generator => crates/atom_generator}/src/generator/atom.rs | 0 .../atom_generator}/src/generator/classification.rs | 0 .../atom_generator}/src/generator/handlebars.rs | 0 .../atom_generator}/src/generator/property.rs | 0 .../atom_generator}/src/generator/symbol_grammar.rs | 0 {atom_generator => crates/atom_generator}/src/main.rs | 0 {atom_generator => crates/atom_generator}/src/rust_structs.rs | 0 .../atom_generator}/src/rust_structs/pest_symbol_list.rs | 0 .../atom_generator}/src/rust_structs/rust_atom_list.rs | 0 .../src/rust_structs/rust_classification_list.rs | 0 .../atom_generator}/src/rust_structs/rust_function_set.rs | 0 .../atom_generator}/src/rust_structs/rust_property_list.rs | 0 .../atom_generator}/src/templates/symbol.pest.hbs | 0 {atom_generator => crates/atom_generator}/src/toml_structs.rs | 0 .../atom_generator}/src/toml_structs/toml_atom.rs | 0 .../atom_generator}/src/toml_structs/toml_atom_list.rs | 0 .../atom_generator}/src/toml_structs/toml_base_unit.rs | 0 .../atom_generator}/src/toml_structs/toml_custom_atom_list.rs | 0 .../atom_generator}/src/toml_structs/toml_definition.rs | 0 .../atom_generator}/src/toml_structs/toml_prefix.rs | 0 .../atom_generator}/src/toml_structs/toml_unit.rs | 0 {definition_fetcher => crates/definition_fetcher}/Cargo.toml | 0 {definition_fetcher => crates/definition_fetcher}/README.md | 0 {definition_fetcher => crates/definition_fetcher}/src/main.rs | 0 {ffi => crates/ffi}/Cargo.toml | 0 {ffi => crates/ffi}/Changelog.md | 0 {ffi => crates/ffi}/README.md | 0 {ffi => crates/ffi}/build.rs | 0 {ffi => crates/ffi}/cbindgen.toml | 0 {ffi => crates/ffi}/src/lib.rs | 0 {ffi => crates/ffi}/src/measurement.rs | 0 {ffi => crates/ffi}/src/unit.rs | 0 138 files changed, 1 insertion(+), 1 deletion(-) rename {api => crates/api}/CHANGELOG.md (100%) rename {api => crates/api}/Cargo.toml (100%) rename {api => crates/api}/benches/common.rs (100%) rename {api => crates/api}/benches/measurements_benchmarks.rs (100%) rename {api => crates/api}/benches/unit_benchmarks.rs (100%) rename {api => crates/api}/src/as_fraction.rs (100%) rename {api => crates/api}/src/convertible.rs (100%) rename {api => crates/api}/src/error.rs (100%) rename {api => crates/api}/src/field_eq.rs (100%) rename {api => crates/api}/src/invert.rs (100%) rename {api => crates/api}/src/is_compatible_with.rs (100%) rename {api => crates/api}/src/lib.rs (100%) rename {api => crates/api}/src/macros.rs (100%) rename {api => crates/api}/src/measurement.rs (100%) rename {api => crates/api}/src/measurement/composable.rs (100%) rename {api => crates/api}/src/measurement/convertible.rs (100%) rename {api => crates/api}/src/measurement/display.rs (100%) rename {api => crates/api}/src/measurement/field_eq.rs (100%) rename {api => crates/api}/src/measurement/invert.rs (100%) rename {api => crates/api}/src/measurement/is_compatible_with.rs (100%) rename {api => crates/api}/src/measurement/ops.rs (100%) rename {api => crates/api}/src/measurement/partial_eq.rs (100%) rename {api => crates/api}/src/measurement/partial_ord.rs (100%) rename {api => crates/api}/src/measurement/reducible.rs (100%) rename {api => crates/api}/src/measurement/to_reduced.rs (100%) rename {api => crates/api}/src/measurement/ucum_unit.rs (100%) rename {api => crates/api}/src/parser.rs (100%) rename {api => crates/api}/src/parser/annotation_composition.rs (100%) rename {api => crates/api}/src/parser/atom.rs (100%) rename {api => crates/api}/src/parser/atom/composable.rs (100%) rename {api => crates/api}/src/parser/atom/display.rs (100%) rename {api => crates/api}/src/parser/atom/hash.rs (100%) rename {api => crates/api}/src/parser/atom/partial_eq.rs (100%) rename {api => crates/api}/src/parser/atom/reducible.rs (100%) rename {api => crates/api}/src/parser/atom_test.rs (100%) rename {api => crates/api}/src/parser/classification.rs (100%) rename {api => crates/api}/src/parser/composable.rs (100%) rename {api => crates/api}/src/parser/composition.rs (100%) rename {api => crates/api}/src/parser/definition.rs (100%) rename {api => crates/api}/src/parser/dimension.rs (100%) rename {api => crates/api}/src/parser/error.rs (100%) rename {api => crates/api}/src/parser/function_set.rs (100%) rename {api => crates/api}/src/parser/prefix.rs (100%) rename {api => crates/api}/src/parser/property.rs (100%) rename {api => crates/api}/src/parser/symbols.rs (100%) rename {api => crates/api}/src/parser/symbols/mapper.rs (100%) rename {api => crates/api}/src/parser/symbols/symbol.pest (100%) rename {api => crates/api}/src/parser/symbols/symbol.rs (100%) rename {api => crates/api}/src/parser/symbols/symbol_parser.rs (100%) rename {api => crates/api}/src/parser/symbols/symbol_parser_test.rs (100%) rename {api => crates/api}/src/parser/term.rs (100%) rename {api => crates/api}/src/parser/term/annotation_composable.rs (100%) rename {api => crates/api}/src/parser/term/composable.rs (100%) rename {api => crates/api}/src/parser/term/display.rs (100%) rename {api => crates/api}/src/parser/term/field_eq.rs (100%) rename {api => crates/api}/src/parser/term/invert.rs (100%) rename {api => crates/api}/src/parser/term/is_compatible_with.rs (100%) rename {api => crates/api}/src/parser/term/partial_eq.rs (100%) rename {api => crates/api}/src/parser/term/reducible.rs (100%) rename {api => crates/api}/src/parser/term/ucum_unit.rs (100%) rename {api => crates/api}/src/parser/terms.rs (100%) rename {api => crates/api}/src/parser/terms/mapper.rs (100%) rename {api => crates/api}/src/parser/terms/mapper/annotatable.rs (100%) rename {api => crates/api}/src/parser/terms/mapper/annotation.rs (100%) rename {api => crates/api}/src/parser/terms/mapper/ast_term.rs (100%) rename {api => crates/api}/src/parser/terms/mapper/basic_component.rs (100%) rename {api => crates/api}/src/parser/terms/mapper/component.rs (100%) rename {api => crates/api}/src/parser/terms/mapper/digits.rs (100%) rename {api => crates/api}/src/parser/terms/mapper/exponent.rs (100%) rename {api => crates/api}/src/parser/terms/mapper/factor.rs (100%) rename {api => crates/api}/src/parser/terms/mapper/finishable.rs (100%) rename {api => crates/api}/src/parser/terms/mapper/main_term.rs (100%) rename {api => crates/api}/src/parser/terms/mapper/simple_unit.rs (100%) rename {api => crates/api}/src/parser/terms/term.pest (100%) rename {api => crates/api}/src/parser/terms/term_parser.rs (100%) rename {api => crates/api}/src/parser/ucum_symbol.rs (100%) rename {api => crates/api}/src/reduce.rs (100%) rename {api => crates/api}/src/reducible.rs (100%) rename {api => crates/api}/src/ucum_unit.rs (100%) rename {api => crates/api}/src/unit.rs (100%) rename {api => crates/api}/src/unit/as_fraction.rs (100%) rename {api => crates/api}/src/unit/composable.rs (100%) rename {api => crates/api}/src/unit/custom_ffi.rs (100%) rename {api => crates/api}/src/unit/deref.rs (100%) rename {api => crates/api}/src/unit/display.rs (100%) rename {api => crates/api}/src/unit/field_eq.rs (100%) rename {api => crates/api}/src/unit/from_str.rs (100%) rename {api => crates/api}/src/unit/invert.rs (100%) rename {api => crates/api}/src/unit/is_compatible_with.rs (100%) rename {api => crates/api}/src/unit/ops.rs (100%) rename {api => crates/api}/src/unit/partial_eq.rs (100%) rename {api => crates/api}/src/unit/partial_ord.rs (100%) rename {api => crates/api}/src/unit/reducible.rs (100%) rename {api => crates/api}/src/unit/serde.rs (100%) rename {api => crates/api}/src/unit/term_reducing.rs (100%) rename {api => crates/api}/src/unit/to_reduced.rs (100%) rename {api => crates/api}/src/unit/ucum_unit.rs (100%) rename {api => crates/api}/tests/measurements_test.rs (100%) rename {atom_generator => crates/atom_generator}/Atoms.toml (100%) rename {atom_generator => crates/atom_generator}/Cargo.toml (100%) rename {atom_generator => crates/atom_generator}/README.md (100%) rename {atom_generator => crates/atom_generator}/src/from_toml.rs (100%) rename {atom_generator => crates/atom_generator}/src/from_toml/atoms.rs (100%) rename {atom_generator => crates/atom_generator}/src/from_toml/custom_atoms.rs (100%) rename {atom_generator => crates/atom_generator}/src/generator.rs (100%) rename {atom_generator => crates/atom_generator}/src/generator/atom.rs (100%) rename {atom_generator => crates/atom_generator}/src/generator/classification.rs (100%) rename {atom_generator => crates/atom_generator}/src/generator/handlebars.rs (100%) rename {atom_generator => crates/atom_generator}/src/generator/property.rs (100%) rename {atom_generator => crates/atom_generator}/src/generator/symbol_grammar.rs (100%) rename {atom_generator => crates/atom_generator}/src/main.rs (100%) rename {atom_generator => crates/atom_generator}/src/rust_structs.rs (100%) rename {atom_generator => crates/atom_generator}/src/rust_structs/pest_symbol_list.rs (100%) rename {atom_generator => crates/atom_generator}/src/rust_structs/rust_atom_list.rs (100%) rename {atom_generator => crates/atom_generator}/src/rust_structs/rust_classification_list.rs (100%) rename {atom_generator => crates/atom_generator}/src/rust_structs/rust_function_set.rs (100%) rename {atom_generator => crates/atom_generator}/src/rust_structs/rust_property_list.rs (100%) rename {atom_generator => crates/atom_generator}/src/templates/symbol.pest.hbs (100%) rename {atom_generator => crates/atom_generator}/src/toml_structs.rs (100%) rename {atom_generator => crates/atom_generator}/src/toml_structs/toml_atom.rs (100%) rename {atom_generator => crates/atom_generator}/src/toml_structs/toml_atom_list.rs (100%) rename {atom_generator => crates/atom_generator}/src/toml_structs/toml_base_unit.rs (100%) rename {atom_generator => crates/atom_generator}/src/toml_structs/toml_custom_atom_list.rs (100%) rename {atom_generator => crates/atom_generator}/src/toml_structs/toml_definition.rs (100%) rename {atom_generator => crates/atom_generator}/src/toml_structs/toml_prefix.rs (100%) rename {atom_generator => crates/atom_generator}/src/toml_structs/toml_unit.rs (100%) rename {definition_fetcher => crates/definition_fetcher}/Cargo.toml (100%) rename {definition_fetcher => crates/definition_fetcher}/README.md (100%) rename {definition_fetcher => crates/definition_fetcher}/src/main.rs (100%) rename {ffi => crates/ffi}/Cargo.toml (100%) rename {ffi => crates/ffi}/Changelog.md (100%) rename {ffi => crates/ffi}/README.md (100%) rename {ffi => crates/ffi}/build.rs (100%) rename {ffi => crates/ffi}/cbindgen.toml (100%) rename {ffi => crates/ffi}/src/lib.rs (100%) rename {ffi => crates/ffi}/src/measurement.rs (100%) rename {ffi => crates/ffi}/src/unit.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 0957a575..dec46622 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["api", "atom_generator", "definition_fetcher", "ffi"] +members = ["crates/*"] resolver = "2" [workspace.package] diff --git a/api/CHANGELOG.md b/crates/api/CHANGELOG.md similarity index 100% rename from api/CHANGELOG.md rename to crates/api/CHANGELOG.md diff --git a/api/Cargo.toml b/crates/api/Cargo.toml similarity index 100% rename from api/Cargo.toml rename to crates/api/Cargo.toml diff --git a/api/benches/common.rs b/crates/api/benches/common.rs similarity index 100% rename from api/benches/common.rs rename to crates/api/benches/common.rs diff --git a/api/benches/measurements_benchmarks.rs b/crates/api/benches/measurements_benchmarks.rs similarity index 100% rename from api/benches/measurements_benchmarks.rs rename to crates/api/benches/measurements_benchmarks.rs diff --git a/api/benches/unit_benchmarks.rs b/crates/api/benches/unit_benchmarks.rs similarity index 100% rename from api/benches/unit_benchmarks.rs rename to crates/api/benches/unit_benchmarks.rs diff --git a/api/src/as_fraction.rs b/crates/api/src/as_fraction.rs similarity index 100% rename from api/src/as_fraction.rs rename to crates/api/src/as_fraction.rs diff --git a/api/src/convertible.rs b/crates/api/src/convertible.rs similarity index 100% rename from api/src/convertible.rs rename to crates/api/src/convertible.rs diff --git a/api/src/error.rs b/crates/api/src/error.rs similarity index 100% rename from api/src/error.rs rename to crates/api/src/error.rs diff --git a/api/src/field_eq.rs b/crates/api/src/field_eq.rs similarity index 100% rename from api/src/field_eq.rs rename to crates/api/src/field_eq.rs diff --git a/api/src/invert.rs b/crates/api/src/invert.rs similarity index 100% rename from api/src/invert.rs rename to crates/api/src/invert.rs diff --git a/api/src/is_compatible_with.rs b/crates/api/src/is_compatible_with.rs similarity index 100% rename from api/src/is_compatible_with.rs rename to crates/api/src/is_compatible_with.rs diff --git a/api/src/lib.rs b/crates/api/src/lib.rs similarity index 100% rename from api/src/lib.rs rename to crates/api/src/lib.rs diff --git a/api/src/macros.rs b/crates/api/src/macros.rs similarity index 100% rename from api/src/macros.rs rename to crates/api/src/macros.rs diff --git a/api/src/measurement.rs b/crates/api/src/measurement.rs similarity index 100% rename from api/src/measurement.rs rename to crates/api/src/measurement.rs diff --git a/api/src/measurement/composable.rs b/crates/api/src/measurement/composable.rs similarity index 100% rename from api/src/measurement/composable.rs rename to crates/api/src/measurement/composable.rs diff --git a/api/src/measurement/convertible.rs b/crates/api/src/measurement/convertible.rs similarity index 100% rename from api/src/measurement/convertible.rs rename to crates/api/src/measurement/convertible.rs diff --git a/api/src/measurement/display.rs b/crates/api/src/measurement/display.rs similarity index 100% rename from api/src/measurement/display.rs rename to crates/api/src/measurement/display.rs diff --git a/api/src/measurement/field_eq.rs b/crates/api/src/measurement/field_eq.rs similarity index 100% rename from api/src/measurement/field_eq.rs rename to crates/api/src/measurement/field_eq.rs diff --git a/api/src/measurement/invert.rs b/crates/api/src/measurement/invert.rs similarity index 100% rename from api/src/measurement/invert.rs rename to crates/api/src/measurement/invert.rs diff --git a/api/src/measurement/is_compatible_with.rs b/crates/api/src/measurement/is_compatible_with.rs similarity index 100% rename from api/src/measurement/is_compatible_with.rs rename to crates/api/src/measurement/is_compatible_with.rs diff --git a/api/src/measurement/ops.rs b/crates/api/src/measurement/ops.rs similarity index 100% rename from api/src/measurement/ops.rs rename to crates/api/src/measurement/ops.rs diff --git a/api/src/measurement/partial_eq.rs b/crates/api/src/measurement/partial_eq.rs similarity index 100% rename from api/src/measurement/partial_eq.rs rename to crates/api/src/measurement/partial_eq.rs diff --git a/api/src/measurement/partial_ord.rs b/crates/api/src/measurement/partial_ord.rs similarity index 100% rename from api/src/measurement/partial_ord.rs rename to crates/api/src/measurement/partial_ord.rs diff --git a/api/src/measurement/reducible.rs b/crates/api/src/measurement/reducible.rs similarity index 100% rename from api/src/measurement/reducible.rs rename to crates/api/src/measurement/reducible.rs diff --git a/api/src/measurement/to_reduced.rs b/crates/api/src/measurement/to_reduced.rs similarity index 100% rename from api/src/measurement/to_reduced.rs rename to crates/api/src/measurement/to_reduced.rs diff --git a/api/src/measurement/ucum_unit.rs b/crates/api/src/measurement/ucum_unit.rs similarity index 100% rename from api/src/measurement/ucum_unit.rs rename to crates/api/src/measurement/ucum_unit.rs diff --git a/api/src/parser.rs b/crates/api/src/parser.rs similarity index 100% rename from api/src/parser.rs rename to crates/api/src/parser.rs diff --git a/api/src/parser/annotation_composition.rs b/crates/api/src/parser/annotation_composition.rs similarity index 100% rename from api/src/parser/annotation_composition.rs rename to crates/api/src/parser/annotation_composition.rs diff --git a/api/src/parser/atom.rs b/crates/api/src/parser/atom.rs similarity index 100% rename from api/src/parser/atom.rs rename to crates/api/src/parser/atom.rs diff --git a/api/src/parser/atom/composable.rs b/crates/api/src/parser/atom/composable.rs similarity index 100% rename from api/src/parser/atom/composable.rs rename to crates/api/src/parser/atom/composable.rs diff --git a/api/src/parser/atom/display.rs b/crates/api/src/parser/atom/display.rs similarity index 100% rename from api/src/parser/atom/display.rs rename to crates/api/src/parser/atom/display.rs diff --git a/api/src/parser/atom/hash.rs b/crates/api/src/parser/atom/hash.rs similarity index 100% rename from api/src/parser/atom/hash.rs rename to crates/api/src/parser/atom/hash.rs diff --git a/api/src/parser/atom/partial_eq.rs b/crates/api/src/parser/atom/partial_eq.rs similarity index 100% rename from api/src/parser/atom/partial_eq.rs rename to crates/api/src/parser/atom/partial_eq.rs diff --git a/api/src/parser/atom/reducible.rs b/crates/api/src/parser/atom/reducible.rs similarity index 100% rename from api/src/parser/atom/reducible.rs rename to crates/api/src/parser/atom/reducible.rs diff --git a/api/src/parser/atom_test.rs b/crates/api/src/parser/atom_test.rs similarity index 100% rename from api/src/parser/atom_test.rs rename to crates/api/src/parser/atom_test.rs diff --git a/api/src/parser/classification.rs b/crates/api/src/parser/classification.rs similarity index 100% rename from api/src/parser/classification.rs rename to crates/api/src/parser/classification.rs diff --git a/api/src/parser/composable.rs b/crates/api/src/parser/composable.rs similarity index 100% rename from api/src/parser/composable.rs rename to crates/api/src/parser/composable.rs diff --git a/api/src/parser/composition.rs b/crates/api/src/parser/composition.rs similarity index 100% rename from api/src/parser/composition.rs rename to crates/api/src/parser/composition.rs diff --git a/api/src/parser/definition.rs b/crates/api/src/parser/definition.rs similarity index 100% rename from api/src/parser/definition.rs rename to crates/api/src/parser/definition.rs diff --git a/api/src/parser/dimension.rs b/crates/api/src/parser/dimension.rs similarity index 100% rename from api/src/parser/dimension.rs rename to crates/api/src/parser/dimension.rs diff --git a/api/src/parser/error.rs b/crates/api/src/parser/error.rs similarity index 100% rename from api/src/parser/error.rs rename to crates/api/src/parser/error.rs diff --git a/api/src/parser/function_set.rs b/crates/api/src/parser/function_set.rs similarity index 100% rename from api/src/parser/function_set.rs rename to crates/api/src/parser/function_set.rs diff --git a/api/src/parser/prefix.rs b/crates/api/src/parser/prefix.rs similarity index 100% rename from api/src/parser/prefix.rs rename to crates/api/src/parser/prefix.rs diff --git a/api/src/parser/property.rs b/crates/api/src/parser/property.rs similarity index 100% rename from api/src/parser/property.rs rename to crates/api/src/parser/property.rs diff --git a/api/src/parser/symbols.rs b/crates/api/src/parser/symbols.rs similarity index 100% rename from api/src/parser/symbols.rs rename to crates/api/src/parser/symbols.rs diff --git a/api/src/parser/symbols/mapper.rs b/crates/api/src/parser/symbols/mapper.rs similarity index 100% rename from api/src/parser/symbols/mapper.rs rename to crates/api/src/parser/symbols/mapper.rs diff --git a/api/src/parser/symbols/symbol.pest b/crates/api/src/parser/symbols/symbol.pest similarity index 100% rename from api/src/parser/symbols/symbol.pest rename to crates/api/src/parser/symbols/symbol.pest diff --git a/api/src/parser/symbols/symbol.rs b/crates/api/src/parser/symbols/symbol.rs similarity index 100% rename from api/src/parser/symbols/symbol.rs rename to crates/api/src/parser/symbols/symbol.rs diff --git a/api/src/parser/symbols/symbol_parser.rs b/crates/api/src/parser/symbols/symbol_parser.rs similarity index 100% rename from api/src/parser/symbols/symbol_parser.rs rename to crates/api/src/parser/symbols/symbol_parser.rs diff --git a/api/src/parser/symbols/symbol_parser_test.rs b/crates/api/src/parser/symbols/symbol_parser_test.rs similarity index 100% rename from api/src/parser/symbols/symbol_parser_test.rs rename to crates/api/src/parser/symbols/symbol_parser_test.rs diff --git a/api/src/parser/term.rs b/crates/api/src/parser/term.rs similarity index 100% rename from api/src/parser/term.rs rename to crates/api/src/parser/term.rs diff --git a/api/src/parser/term/annotation_composable.rs b/crates/api/src/parser/term/annotation_composable.rs similarity index 100% rename from api/src/parser/term/annotation_composable.rs rename to crates/api/src/parser/term/annotation_composable.rs diff --git a/api/src/parser/term/composable.rs b/crates/api/src/parser/term/composable.rs similarity index 100% rename from api/src/parser/term/composable.rs rename to crates/api/src/parser/term/composable.rs diff --git a/api/src/parser/term/display.rs b/crates/api/src/parser/term/display.rs similarity index 100% rename from api/src/parser/term/display.rs rename to crates/api/src/parser/term/display.rs diff --git a/api/src/parser/term/field_eq.rs b/crates/api/src/parser/term/field_eq.rs similarity index 100% rename from api/src/parser/term/field_eq.rs rename to crates/api/src/parser/term/field_eq.rs diff --git a/api/src/parser/term/invert.rs b/crates/api/src/parser/term/invert.rs similarity index 100% rename from api/src/parser/term/invert.rs rename to crates/api/src/parser/term/invert.rs diff --git a/api/src/parser/term/is_compatible_with.rs b/crates/api/src/parser/term/is_compatible_with.rs similarity index 100% rename from api/src/parser/term/is_compatible_with.rs rename to crates/api/src/parser/term/is_compatible_with.rs diff --git a/api/src/parser/term/partial_eq.rs b/crates/api/src/parser/term/partial_eq.rs similarity index 100% rename from api/src/parser/term/partial_eq.rs rename to crates/api/src/parser/term/partial_eq.rs diff --git a/api/src/parser/term/reducible.rs b/crates/api/src/parser/term/reducible.rs similarity index 100% rename from api/src/parser/term/reducible.rs rename to crates/api/src/parser/term/reducible.rs diff --git a/api/src/parser/term/ucum_unit.rs b/crates/api/src/parser/term/ucum_unit.rs similarity index 100% rename from api/src/parser/term/ucum_unit.rs rename to crates/api/src/parser/term/ucum_unit.rs diff --git a/api/src/parser/terms.rs b/crates/api/src/parser/terms.rs similarity index 100% rename from api/src/parser/terms.rs rename to crates/api/src/parser/terms.rs diff --git a/api/src/parser/terms/mapper.rs b/crates/api/src/parser/terms/mapper.rs similarity index 100% rename from api/src/parser/terms/mapper.rs rename to crates/api/src/parser/terms/mapper.rs diff --git a/api/src/parser/terms/mapper/annotatable.rs b/crates/api/src/parser/terms/mapper/annotatable.rs similarity index 100% rename from api/src/parser/terms/mapper/annotatable.rs rename to crates/api/src/parser/terms/mapper/annotatable.rs diff --git a/api/src/parser/terms/mapper/annotation.rs b/crates/api/src/parser/terms/mapper/annotation.rs similarity index 100% rename from api/src/parser/terms/mapper/annotation.rs rename to crates/api/src/parser/terms/mapper/annotation.rs diff --git a/api/src/parser/terms/mapper/ast_term.rs b/crates/api/src/parser/terms/mapper/ast_term.rs similarity index 100% rename from api/src/parser/terms/mapper/ast_term.rs rename to crates/api/src/parser/terms/mapper/ast_term.rs diff --git a/api/src/parser/terms/mapper/basic_component.rs b/crates/api/src/parser/terms/mapper/basic_component.rs similarity index 100% rename from api/src/parser/terms/mapper/basic_component.rs rename to crates/api/src/parser/terms/mapper/basic_component.rs diff --git a/api/src/parser/terms/mapper/component.rs b/crates/api/src/parser/terms/mapper/component.rs similarity index 100% rename from api/src/parser/terms/mapper/component.rs rename to crates/api/src/parser/terms/mapper/component.rs diff --git a/api/src/parser/terms/mapper/digits.rs b/crates/api/src/parser/terms/mapper/digits.rs similarity index 100% rename from api/src/parser/terms/mapper/digits.rs rename to crates/api/src/parser/terms/mapper/digits.rs diff --git a/api/src/parser/terms/mapper/exponent.rs b/crates/api/src/parser/terms/mapper/exponent.rs similarity index 100% rename from api/src/parser/terms/mapper/exponent.rs rename to crates/api/src/parser/terms/mapper/exponent.rs diff --git a/api/src/parser/terms/mapper/factor.rs b/crates/api/src/parser/terms/mapper/factor.rs similarity index 100% rename from api/src/parser/terms/mapper/factor.rs rename to crates/api/src/parser/terms/mapper/factor.rs diff --git a/api/src/parser/terms/mapper/finishable.rs b/crates/api/src/parser/terms/mapper/finishable.rs similarity index 100% rename from api/src/parser/terms/mapper/finishable.rs rename to crates/api/src/parser/terms/mapper/finishable.rs diff --git a/api/src/parser/terms/mapper/main_term.rs b/crates/api/src/parser/terms/mapper/main_term.rs similarity index 100% rename from api/src/parser/terms/mapper/main_term.rs rename to crates/api/src/parser/terms/mapper/main_term.rs diff --git a/api/src/parser/terms/mapper/simple_unit.rs b/crates/api/src/parser/terms/mapper/simple_unit.rs similarity index 100% rename from api/src/parser/terms/mapper/simple_unit.rs rename to crates/api/src/parser/terms/mapper/simple_unit.rs diff --git a/api/src/parser/terms/term.pest b/crates/api/src/parser/terms/term.pest similarity index 100% rename from api/src/parser/terms/term.pest rename to crates/api/src/parser/terms/term.pest diff --git a/api/src/parser/terms/term_parser.rs b/crates/api/src/parser/terms/term_parser.rs similarity index 100% rename from api/src/parser/terms/term_parser.rs rename to crates/api/src/parser/terms/term_parser.rs diff --git a/api/src/parser/ucum_symbol.rs b/crates/api/src/parser/ucum_symbol.rs similarity index 100% rename from api/src/parser/ucum_symbol.rs rename to crates/api/src/parser/ucum_symbol.rs diff --git a/api/src/reduce.rs b/crates/api/src/reduce.rs similarity index 100% rename from api/src/reduce.rs rename to crates/api/src/reduce.rs diff --git a/api/src/reducible.rs b/crates/api/src/reducible.rs similarity index 100% rename from api/src/reducible.rs rename to crates/api/src/reducible.rs diff --git a/api/src/ucum_unit.rs b/crates/api/src/ucum_unit.rs similarity index 100% rename from api/src/ucum_unit.rs rename to crates/api/src/ucum_unit.rs diff --git a/api/src/unit.rs b/crates/api/src/unit.rs similarity index 100% rename from api/src/unit.rs rename to crates/api/src/unit.rs diff --git a/api/src/unit/as_fraction.rs b/crates/api/src/unit/as_fraction.rs similarity index 100% rename from api/src/unit/as_fraction.rs rename to crates/api/src/unit/as_fraction.rs diff --git a/api/src/unit/composable.rs b/crates/api/src/unit/composable.rs similarity index 100% rename from api/src/unit/composable.rs rename to crates/api/src/unit/composable.rs diff --git a/api/src/unit/custom_ffi.rs b/crates/api/src/unit/custom_ffi.rs similarity index 100% rename from api/src/unit/custom_ffi.rs rename to crates/api/src/unit/custom_ffi.rs diff --git a/api/src/unit/deref.rs b/crates/api/src/unit/deref.rs similarity index 100% rename from api/src/unit/deref.rs rename to crates/api/src/unit/deref.rs diff --git a/api/src/unit/display.rs b/crates/api/src/unit/display.rs similarity index 100% rename from api/src/unit/display.rs rename to crates/api/src/unit/display.rs diff --git a/api/src/unit/field_eq.rs b/crates/api/src/unit/field_eq.rs similarity index 100% rename from api/src/unit/field_eq.rs rename to crates/api/src/unit/field_eq.rs diff --git a/api/src/unit/from_str.rs b/crates/api/src/unit/from_str.rs similarity index 100% rename from api/src/unit/from_str.rs rename to crates/api/src/unit/from_str.rs diff --git a/api/src/unit/invert.rs b/crates/api/src/unit/invert.rs similarity index 100% rename from api/src/unit/invert.rs rename to crates/api/src/unit/invert.rs diff --git a/api/src/unit/is_compatible_with.rs b/crates/api/src/unit/is_compatible_with.rs similarity index 100% rename from api/src/unit/is_compatible_with.rs rename to crates/api/src/unit/is_compatible_with.rs diff --git a/api/src/unit/ops.rs b/crates/api/src/unit/ops.rs similarity index 100% rename from api/src/unit/ops.rs rename to crates/api/src/unit/ops.rs diff --git a/api/src/unit/partial_eq.rs b/crates/api/src/unit/partial_eq.rs similarity index 100% rename from api/src/unit/partial_eq.rs rename to crates/api/src/unit/partial_eq.rs diff --git a/api/src/unit/partial_ord.rs b/crates/api/src/unit/partial_ord.rs similarity index 100% rename from api/src/unit/partial_ord.rs rename to crates/api/src/unit/partial_ord.rs diff --git a/api/src/unit/reducible.rs b/crates/api/src/unit/reducible.rs similarity index 100% rename from api/src/unit/reducible.rs rename to crates/api/src/unit/reducible.rs diff --git a/api/src/unit/serde.rs b/crates/api/src/unit/serde.rs similarity index 100% rename from api/src/unit/serde.rs rename to crates/api/src/unit/serde.rs diff --git a/api/src/unit/term_reducing.rs b/crates/api/src/unit/term_reducing.rs similarity index 100% rename from api/src/unit/term_reducing.rs rename to crates/api/src/unit/term_reducing.rs diff --git a/api/src/unit/to_reduced.rs b/crates/api/src/unit/to_reduced.rs similarity index 100% rename from api/src/unit/to_reduced.rs rename to crates/api/src/unit/to_reduced.rs diff --git a/api/src/unit/ucum_unit.rs b/crates/api/src/unit/ucum_unit.rs similarity index 100% rename from api/src/unit/ucum_unit.rs rename to crates/api/src/unit/ucum_unit.rs diff --git a/api/tests/measurements_test.rs b/crates/api/tests/measurements_test.rs similarity index 100% rename from api/tests/measurements_test.rs rename to crates/api/tests/measurements_test.rs diff --git a/atom_generator/Atoms.toml b/crates/atom_generator/Atoms.toml similarity index 100% rename from atom_generator/Atoms.toml rename to crates/atom_generator/Atoms.toml diff --git a/atom_generator/Cargo.toml b/crates/atom_generator/Cargo.toml similarity index 100% rename from atom_generator/Cargo.toml rename to crates/atom_generator/Cargo.toml diff --git a/atom_generator/README.md b/crates/atom_generator/README.md similarity index 100% rename from atom_generator/README.md rename to crates/atom_generator/README.md diff --git a/atom_generator/src/from_toml.rs b/crates/atom_generator/src/from_toml.rs similarity index 100% rename from atom_generator/src/from_toml.rs rename to crates/atom_generator/src/from_toml.rs diff --git a/atom_generator/src/from_toml/atoms.rs b/crates/atom_generator/src/from_toml/atoms.rs similarity index 100% rename from atom_generator/src/from_toml/atoms.rs rename to crates/atom_generator/src/from_toml/atoms.rs diff --git a/atom_generator/src/from_toml/custom_atoms.rs b/crates/atom_generator/src/from_toml/custom_atoms.rs similarity index 100% rename from atom_generator/src/from_toml/custom_atoms.rs rename to crates/atom_generator/src/from_toml/custom_atoms.rs diff --git a/atom_generator/src/generator.rs b/crates/atom_generator/src/generator.rs similarity index 100% rename from atom_generator/src/generator.rs rename to crates/atom_generator/src/generator.rs diff --git a/atom_generator/src/generator/atom.rs b/crates/atom_generator/src/generator/atom.rs similarity index 100% rename from atom_generator/src/generator/atom.rs rename to crates/atom_generator/src/generator/atom.rs diff --git a/atom_generator/src/generator/classification.rs b/crates/atom_generator/src/generator/classification.rs similarity index 100% rename from atom_generator/src/generator/classification.rs rename to crates/atom_generator/src/generator/classification.rs diff --git a/atom_generator/src/generator/handlebars.rs b/crates/atom_generator/src/generator/handlebars.rs similarity index 100% rename from atom_generator/src/generator/handlebars.rs rename to crates/atom_generator/src/generator/handlebars.rs diff --git a/atom_generator/src/generator/property.rs b/crates/atom_generator/src/generator/property.rs similarity index 100% rename from atom_generator/src/generator/property.rs rename to crates/atom_generator/src/generator/property.rs diff --git a/atom_generator/src/generator/symbol_grammar.rs b/crates/atom_generator/src/generator/symbol_grammar.rs similarity index 100% rename from atom_generator/src/generator/symbol_grammar.rs rename to crates/atom_generator/src/generator/symbol_grammar.rs diff --git a/atom_generator/src/main.rs b/crates/atom_generator/src/main.rs similarity index 100% rename from atom_generator/src/main.rs rename to crates/atom_generator/src/main.rs diff --git a/atom_generator/src/rust_structs.rs b/crates/atom_generator/src/rust_structs.rs similarity index 100% rename from atom_generator/src/rust_structs.rs rename to crates/atom_generator/src/rust_structs.rs diff --git a/atom_generator/src/rust_structs/pest_symbol_list.rs b/crates/atom_generator/src/rust_structs/pest_symbol_list.rs similarity index 100% rename from atom_generator/src/rust_structs/pest_symbol_list.rs rename to crates/atom_generator/src/rust_structs/pest_symbol_list.rs diff --git a/atom_generator/src/rust_structs/rust_atom_list.rs b/crates/atom_generator/src/rust_structs/rust_atom_list.rs similarity index 100% rename from atom_generator/src/rust_structs/rust_atom_list.rs rename to crates/atom_generator/src/rust_structs/rust_atom_list.rs diff --git a/atom_generator/src/rust_structs/rust_classification_list.rs b/crates/atom_generator/src/rust_structs/rust_classification_list.rs similarity index 100% rename from atom_generator/src/rust_structs/rust_classification_list.rs rename to crates/atom_generator/src/rust_structs/rust_classification_list.rs diff --git a/atom_generator/src/rust_structs/rust_function_set.rs b/crates/atom_generator/src/rust_structs/rust_function_set.rs similarity index 100% rename from atom_generator/src/rust_structs/rust_function_set.rs rename to crates/atom_generator/src/rust_structs/rust_function_set.rs diff --git a/atom_generator/src/rust_structs/rust_property_list.rs b/crates/atom_generator/src/rust_structs/rust_property_list.rs similarity index 100% rename from atom_generator/src/rust_structs/rust_property_list.rs rename to crates/atom_generator/src/rust_structs/rust_property_list.rs diff --git a/atom_generator/src/templates/symbol.pest.hbs b/crates/atom_generator/src/templates/symbol.pest.hbs similarity index 100% rename from atom_generator/src/templates/symbol.pest.hbs rename to crates/atom_generator/src/templates/symbol.pest.hbs diff --git a/atom_generator/src/toml_structs.rs b/crates/atom_generator/src/toml_structs.rs similarity index 100% rename from atom_generator/src/toml_structs.rs rename to crates/atom_generator/src/toml_structs.rs diff --git a/atom_generator/src/toml_structs/toml_atom.rs b/crates/atom_generator/src/toml_structs/toml_atom.rs similarity index 100% rename from atom_generator/src/toml_structs/toml_atom.rs rename to crates/atom_generator/src/toml_structs/toml_atom.rs diff --git a/atom_generator/src/toml_structs/toml_atom_list.rs b/crates/atom_generator/src/toml_structs/toml_atom_list.rs similarity index 100% rename from atom_generator/src/toml_structs/toml_atom_list.rs rename to crates/atom_generator/src/toml_structs/toml_atom_list.rs diff --git a/atom_generator/src/toml_structs/toml_base_unit.rs b/crates/atom_generator/src/toml_structs/toml_base_unit.rs similarity index 100% rename from atom_generator/src/toml_structs/toml_base_unit.rs rename to crates/atom_generator/src/toml_structs/toml_base_unit.rs diff --git a/atom_generator/src/toml_structs/toml_custom_atom_list.rs b/crates/atom_generator/src/toml_structs/toml_custom_atom_list.rs similarity index 100% rename from atom_generator/src/toml_structs/toml_custom_atom_list.rs rename to crates/atom_generator/src/toml_structs/toml_custom_atom_list.rs diff --git a/atom_generator/src/toml_structs/toml_definition.rs b/crates/atom_generator/src/toml_structs/toml_definition.rs similarity index 100% rename from atom_generator/src/toml_structs/toml_definition.rs rename to crates/atom_generator/src/toml_structs/toml_definition.rs diff --git a/atom_generator/src/toml_structs/toml_prefix.rs b/crates/atom_generator/src/toml_structs/toml_prefix.rs similarity index 100% rename from atom_generator/src/toml_structs/toml_prefix.rs rename to crates/atom_generator/src/toml_structs/toml_prefix.rs diff --git a/atom_generator/src/toml_structs/toml_unit.rs b/crates/atom_generator/src/toml_structs/toml_unit.rs similarity index 100% rename from atom_generator/src/toml_structs/toml_unit.rs rename to crates/atom_generator/src/toml_structs/toml_unit.rs diff --git a/definition_fetcher/Cargo.toml b/crates/definition_fetcher/Cargo.toml similarity index 100% rename from definition_fetcher/Cargo.toml rename to crates/definition_fetcher/Cargo.toml diff --git a/definition_fetcher/README.md b/crates/definition_fetcher/README.md similarity index 100% rename from definition_fetcher/README.md rename to crates/definition_fetcher/README.md diff --git a/definition_fetcher/src/main.rs b/crates/definition_fetcher/src/main.rs similarity index 100% rename from definition_fetcher/src/main.rs rename to crates/definition_fetcher/src/main.rs diff --git a/ffi/Cargo.toml b/crates/ffi/Cargo.toml similarity index 100% rename from ffi/Cargo.toml rename to crates/ffi/Cargo.toml diff --git a/ffi/Changelog.md b/crates/ffi/Changelog.md similarity index 100% rename from ffi/Changelog.md rename to crates/ffi/Changelog.md diff --git a/ffi/README.md b/crates/ffi/README.md similarity index 100% rename from ffi/README.md rename to crates/ffi/README.md diff --git a/ffi/build.rs b/crates/ffi/build.rs similarity index 100% rename from ffi/build.rs rename to crates/ffi/build.rs diff --git a/ffi/cbindgen.toml b/crates/ffi/cbindgen.toml similarity index 100% rename from ffi/cbindgen.toml rename to crates/ffi/cbindgen.toml diff --git a/ffi/src/lib.rs b/crates/ffi/src/lib.rs similarity index 100% rename from ffi/src/lib.rs rename to crates/ffi/src/lib.rs diff --git a/ffi/src/measurement.rs b/crates/ffi/src/measurement.rs similarity index 100% rename from ffi/src/measurement.rs rename to crates/ffi/src/measurement.rs diff --git a/ffi/src/unit.rs b/crates/ffi/src/unit.rs similarity index 100% rename from ffi/src/unit.rs rename to crates/ffi/src/unit.rs From ad509c2ee1beff1f19cd9a5354eb2af9e9782f5e Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 5 Feb 2024 16:51:01 -0800 Subject: [PATCH 34/80] PLCC-287 Impl Inv for *Inver* implementors --- crates/api/Cargo.toml | 2 +- crates/api/src/invert.rs | 6 ++ crates/api/src/lib.rs | 2 +- crates/api/src/measurement.rs | 1 + crates/api/src/measurement/invert.rs | 20 +++-- crates/api/src/measurement/num_traits.rs | 1 + crates/api/src/measurement/num_traits/inv.rs | 81 ++++++++++++++++++ crates/api/src/parser/term.rs | 2 + crates/api/src/parser/term/invert.rs | 26 +++--- crates/api/src/parser/term/num_traits.rs | 1 + crates/api/src/parser/term/num_traits/inv.rs | 82 +++++++++++++++++++ .../api/src/parser/terms/mapper/ast_term.rs | 14 ++-- .../api/src/parser/terms/mapper/main_term.rs | 18 ++-- crates/api/src/unit.rs | 8 +- crates/api/src/unit/as_fraction.rs | 6 +- crates/api/src/unit/invert.rs | 10 ++- crates/api/src/unit/num_traits.rs | 1 + crates/api/src/unit/num_traits/inv.rs | 79 ++++++++++++++++++ crates/api/src/unit/ops.rs | 10 ++- crates/api/src/unit/to_reduced.rs | 13 ++- 20 files changed, 334 insertions(+), 49 deletions(-) create mode 100644 crates/api/src/measurement/num_traits.rs create mode 100644 crates/api/src/measurement/num_traits/inv.rs create mode 100644 crates/api/src/parser/term/num_traits.rs create mode 100644 crates/api/src/parser/term/num_traits/inv.rs create mode 100644 crates/api/src/unit/num_traits.rs create mode 100644 crates/api/src/unit/num_traits/inv.rs diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index 2530ef28..b8f7749e 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -11,7 +11,7 @@ publish = ["agrian-registry"] [dependencies] approx.workspace = true ffi_common = { workspace = true, optional = true } -num-traits = "0.2.17" +num-traits = "0.2" pest = "^2.1" pest_derive = "^2.1" serde = { workspace = true, optional = true } diff --git a/crates/api/src/invert.rs b/crates/api/src/invert.rs index 29209ea2..5bdf4f7b 100644 --- a/crates/api/src/invert.rs +++ b/crates/api/src/invert.rs @@ -1,12 +1,17 @@ +// TODO: Remove in 1.0.0 release. +#![allow(deprecated)] + //! Defines a basic interface for inverting types, similar to that of a fraction. //! +#[deprecated(since = "1.0.0", note = "Please use num_traits::Inv")] pub trait Invert { /// Updates `self` to be inverted. /// fn invert(self); } +#[deprecated(since = "1.0.0", note = "Please use num_traits::Inv")] pub trait ToInverse { type Output; @@ -15,6 +20,7 @@ pub trait ToInverse { fn to_inverse(&self) -> Self::Output; } +#[deprecated(since = "1.0.0", note = "Please use num_traits::Inv")] pub trait IntoInverse: ToInverse { /// Builds a new `Self` that is inverted. /// diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index f32d679b..784e05a5 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -16,7 +16,7 @@ unused_results, variant_size_differences )] -#![allow(clippy::redundant_pub_crate)] +#![allow(clippy::redundant_pub_crate, deprecated_in_future)] #[macro_use] mod macros; diff --git a/crates/api/src/measurement.rs b/crates/api/src/measurement.rs index 44fa3152..6a234c64 100644 --- a/crates/api/src/measurement.rs +++ b/crates/api/src/measurement.rs @@ -4,6 +4,7 @@ mod display; mod field_eq; mod invert; mod is_compatible_with; +mod num_traits; mod ops; mod partial_eq; mod partial_ord; diff --git a/crates/api/src/measurement/invert.rs b/crates/api/src/measurement/invert.rs index cfa67890..c8bb4436 100644 --- a/crates/api/src/measurement/invert.rs +++ b/crates/api/src/measurement/invert.rs @@ -1,32 +1,34 @@ -use super::Measurement; +// TODO: Remove in 1.0.0 release. +#![allow(deprecated)] + use crate::{ invert::{Invert, ToInverse}, Error, }; +use super::Measurement; + impl Invert for &mut Measurement { #[inline] fn invert(self) { - self.value = 1.0 / self.value; - self.unit.invert(); + let _ = num_traits::Inv::inv(self); } } +// TODO: Remove the check for divide by 0 in the future. +// impl ToInverse for Measurement { type Output = Result; #[inline] fn to_inverse(&self) -> Self::Output { - let new_value = 1.0 / self.value; + let m = num_traits::Inv::inv(self.clone()); - if new_value.is_infinite() { + if m.value.is_infinite() { return Err(Error::DivideByZero); } - Ok(Self { - value: new_value, - unit: self.unit.to_inverse(), - }) + Ok(m) } } diff --git a/crates/api/src/measurement/num_traits.rs b/crates/api/src/measurement/num_traits.rs new file mode 100644 index 00000000..932954a9 --- /dev/null +++ b/crates/api/src/measurement/num_traits.rs @@ -0,0 +1 @@ +mod inv; diff --git a/crates/api/src/measurement/num_traits/inv.rs b/crates/api/src/measurement/num_traits/inv.rs new file mode 100644 index 00000000..43df9389 --- /dev/null +++ b/crates/api/src/measurement/num_traits/inv.rs @@ -0,0 +1,81 @@ +use num_traits::Inv; + +use crate::Measurement; + +impl Inv for Measurement { + type Output = Self; + + fn inv(self) -> Self::Output { + let mut s = self; + s.value = s.value.inv(); + s.unit = s.unit.inv(); + s + } +} + +impl<'a> Inv for &'a mut Measurement { + type Output = Self; + + fn inv(self) -> Self::Output { + self.value = self.value.inv(); + let _ = Inv::inv(&mut self.unit); + self + } +} + +#[cfg(test)] +mod tests { + use crate::Measurement; + use num_traits::Inv; + + macro_rules! test_inv { + ($test_name:ident, $subject:expr, $expected:expr) => { + #[test] + fn $test_name() { + // Test &Measurement impl + // let new_measurement = Inv::inv(&$subject); + // assert_eq!(new_measurement, $expected); + + // Test &mut Measurement impl + let mut mut_borrowed = $subject.clone(); + let _ = Inv::inv(&mut mut_borrowed); + assert_eq!(mut_borrowed, $expected); + + // Test Measurement impl + let owned = $subject; + let inverted = Inv::inv(owned); + assert_eq!(inverted, $expected); + } + }; + } + + test_inv!( + validate_numerator_no_exponent, + Measurement::try_new(10.0, "m").unwrap(), + Measurement::try_new(0.1, "m-1").unwrap() + ); + + test_inv!( + validate_numerator_with_exponent_1, + Measurement::try_new(10.0, "m1").unwrap(), + Measurement::try_new(0.1, "m-1").unwrap() + ); + + test_inv!( + validate_numerator_with_exponent_minus_1, + Measurement::try_new(10.0, "m-1").unwrap(), + Measurement::try_new(0.1, "m").unwrap() + ); + + test_inv!( + validate_numerator_and_denominator, + Measurement::try_new(10.0, "m2/s2").unwrap(), + Measurement::try_new(0.1, "s2/m2").unwrap() + ); + + test_inv!( + validate_numerator_and_denominator_mixed, + Measurement::try_new(10.0, "m2/s2.g4/km4/har5").unwrap(), + Measurement::try_new(0.1, "s2.g4.har5/m2.km4").unwrap() + ); +} diff --git a/crates/api/src/parser/term.rs b/crates/api/src/parser/term.rs index e4d862d3..0fe99b9a 100644 --- a/crates/api/src/parser/term.rs +++ b/crates/api/src/parser/term.rs @@ -4,6 +4,7 @@ mod display; mod field_eq; mod invert; mod is_compatible_with; +mod num_traits; mod partial_eq; mod reducible; mod ucum_unit; @@ -42,6 +43,7 @@ impl Term { /// Creates a new `Term` that's equivalent to the unit "1". /// + #[deprecated(since = "1.0.0", note = "Please use term::UNITY instead")] #[must_use] pub const fn new_unity() -> Self { Self { diff --git a/crates/api/src/parser/term/invert.rs b/crates/api/src/parser/term/invert.rs index 7c1f3143..f04d93ee 100644 --- a/crates/api/src/parser/term/invert.rs +++ b/crates/api/src/parser/term/invert.rs @@ -1,17 +1,20 @@ +// TODO: Remove in 1.0.0 release. +#![allow(deprecated)] + use std::borrow::Cow; -use super::Term; +use num_traits::Inv; + use crate::invert::{Invert, ToInverse}; +use super::Term; + // ╭──────╮ // │ Term │ // ╰──────╯ impl Invert for &mut Term { fn invert(self) { - self.exponent = self.exponent.map_or(Some(-1), |e| match e { - -1 => None, - _ => Some(-e), - }); + let _ = Inv::inv(self); } } @@ -19,10 +22,7 @@ impl ToInverse for Term { type Output = Self; fn to_inverse(&self) -> Self::Output { - let mut new_term = self.clone(); - new_term.invert(); - - new_term + Inv::inv(self) } } @@ -32,7 +32,7 @@ impl ToInverse for Term { impl Invert for &mut Vec { fn invert(self) { for term in self.iter_mut() { - term.invert(); + let _ = Inv::inv(term); } } } @@ -41,7 +41,7 @@ impl ToInverse for Vec { type Output = Self; fn to_inverse(&self) -> Self::Output { - self.iter().map(ToInverse::to_inverse).collect() + self.iter().map(Inv::inv).collect() } } @@ -51,7 +51,7 @@ impl ToInverse for Vec { impl<'a> Invert for &mut Cow<'a, [Term]> { fn invert(self) { for term in self.to_mut().iter_mut() { - term.invert(); + let _ = term.inv(); } } } @@ -60,7 +60,7 @@ impl<'a> ToInverse for Cow<'a, [Term]> { type Output = Self; fn to_inverse(&self) -> Self::Output { - self.iter().map(ToInverse::to_inverse).collect() + self.iter().map(Inv::inv).collect() } } diff --git a/crates/api/src/parser/term/num_traits.rs b/crates/api/src/parser/term/num_traits.rs new file mode 100644 index 00000000..932954a9 --- /dev/null +++ b/crates/api/src/parser/term/num_traits.rs @@ -0,0 +1 @@ +mod inv; diff --git a/crates/api/src/parser/term/num_traits/inv.rs b/crates/api/src/parser/term/num_traits/inv.rs new file mode 100644 index 00000000..eb8b0820 --- /dev/null +++ b/crates/api/src/parser/term/num_traits/inv.rs @@ -0,0 +1,82 @@ +use num_traits::Inv; + +use crate::Term; + +impl Inv for Term { + type Output = Self; + + fn inv(self) -> Self::Output { + let mut s = self; + + s.exponent = s.exponent.map_or(Some(-1), |e| match e { + -1 => None, + _ => Some(-e), + }); + + s + } +} + +impl<'a> Inv for &'a Term { + type Output = Term; + + fn inv(self) -> Self::Output { + let new_term = self.clone(); + new_term.inv() + } +} + +impl<'a> Inv for &'a mut Term { + type Output = Self; + + fn inv(self) -> Self::Output { + self.exponent = self.exponent.map_or(Some(-1), |e| match e { + -1 => None, + _ => Some(-e), + }); + + self + } +} + +#[cfg(test)] +mod tests { + use crate::{Atom, Term}; + + use super::*; + + macro_rules! test_inv { + ($test_name:ident, $subject:expr, $expected:expr) => { + #[test] + fn $test_name() { + // Test &mut Term impl + let mut mut_borrowed = $subject.clone(); + let _ = Inv::inv(&mut mut_borrowed); + assert_eq!(mut_borrowed, $expected); + + // Test Term impl + let owned = $subject; + let inverted = Inv::inv(owned); + assert_eq!(inverted, $expected); + } + }; + } + + test_inv!( + validate_invert_numerator_no_exponent, + term!(Meter), + term!(Meter, exponent: -1) + ); + + test_inv!( + validate_invert_numerator_with_exponent_1, + term!(Meter, exponent: 1), + term!(Meter, exponent: -1) + ); + + test_inv!( + validate_invert_numerator_with_exponent_minus_1, + term!(Meter, exponent: -1), + term!(Meter) + ); +} diff --git a/crates/api/src/parser/terms/mapper/ast_term.rs b/crates/api/src/parser/terms/mapper/ast_term.rs index b7392a24..2356a189 100644 --- a/crates/api/src/parser/terms/mapper/ast_term.rs +++ b/crates/api/src/parser/terms/mapper/ast_term.rs @@ -1,7 +1,10 @@ -use super::{Component, Error, Finishable, Term, Visit}; -use crate::{invert::Invert, parser::terms::term_parser::Rule}; +use num_traits::Inv; use pest::iterators::Pair; +use crate::parser::terms::term_parser::Rule; + +use super::{Component, Error, Finishable, Term, Visit}; + pub(super) struct AstTerm { pub(super) component: Component, pub(super) terms: Vec, @@ -36,18 +39,19 @@ impl AstTerm { match pairs.next() { Some(third) => match third.as_rule() { Rule::term => { - let mut new_terms: Vec = Self::visit(third)?.finish(); + let new_terms: Vec = Self::visit(third)?.finish(); + let mut u = crate::Unit::new(new_terms); match op { SecondToken::Dot => (), SecondToken::Slash => { - new_terms.invert(); + let _ = Inv::inv(&mut u); } } Ok(Self { component, - terms: new_terms, + terms: u.into_terms().to_vec(), }) } _ => unreachable!(), diff --git a/crates/api/src/parser/terms/mapper/main_term.rs b/crates/api/src/parser/terms/mapper/main_term.rs index 27f1ee7a..24c39107 100644 --- a/crates/api/src/parser/terms/mapper/main_term.rs +++ b/crates/api/src/parser/terms/mapper/main_term.rs @@ -1,10 +1,10 @@ -use super::{AstTerm, Finishable, Visit}; -use crate::{ - invert::Invert, - parser::{terms::term_parser::Rule, Error, Term}, -}; +use num_traits::Inv; use pest::iterators::Pair; +use crate::parser::{terms::term_parser::Rule, Error, Term}; + +use super::{AstTerm, Finishable, Visit}; + pub(super) struct MainTerm { pub(super) terms: Vec, } @@ -32,12 +32,14 @@ impl Visit for MainTerm { match pairs.next() { Some(second) => match second.as_rule() { Rule::term => { - let mut terms: Vec = AstTerm::visit(second)?.finish(); + let terms: Vec = AstTerm::visit(second)?.finish(); // If we're here it's because there was a leading slash, so invert. - terms.invert(); + let u = crate::Unit::new(terms).inv(); - Ok(Self { terms }) + Ok(Self { + terms: u.into_terms().to_vec(), + }) } _ => unreachable!(), }, diff --git a/crates/api/src/unit.rs b/crates/api/src/unit.rs index 84eb1b9d..5edd01ae 100644 --- a/crates/api/src/unit.rs +++ b/crates/api/src/unit.rs @@ -6,6 +6,7 @@ mod field_eq; mod from_str; mod invert; mod is_compatible_with; +mod num_traits; mod ops; mod partial_eq; mod partial_ord; @@ -90,7 +91,7 @@ impl Unit { /// Creates a new `Unit` that's equivalent to "1". /// - #[deprecated(since = "0.23.0", note = "Please use unit::UNITY instead")] + #[deprecated(since = "1.0.0", note = "Please use unit::UNITY instead")] #[must_use] pub const fn new_unity() -> Self { UNITY @@ -103,6 +104,11 @@ impl Unit { &self.terms } + #[must_use] + pub fn into_terms(self) -> Cow<'static, [Term]> { + self.terms + } + /// A `Unit` is a unity `Unit` if represents "1", which technically means /// here: /// diff --git a/crates/api/src/unit/as_fraction.rs b/crates/api/src/unit/as_fraction.rs index c0cc36a1..d913e58a 100644 --- a/crates/api/src/unit/as_fraction.rs +++ b/crates/api/src/unit/as_fraction.rs @@ -1,4 +1,6 @@ -use crate::{as_fraction::AsFraction, invert::ToInverse, parser::Term, unit::Unit}; +use num_traits::Inv; + +use crate::{as_fraction::AsFraction, parser::Term, unit::Unit}; impl AsFraction for Unit { type Numerator = Option; @@ -26,7 +28,7 @@ impl AsFraction for Unit { .terms .iter() .filter_map(|term| match term.exponent { - Some(e) if e.is_negative() => Some(term.to_inverse()), + Some(e) if e.is_negative() => Some(term.inv()), _ => None, }) .collect(); diff --git a/crates/api/src/unit/invert.rs b/crates/api/src/unit/invert.rs index d267720a..9f621bca 100644 --- a/crates/api/src/unit/invert.rs +++ b/crates/api/src/unit/invert.rs @@ -1,10 +1,14 @@ -use super::Unit; +// TODO: Remove in 1.0.0 release. +#![allow(deprecated)] + use crate::invert::{Invert, ToInverse}; +use super::Unit; + impl Invert for &mut Unit { #[inline] fn invert(self) { - self.terms.invert(); + let _ = num_traits::Inv::inv(self); } } @@ -13,7 +17,7 @@ impl ToInverse for Unit { #[inline] fn to_inverse(&self) -> Self::Output { - Self::new(self.terms.to_inverse()) + num_traits::Inv::inv(self.clone()) } } diff --git a/crates/api/src/unit/num_traits.rs b/crates/api/src/unit/num_traits.rs new file mode 100644 index 00000000..932954a9 --- /dev/null +++ b/crates/api/src/unit/num_traits.rs @@ -0,0 +1 @@ +mod inv; diff --git a/crates/api/src/unit/num_traits/inv.rs b/crates/api/src/unit/num_traits/inv.rs new file mode 100644 index 00000000..7b359b39 --- /dev/null +++ b/crates/api/src/unit/num_traits/inv.rs @@ -0,0 +1,79 @@ +use num_traits::Inv; + +use crate::Unit; + +impl Inv for Unit { + type Output = Self; + + fn inv(self) -> Self::Output { + Self { + terms: self.terms.iter().map(Inv::inv).collect(), + } + } +} + +impl<'a> Inv for &'a mut Unit { + type Output = Self; + + fn inv(self) -> Self::Output { + for term in self.terms.to_mut().iter_mut() { + let _ = term.inv(); + } + + self + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use super::*; + + macro_rules! test_inv { + ($test_name:ident, $subject:expr, $expected:expr) => { + #[test] + fn $test_name() { + // Test &mut Unit impl + let mut mut_borrowed = $subject.clone(); + let _ = Inv::inv(&mut mut_borrowed); + assert_eq!(mut_borrowed, $expected); + + // Test Unit impl + let owned = $subject; + let inverted = Inv::inv(owned); + assert_eq!(inverted, $expected); + } + }; + } + + test_inv!( + validate_numerator_no_exponent, + Unit::from_str("m").unwrap(), + Unit::from_str("m-1").unwrap() + ); + + test_inv!( + validate_numerator_with_exponent_1, + Unit::from_str("m1").unwrap(), + Unit::from_str("m-1").unwrap() + ); + + test_inv!( + validate_numerator_with_exponent_minus_1, + Unit::from_str("m-1").unwrap(), + Unit::from_str("m").unwrap() + ); + + test_inv!( + validate_numerator_and_denominator, + Unit::from_str("m2/s2").unwrap(), + Unit::from_str("s2/m2").unwrap() + ); + + test_inv!( + validate_numerator_and_denominator_mixed, + Unit::from_str("m2/s2.g4/km4/har5").unwrap(), + Unit::from_str("s2.g4.har5/m2.km4").unwrap() + ); +} diff --git a/crates/api/src/unit/ops.rs b/crates/api/src/unit/ops.rs index 0337b545..38eb9f12 100644 --- a/crates/api/src/unit/ops.rs +++ b/crates/api/src/unit/ops.rs @@ -1,7 +1,11 @@ -use super::term_reducing; -use crate::{invert::ToInverse, Term, Unit}; use std::ops::{Div, Mul}; +use num_traits::Inv; + +use crate::{Term, Unit}; + +use super::term_reducing; + //----------------------------------------------------------------------------- // impl Div //----------------------------------------------------------------------------- @@ -10,7 +14,7 @@ fn divide_terms(lhs: &[Term], rhs: &[Term]) -> Vec { terms.extend_from_slice(lhs); for term in rhs { - terms.push(term.to_inverse()); + terms.push(term.inv()); } term_reducing::reduce_terms(&terms) diff --git a/crates/api/src/unit/to_reduced.rs b/crates/api/src/unit/to_reduced.rs index 78e135b9..f9bb4a05 100644 --- a/crates/api/src/unit/to_reduced.rs +++ b/crates/api/src/unit/to_reduced.rs @@ -1,12 +1,16 @@ -use super::Unit; +use std::borrow::Cow; + +use num_traits::Inv; + use crate::{ as_fraction::AsFraction, - invert::IntoInverse, parser::{Composable, Composition}, reduce::ToReduced, Term, }; +use super::Unit; + type OptionCombos = Vec>; /// The implementation here checks for `Unit`s in `self`'s numerator and denominator that have the @@ -60,7 +64,10 @@ impl ToReduced for Unit { let mut new_terms: Vec = Vec::with_capacity(new_numerators.len() + new_denominators.len()); new_terms.extend_from_slice(&new_numerators); - new_terms.extend_from_slice(&new_denominators.into_inverse()); + let denom_unit = Self { + terms: Cow::Owned(new_denominators), + }; + new_terms.extend_from_slice(&denom_unit.inv().terms); Self::new(super::term_reducing::reduce_terms(&new_terms)) } From e891d1b47bbe17df611a4ea33617fd9b19a1c050 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Tue, 6 Feb 2024 11:47:53 -0800 Subject: [PATCH 35/80] PLCC-287 Implement One and use --- crates/api/src/measurement.rs | 5 +++- crates/api/src/measurement/num_traits.rs | 1 + .../src/measurement/num_traits/identities.rs | 28 +++++++++++++++++++ crates/api/src/measurement/reducible.rs | 6 ++-- crates/api/src/parser/atom/reducible.rs | 2 +- crates/api/src/parser/definition.rs | 4 +-- crates/api/src/parser/term.rs | 26 +++++++++-------- crates/api/src/parser/term/display.rs | 6 ++-- crates/api/src/parser/term/reducible.rs | 22 ++++++++------- crates/api/src/parser/term/ucum_unit.rs | 5 ++-- crates/api/src/unit.rs | 3 +- crates/api/src/unit/deref.rs | 1 + crates/api/src/unit/reducible.rs | 4 +-- crates/api/src/unit/serde.rs | 8 ++++-- crates/api/src/unit/term_reducing.rs | 15 +++++++--- crates/api/src/unit/ucum_unit.rs | 2 +- crates/atom_generator/src/generator/atom.rs | 2 +- 17 files changed, 95 insertions(+), 45 deletions(-) create mode 100644 crates/api/src/measurement/num_traits/identities.rs diff --git a/crates/api/src/measurement.rs b/crates/api/src/measurement.rs index 6a234c64..8e2dd3be 100644 --- a/crates/api/src/measurement.rs +++ b/crates/api/src/measurement.rs @@ -14,8 +14,11 @@ mod ucum_unit; use crate::{reducible::Reducible, ucum_unit::UcumUnit, unit::Unit}; +use ::num_traits::One; + #[cfg(feature = "cffi")] use ffi_common::derive::FFI; + #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; @@ -107,7 +110,7 @@ impl Measurement { } else if other_unit.is_special() { other_unit.calculate_magnitude(self.value) } else { - self.scalar() / other_unit.reduce_value(1.0) + self.scalar() / other_unit.reduce_value(One::one()) } } } diff --git a/crates/api/src/measurement/num_traits.rs b/crates/api/src/measurement/num_traits.rs index 932954a9..f11410fd 100644 --- a/crates/api/src/measurement/num_traits.rs +++ b/crates/api/src/measurement/num_traits.rs @@ -1 +1,2 @@ +mod identities; mod inv; diff --git a/crates/api/src/measurement/num_traits/identities.rs b/crates/api/src/measurement/num_traits/identities.rs new file mode 100644 index 00000000..06cd439a --- /dev/null +++ b/crates/api/src/measurement/num_traits/identities.rs @@ -0,0 +1,28 @@ +use num_traits::One; + +use crate::Measurement; + +impl One for Measurement { + fn one() -> Self { + Self { + value: One::one(), + unit: crate::unit::UNITY, + } + } + + fn is_one(&self) -> bool { + self.value.is_one() + } +} + +#[cfg(test)] +mod tests { + use crate::unit; + + use super::*; + + #[test] + fn one_test() { + assert_eq!(Measurement::new(1.0, unit::UNITY), Measurement::one()); + } +} diff --git a/crates/api/src/measurement/reducible.rs b/crates/api/src/measurement/reducible.rs index 7ba57993..b7352fbd 100644 --- a/crates/api/src/measurement/reducible.rs +++ b/crates/api/src/measurement/reducible.rs @@ -1,3 +1,5 @@ +use num_traits::One; + use crate::{measurement::Measurement, reducible::Reducible, ucum_unit::UcumUnit}; impl Reducible for Measurement { @@ -5,7 +7,7 @@ impl Reducible for Measurement { if self.is_special() { self.unit.reduce_value(value) } else { - value * self.unit.reduce_value(1.0) + value * self.unit.reduce_value(One::one()) } } @@ -13,7 +15,7 @@ impl Reducible for Measurement { if self.is_special() { self.unit.calculate_magnitude(self.scalar()) } else { - value * self.unit.calculate_magnitude(1.0) + value * self.unit.calculate_magnitude(One::one()) } } } diff --git a/crates/api/src/parser/atom/reducible.rs b/crates/api/src/parser/atom/reducible.rs index 34d132d5..4a11a76a 100644 --- a/crates/api/src/parser/atom/reducible.rs +++ b/crates/api/src/parser/atom/reducible.rs @@ -9,7 +9,7 @@ impl Reducible for Atom { if self.is_special() { self.definition().calculate_magnitude(value) } else { - 1.0 + num_traits::One::one() } } } diff --git a/crates/api/src/parser/definition.rs b/crates/api/src/parser/definition.rs index 09d92a3b..7e163eef 100644 --- a/crates/api/src/parser/definition.rs +++ b/crates/api/src/parser/definition.rs @@ -81,7 +81,7 @@ impl Definition { impl Reducible for Definition { fn reduce_value(&self, other_value: f64) -> f64 { match self { - Self::Base => 1.0, + Self::Base => One::one(), Self::NonDimensional(value) => *value, Self::Dimensional { value, terms } => value * terms.reduce_value(other_value), Self::NonDimensionalSpecial { function_set, .. } @@ -93,7 +93,7 @@ impl Reducible for Definition { fn calculate_magnitude(&self, other_value: f64) -> f64 { match self { - Self::Base => 1.0, + Self::Base => One::one(), Self::NonDimensional(value) => *value, Self::Dimensional { value, terms } => value * terms.calculate_magnitude(other_value), Self::NonDimensionalSpecial { function_set, .. } diff --git a/crates/api/src/parser/term.rs b/crates/api/src/parser/term.rs index 0fe99b9a..a6f6dcfc 100644 --- a/crates/api/src/parser/term.rs +++ b/crates/api/src/parser/term.rs @@ -11,7 +11,15 @@ mod ucum_unit; use crate::parser::{Atom, Prefix}; -pub const UNITY: Term = Term::new_unity(); +pub const UNITY: Term = { + Term { + atom: None, + prefix: None, + factor: Some(1), + exponent: None, + annotation: None, + } +}; pub const UNITY_ARRAY: [Term; 1] = [UNITY]; pub const UNITY_ARRAY_REF: &[Term; 1] = &UNITY_ARRAY; @@ -46,13 +54,7 @@ impl Term { #[deprecated(since = "1.0.0", note = "Please use term::UNITY instead")] #[must_use] pub const fn new_unity() -> Self { - Self { - atom: None, - prefix: None, - factor: Some(1), - exponent: None, - annotation: None, - } + UNITY } /// A `Term` is a unity `Term` if represents "1", which technically means @@ -63,6 +65,9 @@ impl Term { /// * it has no `Atom` /// * it has no `Prefix` /// + /// NOTE: This does not check the annotation since that does not effect the + /// quantity of the Term. + /// #[must_use] pub fn is_unity(&self) -> bool { self.factor == Some(1_u32) @@ -126,11 +131,10 @@ impl Term { #[cfg(test)] mod tests { - use super::Term; + use super::*; #[test] fn validate_new_unity() { - let term = Term::new_unity(); - assert_eq!(term.to_string(), "1"); + assert_eq!(UNITY.to_string(), "1"); } } diff --git a/crates/api/src/parser/term/display.rs b/crates/api/src/parser/term/display.rs index 9e70f245..0be1b787 100644 --- a/crates/api/src/parser/term/display.rs +++ b/crates/api/src/parser/term/display.rs @@ -52,7 +52,7 @@ fn extract_term_string_atom(term_string: &mut String, term: &Term) { #[cfg(test)] mod tests { - use crate::parser::{Atom, Prefix, Term}; + use crate::parser::{term::UNITY, Atom, Prefix, Term}; macro_rules! validate_display { ($test_name:ident, $term:expr, $output:expr) => { @@ -82,11 +82,11 @@ mod tests { }, "{seed}" ); - validate_display!(validate_display_unity, Term::new_unity(), "1"); + validate_display!(validate_display_unity, UNITY, "1"); validate_display!( validate_display_unity_annotation, { - let mut t = Term::new_unity(); + let mut t = UNITY; t.annotation = Some("seed".to_string()); t }, diff --git a/crates/api/src/parser/term/reducible.rs b/crates/api/src/parser/term/reducible.rs index 6ee1fe5d..9e53f04d 100644 --- a/crates/api/src/parser/term/reducible.rs +++ b/crates/api/src/parser/term/reducible.rs @@ -1,23 +1,24 @@ -#![allow(clippy::large_enum_variant)] -#![allow(clippy::result_large_err)] - use std::borrow::Cow; +use num_traits::One; + use crate::{parser::ucum_symbol::UcumSymbol, reducible::Reducible}; use super::Term; impl Reducible for Term { fn reduce_value(&self, value: f64) -> f64 { - let atom_scalar = self.atom.map_or(1.0, |a| a.reduce_value(value)); - let prefix_scalar = self.prefix.map_or(1.0, |p| p.definition_value()); + let atom_scalar = self.atom.map_or_else(One::one, |a| a.reduce_value(value)); + let prefix_scalar = self.prefix.map_or_else(One::one, |p| p.definition_value()); combine_term_values(atom_scalar, prefix_scalar, self.factor, self.exponent) } fn calculate_magnitude(&self, value: f64) -> f64 { - let atom_magnitude = self.atom.map_or(1.0, |a| a.calculate_magnitude(value)); - let prefix_magnitude = self.prefix.map_or(1.0, |p| p.definition_value()); + let atom_magnitude = self + .atom + .map_or_else(One::one, |a| a.calculate_magnitude(value)); + let prefix_magnitude = self.prefix.map_or_else(One::one, |p| p.definition_value()); combine_term_values(atom_magnitude, prefix_magnitude, self.factor, self.exponent) } @@ -26,12 +27,13 @@ impl Reducible for Term { impl<'a> Reducible for Cow<'a, [Term]> { fn reduce_value(&self, value: f64) -> f64 { self.iter() - .fold(1.0, |acc, term| acc * term.reduce_value(value)) + .fold(One::one(), |acc, term| acc * term.reduce_value(value)) } fn calculate_magnitude(&self, value: f64) -> f64 { - self.iter() - .fold(1.0, |acc, term| acc * term.calculate_magnitude(value)) + self.iter().fold(One::one(), |acc, term| { + acc * term.calculate_magnitude(value) + }) } } diff --git a/crates/api/src/parser/term/ucum_unit.rs b/crates/api/src/parser/term/ucum_unit.rs index d390918a..0c5ebbc6 100644 --- a/crates/api/src/parser/term/ucum_unit.rs +++ b/crates/api/src/parser/term/ucum_unit.rs @@ -1,7 +1,6 @@ -use super::Term; use crate::{reducible::Reducible, ucum_unit::UcumUnit}; -impl UcumUnit for Term { +impl UcumUnit for super::Term { fn is_special(&self) -> bool { self.atom.map_or(false, |a| a.is_special()) } @@ -33,7 +32,7 @@ impl UcumUnit for Term { } fn scalar(&self) -> f64 { - self.reduce_value(1.0) + self.reduce_value(num_traits::One::one()) } fn magnitude(&self) -> f64 { diff --git a/crates/api/src/unit.rs b/crates/api/src/unit.rs index 5edd01ae..63fe6a27 100644 --- a/crates/api/src/unit.rs +++ b/crates/api/src/unit.rs @@ -19,6 +19,7 @@ mod ucum_unit; #[cfg(feature = "cffi")] pub mod custom_ffi; + #[cfg(feature = "serde")] mod serde; @@ -120,7 +121,7 @@ impl Unit { /// #[must_use] pub fn is_unity(&self) -> bool { - self.terms.len() == 1 && self.terms[0].is_unity() + &*self.terms == term::UNITY_ARRAY_REF } /// Turns the Unit's Terms into Strings and combines them accordingly. diff --git a/crates/api/src/unit/deref.rs b/crates/api/src/unit/deref.rs index 11263035..e96e6bd3 100644 --- a/crates/api/src/unit/deref.rs +++ b/crates/api/src/unit/deref.rs @@ -3,6 +3,7 @@ use crate::{parser::Term, unit::Unit}; //----------------------------------------------------------------------------- // impl Deref //----------------------------------------------------------------------------- +// TODO: Get rid of this in 1.0. impl ::std::ops::Deref for Unit { type Target = [Term]; diff --git a/crates/api/src/unit/reducible.rs b/crates/api/src/unit/reducible.rs index e8fae183..837ecab1 100644 --- a/crates/api/src/unit/reducible.rs +++ b/crates/api/src/unit/reducible.rs @@ -26,7 +26,7 @@ mod tests { #[test] fn $test_name() { let unit = Unit::from_str($unit_str).unwrap(); - assert_relative_eq!(unit.reduce_value(1.0), $expected_value); + assert_relative_eq!(unit.reduce_value(num_traits::One::one()), $expected_value); } }; } @@ -36,7 +36,7 @@ mod tests { #[test] fn $test_name() { let unit = Unit::from_str($unit_str).unwrap(); - let scalar = unit.reduce_value(1.0); + let scalar = unit.reduce_value(num_traits::One::one()); assert_relative_eq!(unit.calculate_magnitude(scalar), $expected_value); } }; diff --git a/crates/api/src/unit/serde.rs b/crates/api/src/unit/serde.rs index 9771e15a..cab7b6b2 100644 --- a/crates/api/src/unit/serde.rs +++ b/crates/api/src/unit/serde.rs @@ -1,9 +1,11 @@ -use super::Unit; +use std::{fmt, str::FromStr}; + use serde::{ de::{self, Deserialize, Deserializer, Unexpected, Visitor}, ser::{Serialize, Serializer}, }; -use std::{fmt, str::FromStr}; + +use super::Unit; struct UnitVisitor; @@ -76,7 +78,7 @@ mod tests { #[test] fn validate_serde_json_empty_terms() { - let expected_unit = Unit::new_unity(); + let expected_unit = crate::unit::UNITY; let expected_json = r#""1""#; validate_unit(&expected_unit, expected_json); validate_json(expected_json, &expected_unit); diff --git a/crates/api/src/unit/term_reducing.rs b/crates/api/src/unit/term_reducing.rs index d0799dfa..7317a2d0 100644 --- a/crates/api/src/unit/term_reducing.rs +++ b/crates/api/src/unit/term_reducing.rs @@ -1,4 +1,6 @@ -use crate::parser::{Atom, Prefix, Term}; +use num_traits::Zero; + +use crate::parser::{term, Atom, Prefix, Term}; use std::collections::BTreeMap; /// Internal struct used for reducing `Term`s. @@ -51,7 +53,7 @@ pub(super) fn reduce_terms(terms: &[Term]) -> Vec { // If everything is reduced away, the effective Unit should be "1". if map.is_empty() { - vec![Term::new_unity()] + vec![term::UNITY] } else { // Reconstructs the map into the Vec. map.into_iter().map(Term::from).collect() @@ -65,7 +67,12 @@ pub(super) fn reduce_terms(terms: &[Term]) -> Vec { fn reduce_to_map(terms: &[Term]) -> BTreeMap { terms .iter() - .map(|term| (ComposableTerm::from(term), term.exponent.unwrap_or(1))) + .map(|term| { + ( + ComposableTerm::from(term), + term.exponent.unwrap_or_else(num_traits::One::one), + ) + }) .fold( BTreeMap::::new(), |mut map, (key, exponent)| { @@ -79,6 +86,6 @@ fn reduce_to_map(terms: &[Term]) -> BTreeMap { ) .into_iter() // Filter out things that have no values - .filter(|(ct, exponent)| ct.has_value() && *exponent != 0) + .filter(|(ct, exponent)| ct.has_value() && !exponent.is_zero()) .collect() } diff --git a/crates/api/src/unit/ucum_unit.rs b/crates/api/src/unit/ucum_unit.rs index 8d49441c..57bc2faa 100644 --- a/crates/api/src/unit/ucum_unit.rs +++ b/crates/api/src/unit/ucum_unit.rs @@ -73,7 +73,7 @@ impl UcumUnit for Unit { /// #[inline] fn scalar(&self) -> f64 { - self.reduce_value(1.0) + self.reduce_value(num_traits::One::one()) } /// The scalar value of `self` in terms of `self`'s actual unit(s). diff --git a/crates/atom_generator/src/generator/atom.rs b/crates/atom_generator/src/generator/atom.rs index 3ee3ae8d..eaa32bd4 100644 --- a/crates/atom_generator/src/generator/atom.rs +++ b/crates/atom_generator/src/generator/atom.rs @@ -66,7 +66,7 @@ pub(super) fn generate_file_body(atom_list: &RustAtomList) -> String { impl UcumUnit for Atom { fn scalar(&self) -> f64 { - self.reduce_value(1.0) + self.reduce_value(num_traits::One::one()) } fn magnitude(&self) -> f64 { From dd56a9cc2840748405e994a64ab0140d3551bcab Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Tue, 6 Feb 2024 14:45:50 -0800 Subject: [PATCH 36/80] Impl ToPrimitive for Measurement --- crates/api/CHANGELOG.md | 16 ++++++ crates/api/src/macros.rs | 7 +++ crates/api/src/measurement.rs | 1 + crates/api/src/measurement/convert.rs | 7 +++ crates/api/src/measurement/num_traits.rs | 1 + crates/api/src/measurement/num_traits/cast.rs | 51 +++++++++++++++++++ crates/api/src/measurement/num_traits/inv.rs | 4 -- crates/api/src/parser/atom.rs | 2 +- 8 files changed, 84 insertions(+), 5 deletions(-) create mode 100644 crates/api/src/measurement/convert.rs create mode 100644 crates/api/src/measurement/num_traits/cast.rs diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 77a4dc00..9c168462 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -10,12 +10,28 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Added - PCC-174: Derive `Hash` for `Atom`. +- PLCC-287: `impl num_traits::Inv for Measurement`, `Unit`, and `Term`. +- PLCC-287: `impl num_traits::One for Measurement`. +- PLCC-287: `impl From<&Measurement> for f64`. +- PLCC-287: `impl num_traits::ToPrimitive for Measurement`. +- Added `Unit::into_terms()` for cases where you just need the `Term`s of the `Unit`. +- Added `unit` constant: `UNITY` +- Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. +- Added `measurement!()` macro for wrapping `Measurement::try_new().unwrap()`. ### Changed - Rust minimum version updated to `1.64.0`. - (Internal) Rust Codegen is now using `quote` instead of `handlebars` (the pest parser grammar is still generated using `handlebars`). +- (Internal) `Definition` is now an enum and is generic over value type `V`. + +### Deprecated + +- PLCC-287: Deprecated traits `Invert`, `ToInverse`, `IntoInverse`; implementations of + `num_traits::Inv` cover these now. +- The new `unit::UNITY` constant deprecates `Unit::is_unity()`. +- The new `term::UNITY*` constants deprecate `Term::is_unity()`. ## [0.22.0] — 2022-03-23 diff --git a/crates/api/src/macros.rs b/crates/api/src/macros.rs index 3079f10c..5a9e6a23 100644 --- a/crates/api/src/macros.rs +++ b/crates/api/src/macros.rs @@ -1,3 +1,10 @@ +#[macro_export] +macro_rules! measurement { + ($value:expr, $unit:expr) => { + $crate::Measurement::try_new($value, $unit).unwrap() + }; +} + /// The `term!` macro makes building `Term`s slightly more ergonomic and terse. /// It was initially made for testing purposes (since `Term`s are really mainly /// used by internal APIs), but since they are used all over the place, it may diff --git a/crates/api/src/measurement.rs b/crates/api/src/measurement.rs index 8e2dd3be..c4362ed5 100644 --- a/crates/api/src/measurement.rs +++ b/crates/api/src/measurement.rs @@ -1,4 +1,5 @@ mod composable; +mod convert; mod convertible; mod display; mod field_eq; diff --git a/crates/api/src/measurement/convert.rs b/crates/api/src/measurement/convert.rs new file mode 100644 index 00000000..55805f43 --- /dev/null +++ b/crates/api/src/measurement/convert.rs @@ -0,0 +1,7 @@ +use crate::{Measurement, UcumUnit}; + +impl<'a> From<&'a Measurement> for f64 { + fn from(measurement: &'a Measurement) -> Self { + measurement.scalar() + } +} diff --git a/crates/api/src/measurement/num_traits.rs b/crates/api/src/measurement/num_traits.rs index f11410fd..59f700ed 100644 --- a/crates/api/src/measurement/num_traits.rs +++ b/crates/api/src/measurement/num_traits.rs @@ -1,2 +1,3 @@ +mod cast; mod identities; mod inv; diff --git a/crates/api/src/measurement/num_traits/cast.rs b/crates/api/src/measurement/num_traits/cast.rs new file mode 100644 index 00000000..2a55392b --- /dev/null +++ b/crates/api/src/measurement/num_traits/cast.rs @@ -0,0 +1,51 @@ +use num_traits::ToPrimitive; + +use crate::Measurement; + +impl ToPrimitive for Measurement { + fn to_i64(&self) -> Option { + ToPrimitive::to_f64(self) + .as_ref() + .and_then(ToPrimitive::to_i64) + } + + fn to_u64(&self) -> Option { + ToPrimitive::to_f64(self) + .as_ref() + .and_then(ToPrimitive::to_u64) + } + + fn to_f64(&self) -> Option { + Some(f64::from(self)) + } +} + +#[cfg(test)] +mod tests { + use approx::assert_ulps_eq; + + use super::*; + + #[test] + fn to_primitive_test() { + let m = measurement!(10.5, "kL"); + assert_ulps_eq!(10.5, f64::from(&m)); + assert_eq!(10, m.to_i64().unwrap()); + assert_eq!(10, m.to_u64().unwrap()); + + let m = measurement!(-10.5, "kL"); + assert_ulps_eq!(-10.5, f64::from(&m)); + assert_eq!(-10, m.to_i64().unwrap()); + assert!(m.to_u64().is_none()); + + let m = measurement!(10.0, "L"); + assert_ulps_eq!(0.01, f64::from(&m)); + assert_eq!(0, m.to_i64().unwrap()); + assert_eq!(0, m.to_u64().unwrap()); + + let m = measurement!(-10.0, "L"); + assert_ulps_eq!(-0.01, f64::from(&m)); + assert_eq!(0, m.to_i64().unwrap()); + assert_eq!(0, m.to_u64().unwrap()); + } +} diff --git a/crates/api/src/measurement/num_traits/inv.rs b/crates/api/src/measurement/num_traits/inv.rs index 43df9389..7dbae8c1 100644 --- a/crates/api/src/measurement/num_traits/inv.rs +++ b/crates/api/src/measurement/num_traits/inv.rs @@ -32,10 +32,6 @@ mod tests { ($test_name:ident, $subject:expr, $expected:expr) => { #[test] fn $test_name() { - // Test &Measurement impl - // let new_measurement = Inv::inv(&$subject); - // assert_eq!(new_measurement, $expected); - // Test &mut Measurement impl let mut mut_borrowed = $subject.clone(); let _ = Inv::inv(&mut mut_borrowed); diff --git a/crates/api/src/parser/atom.rs b/crates/api/src/parser/atom.rs index e8404490..65e4c9e9 100644 --- a/crates/api/src/parser/atom.rs +++ b/crates/api/src/parser/atom.rs @@ -2734,7 +2734,7 @@ impl UcumSymbol for Atom { } impl UcumUnit for Atom { fn scalar(&self) -> f64 { - self.reduce_value(1.0) + self.reduce_value(num_traits::One::one()) } fn magnitude(&self) -> f64 { self.calculate_magnitude(self.scalar()) From b23ffc9f91d86e05e43cc30ef4b35da0d7c29bcf Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Tue, 6 Feb 2024 16:11:23 -0800 Subject: [PATCH 37/80] PLCC-287 impl NumCast for Measurement --- crates/api/CHANGELOG.md | 1 + crates/api/src/measurement/num_traits/cast.rs | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 9c168462..0ec93fcf 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -14,6 +14,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - PLCC-287: `impl num_traits::One for Measurement`. - PLCC-287: `impl From<&Measurement> for f64`. - PLCC-287: `impl num_traits::ToPrimitive for Measurement`. +- PLCC-287: `impl num_traits::NumCast for Measurement`. - Added `Unit::into_terms()` for cases where you just need the `Term`s of the `Unit`. - Added `unit` constant: `UNITY` - Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. diff --git a/crates/api/src/measurement/num_traits/cast.rs b/crates/api/src/measurement/num_traits/cast.rs index 2a55392b..9ceaa327 100644 --- a/crates/api/src/measurement/num_traits/cast.rs +++ b/crates/api/src/measurement/num_traits/cast.rs @@ -20,6 +20,15 @@ impl ToPrimitive for Measurement { } } +impl num_traits::NumCast for Measurement { + fn from(n: T) -> Option { + Some(Self { + value: n.to_f64()?, + unit: crate::unit::UNITY, + }) + } +} + #[cfg(test)] mod tests { use approx::assert_ulps_eq; @@ -48,4 +57,21 @@ mod tests { assert_eq!(0, m.to_i64().unwrap()); assert_eq!(0, m.to_u64().unwrap()); } + + #[test] + fn numcast_test() { + use num_traits::NumCast; + + let output = ::from(std::u32::MAX).unwrap(); + assert_eq!( + Measurement::new(std::u32::MAX.into(), crate::unit::UNITY), + output + ); + + let output = ::from(std::i32::MIN).unwrap(); + assert_eq!( + Measurement::new(std::i32::MIN.into(), crate::unit::UNITY), + output + ); + } } From d5f13dd48342df35de8940d14712112a506b6887 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Tue, 6 Feb 2024 16:17:11 -0800 Subject: [PATCH 38/80] PLCC-287 impl FromPrimitive for Measurement --- crates/api/CHANGELOG.md | 1 + crates/api/src/measurement/num_traits/cast.rs | 31 ++++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 0ec93fcf..6300ca05 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -14,6 +14,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - PLCC-287: `impl num_traits::One for Measurement`. - PLCC-287: `impl From<&Measurement> for f64`. - PLCC-287: `impl num_traits::ToPrimitive for Measurement`. +- PLCC-287: `impl num_traits::FromPrimitive for Measurement`. - PLCC-287: `impl num_traits::NumCast for Measurement`. - Added `Unit::into_terms()` for cases where you just need the `Term`s of the `Unit`. - Added `unit` constant: `UNITY` diff --git a/crates/api/src/measurement/num_traits/cast.rs b/crates/api/src/measurement/num_traits/cast.rs index 9ceaa327..cbabc98b 100644 --- a/crates/api/src/measurement/num_traits/cast.rs +++ b/crates/api/src/measurement/num_traits/cast.rs @@ -1,4 +1,4 @@ -use num_traits::ToPrimitive; +use num_traits::{FromPrimitive, ToPrimitive}; use crate::Measurement; @@ -20,6 +20,20 @@ impl ToPrimitive for Measurement { } } +impl FromPrimitive for Measurement { + fn from_i64(n: i64) -> Option { + n.to_f64().and_then(FromPrimitive::from_f64) + } + + fn from_u64(n: u64) -> Option { + n.to_f64().and_then(FromPrimitive::from_f64) + } + + fn from_f64(n: f64) -> Option { + ::from(n) + } +} + impl num_traits::NumCast for Measurement { fn from(n: T) -> Option { Some(Self { @@ -58,6 +72,21 @@ mod tests { assert_eq!(0, m.to_u64().unwrap()); } + #[test] + fn from_primitive_test() { + let output = Measurement::from_u32(std::u32::MAX).unwrap(); + assert_eq!( + Measurement::new(std::u32::MAX.into(), crate::unit::UNITY), + output + ); + + let output = Measurement::from_i32(std::i32::MAX).unwrap(); + assert_eq!( + Measurement::new(std::i32::MAX.into(), crate::unit::UNITY), + output + ); + } + #[test] fn numcast_test() { use num_traits::NumCast; From 30236e9f0e9b9e51f565b1efe2f5ea203b83e526 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 12 Feb 2024 16:18:24 -0800 Subject: [PATCH 39/80] PLCC-287 impl To/FromPrimitive for Prefix --- crates/api/src/parser/prefix.rs | 56 +++++--- crates/api/src/parser/prefix/num_traits.rs | 1 + .../api/src/parser/prefix/num_traits/cast.rs | 120 ++++++++++++++++++ 3 files changed, 160 insertions(+), 17 deletions(-) create mode 100644 crates/api/src/parser/prefix/num_traits.rs create mode 100644 crates/api/src/parser/prefix/num_traits/cast.rs diff --git a/crates/api/src/parser/prefix.rs b/crates/api/src/parser/prefix.rs index a390c8c1..1af04c6a 100644 --- a/crates/api/src/parser/prefix.rs +++ b/crates/api/src/parser/prefix.rs @@ -1,3 +1,5 @@ +mod num_traits; + use super::{Error, Visit}; use crate::{ parser::{symbols::symbol_parser::Rule, ucum_symbol::UcumSymbol, Classification}, @@ -6,30 +8,50 @@ use crate::{ use pest::iterators::Pair; use std::fmt; -const ATTO: f64 = 1.0e-18; -const CENTI: f64 = 1.0e-2; const DECI: f64 = 1.0e-1; -const DEKA: f64 = 1.0e1; -const EXA: f64 = 1.0e18; +const CENTI: f64 = 1.0e-2; +const MILLI: f64 = 1.0e-3; +const MICRO: f64 = 1.0e-6; +const NANO: f64 = 1.0e-9; +const PICO: f64 = 1.0e-12; const FEMTO: f64 = 1.0e-15; -const GIBI: f64 = 1_073_741_824.0; -const GIGA: f64 = 1.0e9; +const ATTO: f64 = 1.0e-18; +const ZEPTO: f64 = 1.0e-21; +const YOCTO: f64 = 1.0e-24; + +const DEKA: f64 = 1.0e1; const HECTO: f64 = 1.0e2; -const KIBI: f64 = 1024.0; const KILO: f64 = 1.0e3; -const MEBI: f64 = 1_048_576.0; const MEGA: f64 = 1.0e6; -const MICRO: f64 = 1.0e-6; -const MILLI: f64 = 1.0e-3; -const NANO: f64 = 1.0e-9; -const PETA: f64 = 1.0e15; -const PICO: f64 = 1.0e-12; -const TEBI: f64 = 1_099_511_627_776.0; +const GIGA: f64 = 1.0e9; const TERA: f64 = 1.0e12; -const YOCTO: f64 = 1.0e-24; -const YOTTA: f64 = 1.0e24; -const ZEPTO: f64 = 1.0e-21; +const PETA: f64 = 1.0e15; +const EXA: f64 = 1.0e18; const ZETTA: f64 = 1.0e21; +const YOTTA: f64 = 1.0e24; + +const KIBI: f64 = 1024.0; +const MEBI: f64 = 1_048_576.0; +const GIBI: f64 = 1_073_741_824.0; +const TEBI: f64 = 1_099_511_627_776.0; + +pub(crate) mod u128 { + pub(crate) const DEKA: u128 = 10; + pub(crate) const HECTO: u128 = 100; + pub(crate) const KILO: u128 = 1000; + pub(crate) const MEGA: u128 = 1_000_000; + pub(crate) const GIGA: u128 = 1_000_000_000; + pub(crate) const TERA: u128 = 1_000_000_000_000; + pub(crate) const PETA: u128 = 1_000_000_000_000_000; + pub(crate) const EXA: u128 = 1_000_000_000_000_000_000; + pub(crate) const ZETTA: u128 = 1_000_000_000_000_000_000_000; + pub(crate) const YOTTA: u128 = 1_000_000_000_000_000_000_000_000; + + pub(crate) const KIBI: u128 = 1024; + pub(crate) const GIBI: u128 = 1_073_741_824; + pub(crate) const MEBI: u128 = 1_048_576; + pub(crate) const TEBI: u128 = 1_099_511_627_776; +} /// A `Prefix` is essentially a multiplier for an `Atom` within a `Term`; ex. /// the "c" in "cm" modifies meter by 0.01. The UCUM spec says these should diff --git a/crates/api/src/parser/prefix/num_traits.rs b/crates/api/src/parser/prefix/num_traits.rs new file mode 100644 index 00000000..f64549ca --- /dev/null +++ b/crates/api/src/parser/prefix/num_traits.rs @@ -0,0 +1 @@ +mod cast; diff --git a/crates/api/src/parser/prefix/num_traits/cast.rs b/crates/api/src/parser/prefix/num_traits/cast.rs new file mode 100644 index 00000000..8a8f9914 --- /dev/null +++ b/crates/api/src/parser/prefix/num_traits/cast.rs @@ -0,0 +1,120 @@ +use approx::ulps_eq; +use num_traits::{FromPrimitive, ToPrimitive}; + +use crate::{parser::prefix, Prefix, UcumSymbol}; + +impl ToPrimitive for Prefix { + fn to_u64(&self) -> Option { + self.to_u128().as_ref().and_then(ToPrimitive::to_u64) + } + + fn to_i64(&self) -> Option { + self.to_u128().as_ref().and_then(ToPrimitive::to_i64) + } + + fn to_i128(&self) -> Option { + self.to_u128().as_ref().and_then(ToPrimitive::to_i128) + } + + fn to_u128(&self) -> Option { + match self { + Self::Atto + | Self::Centi + | Self::Deci + | Self::Femto + | Self::Micro + | Self::Milli + | Self::Nano + | Self::Pico + | Self::Yocto + | Self::Zepto => Some(0), + Self::Deka => Some(prefix::u128::DEKA), + Self::Exa => Some(prefix::u128::EXA), + Self::Gibi => Some(prefix::u128::GIBI), + Self::Giga => Some(prefix::u128::GIGA), + Self::Hecto => Some(prefix::u128::HECTO), + Self::Kibi => Some(prefix::u128::KIBI), + Self::Kilo => Some(prefix::u128::KILO), + Self::Mebi => Some(prefix::u128::MEBI), + Self::Mega => Some(prefix::u128::MEGA), + Self::Peta => Some(prefix::u128::PETA), + Self::Tebi => Some(prefix::u128::TEBI), + Self::Tera => Some(prefix::u128::TERA), + Self::Yotta => Some(prefix::u128::YOTTA), + Self::Zetta => Some(prefix::u128::ZETTA), + } + } + + fn to_f64(&self) -> Option { + Some(self.definition_value()) + } +} + +impl FromPrimitive for Prefix { + fn from_u64(n: u64) -> Option { + FromPrimitive::from_u128(From::from(n)) + } + + fn from_i64(n: i64) -> Option { + FromPrimitive::from_i128(From::from(n)) + } + + #[allow(clippy::cast_sign_loss)] + fn from_i128(n: i128) -> Option { + FromPrimitive::from_u128(n as u128) + } + + fn from_u128(n: u128) -> Option { + match n { + prefix::u128::DEKA => Some(Self::Deka), + prefix::u128::HECTO => Some(Self::Hecto), + prefix::u128::KILO => Some(Self::Kilo), + prefix::u128::MEGA => Some(Self::Mega), + prefix::u128::GIGA => Some(Self::Giga), + prefix::u128::TERA => Some(Self::Tera), + prefix::u128::PETA => Some(Self::Peta), + prefix::u128::EXA => Some(Self::Exa), + prefix::u128::ZETTA => Some(Self::Zetta), + prefix::u128::YOTTA => Some(Self::Yotta), + _ => None, + } + } + + fn from_f64(n: f64) -> Option { + macro_rules! try_translate { + ($constant:ident => $variant:ident) => { + if ulps_eq!(n, prefix::$constant) { + return Some(Self::$variant); + } + }; + } + + try_translate!(DECI => Deci); // 1e-1 + try_translate!(DEKA => Deka); // 1e1 + try_translate!(CENTI => Centi); // 1e-2 + try_translate!(HECTO => Hecto); // 1e2 + try_translate!(MILLI => Milli); // 1e-3 + try_translate!(KILO => Kilo); // 1e3 + try_translate!(MICRO => Micro); // 1e-6 + try_translate!(MEGA => Mega); // 1e6 + try_translate!(NANO => Nano); // 1e-9 + try_translate!(GIGA => Giga); // 1e9 + try_translate!(PICO => Pico); // 1e-12 + try_translate!(TERA => Tera); // 1e12 + try_translate!(FEMTO => Femto); // 1e-15 + try_translate!(PETA => Peta); // 1e15 + try_translate!(ATTO => Atto); // 1e-18 + try_translate!(EXA => Exa); // 1e18 + try_translate!(ZEPTO => Zepto); // 1e-21 + try_translate!(ZETTA => Zetta); // 1e21 + try_translate!(YOCTO => Yocto); // 1e-24 + try_translate!(YOTTA => Yotta); // 1e24 + + try_translate!(KIBI => Kibi); + try_translate!(MEBI => Mebi); + try_translate!(GIBI => Gibi); + try_translate!(TEBI => Tebi); + + None + } +} From 82480ac074d9d7acfce8c1adc693db3f0c0335ed Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 12 Feb 2024 16:37:37 -0800 Subject: [PATCH 40/80] PLCC-287 impl Pow for Measurement, Unit, Term --- crates/api/src/measurement/num_traits.rs | 1 + crates/api/src/measurement/num_traits/pow.rs | 35 +++++++++++++++ crates/api/src/parser/term/num_traits.rs | 1 + crates/api/src/parser/term/num_traits/pow.rs | 45 ++++++++++++++++++++ crates/api/src/unit/num_traits.rs | 1 + crates/api/src/unit/num_traits/pow.rs | 41 ++++++++++++++++++ 6 files changed, 124 insertions(+) create mode 100644 crates/api/src/measurement/num_traits/pow.rs create mode 100644 crates/api/src/parser/term/num_traits/pow.rs create mode 100644 crates/api/src/unit/num_traits/pow.rs diff --git a/crates/api/src/measurement/num_traits.rs b/crates/api/src/measurement/num_traits.rs index 59f700ed..bd291e56 100644 --- a/crates/api/src/measurement/num_traits.rs +++ b/crates/api/src/measurement/num_traits.rs @@ -1,3 +1,4 @@ mod cast; mod identities; mod inv; +mod pow; diff --git a/crates/api/src/measurement/num_traits/pow.rs b/crates/api/src/measurement/num_traits/pow.rs new file mode 100644 index 00000000..1f96a0ad --- /dev/null +++ b/crates/api/src/measurement/num_traits/pow.rs @@ -0,0 +1,35 @@ +use num_traits::Pow; + +use crate::Measurement; + +impl Pow for Measurement { + type Output = Self; + + fn pow(self, rhs: i32) -> Self::Output { + Self { + value: self.value.pow(rhs), + unit: self.unit.pow(rhs), + } + } +} + +impl<'a> Pow for &'a Measurement { + type Output = Measurement; + + fn pow(self, rhs: i32) -> Self::Output { + Measurement { + value: self.value.pow(rhs), + unit: self.unit.clone().pow(rhs), + } + } +} + +impl<'a> Pow for &'a mut Measurement { + type Output = Self; + + fn pow(self, rhs: i32) -> Self::Output { + self.value = self.value.pow(rhs); + let _ = Pow::pow(&mut self.unit, rhs); + self + } +} diff --git a/crates/api/src/parser/term/num_traits.rs b/crates/api/src/parser/term/num_traits.rs index 932954a9..5b217aca 100644 --- a/crates/api/src/parser/term/num_traits.rs +++ b/crates/api/src/parser/term/num_traits.rs @@ -1 +1,2 @@ mod inv; +mod pow; diff --git a/crates/api/src/parser/term/num_traits/pow.rs b/crates/api/src/parser/term/num_traits/pow.rs new file mode 100644 index 00000000..95e2ec17 --- /dev/null +++ b/crates/api/src/parser/term/num_traits/pow.rs @@ -0,0 +1,45 @@ +use num_traits::Pow; + +use crate::Term; + +impl Pow for Term { + type Output = Self; + + fn pow(self, rhs: i32) -> Self::Output { + let exponent = self.exponent.map_or(rhs, |exp| exp * rhs); + + Self { + factor: self.factor, + prefix: self.prefix, + atom: self.atom, + exponent: Some(exponent), + annotation: self.annotation, + } + } +} + +impl<'a> Pow for &'a Term { + type Output = Term; + + fn pow(self, rhs: i32) -> Self::Output { + let exponent = self.exponent.map_or(rhs, |exp| exp * rhs); + + Term { + factor: self.factor, + prefix: self.prefix, + atom: self.atom, + exponent: Some(exponent), + annotation: self.annotation.clone(), + } + } +} + +impl<'a> Pow for &'a mut Term { + type Output = Self; + + fn pow(self, rhs: i32) -> Self::Output { + self.exponent = Some(self.exponent.map_or(rhs, |exp| exp * rhs)); + + self + } +} diff --git a/crates/api/src/unit/num_traits.rs b/crates/api/src/unit/num_traits.rs index 932954a9..5b217aca 100644 --- a/crates/api/src/unit/num_traits.rs +++ b/crates/api/src/unit/num_traits.rs @@ -1 +1,2 @@ mod inv; +mod pow; diff --git a/crates/api/src/unit/num_traits/pow.rs b/crates/api/src/unit/num_traits/pow.rs new file mode 100644 index 00000000..976b3f8a --- /dev/null +++ b/crates/api/src/unit/num_traits/pow.rs @@ -0,0 +1,41 @@ +use num_traits::Pow; + +use crate::Unit; + +impl Pow for Unit { + type Output = Self; + + fn pow(self, rhs: i32) -> Self::Output { + Self::new( + self.terms + .iter() + .cloned() + .map(|term| term.pow(rhs)) + .collect::>(), + ) + } +} + +impl<'a> Pow for &'a Unit { + type Output = Unit; + + fn pow(self, rhs: i32) -> Self::Output { + Unit::new( + self.terms + .iter() + .map(|term| term.clone().pow(rhs)) + .collect::>(), + ) + } +} + +impl<'a> Pow for &'a mut Unit { + type Output = Self; + + fn pow(self, rhs: i32) -> Self::Output { + self.terms.to_mut().iter_mut().for_each(|term| { + let _ = Pow::pow(term, rhs); + }); + self + } +} From 48a9e83daef46288a1b98e81d3b22583070998b0 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 12 Feb 2024 17:09:51 -0800 Subject: [PATCH 41/80] PLCC-287 impl Neg for Measurement --- crates/api/CHANGELOG.md | 10 +- crates/api/src/macros.rs | 14 +- crates/api/src/measurement/num_traits/pow.rs | 24 ++ crates/api/src/measurement/ops.rs | 71 +++- crates/api/src/parser/atom_test.rs | 2 +- crates/api/src/parser/prefix.rs | 2 +- .../api/src/parser/prefix/num_traits/cast.rs | 316 ++++++++++++++++-- crates/api/src/parser/term.rs | 2 +- .../src/parser/term/annotation_composable.rs | 5 +- crates/api/src/parser/term/composable.rs | 2 +- crates/api/src/parser/term/display.rs | 2 +- crates/api/src/parser/term/invert.rs | 10 +- .../api/src/parser/term/is_compatible_with.rs | 5 +- crates/api/src/parser/term/num_traits.rs | 2 +- crates/api/src/parser/term/num_traits/inv.rs | 16 +- crates/api/src/parser/term/num_traits/pow.rs | 62 ++++ crates/api/src/parser/term/reducible.rs | 5 +- crates/api/src/parser/terms/mapper.rs | 2 +- .../api/src/parser/terms/mapper/ast_term.rs | 7 +- crates/api/src/unit/num_traits/pow.rs | 26 ++ crates/api/src/unit/to_reduced.rs | 8 +- 21 files changed, 508 insertions(+), 85 deletions(-) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 6300ca05..e36754c8 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -13,10 +13,12 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - PLCC-287: `impl num_traits::Inv for Measurement`, `Unit`, and `Term`. - PLCC-287: `impl num_traits::One for Measurement`. - PLCC-287: `impl From<&Measurement> for f64`. -- PLCC-287: `impl num_traits::ToPrimitive for Measurement`. -- PLCC-287: `impl num_traits::FromPrimitive for Measurement`. +- PLCC-287: `impl num_traits::ToPrimitive for Measurement`, `Prefix`. +- PLCC-287: `impl num_traits::FromPrimitive for Measurement`, `Prefix`. - PLCC-287: `impl num_traits::NumCast for Measurement`. -- Added `Unit::into_terms()` for cases where you just need the `Term`s of the `Unit`. +- PLCC-287: `impl num_traits::Pow for Measurement`, `Unit`, `Term`. +- PLCC-287: `impl std::ops::Neg for Measurement`. +- Added `Unit::into_terms()` for cases where you only need the `Term`s of the `Unit`. - Added `unit` constant: `UNITY` - Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. - Added `measurement!()` macro for wrapping `Measurement::try_new().unwrap()`. @@ -41,7 +43,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Implemented `AsRef` for `Measurement` and `Unit`. Allows for downstream wrapper types to implement other functionality for all types via the `AsRef` implementation. -- Implemented `TryFrom<&str> for Unit` (which just calls `from_str()`) to allow for downstream +- Implemented `TryFrom<&str> for Unit` (which only calls `from_str()`) to allow for downstream wrapper implementations around `Unit`. - New `const` `Composition` methods: `new_dimless()`, `new_any()`. - New `composition` `const`s for common dimensional compositions. diff --git a/crates/api/src/macros.rs b/crates/api/src/macros.rs index 5a9e6a23..2398a0ca 100644 --- a/crates/api/src/macros.rs +++ b/crates/api/src/macros.rs @@ -19,7 +19,7 @@ macro_rules! term { ($prefix:ident, $atom:ident, $($attribute_name:ident: $attribute_value:expr),+) => { { - let mut term = Term::new(Some(Prefix::$prefix), Some(Atom::$atom)); + let mut term = $crate::Term::new(Some($crate::Prefix::$prefix), Some($crate::Atom::$atom)); $( term!(@params term, $attribute_name: $attribute_value); )+ @@ -28,12 +28,12 @@ macro_rules! term { }; ($prefix:ident, $atom:ident) => { - Term::new(Some(Prefix::$prefix), Some(Atom::$atom)) + $crate::Term::new(Some(Prefix::$prefix), Some($crate::Atom::$atom)) }; ($atom:ident, $($attribute_name:ident: $attribute_value:expr),+) => { { - let mut term = Term::new(None, Some(Atom::$atom)); + let mut term = $crate::Term::new(None, Some($crate::Atom::$atom)); $( term!(@params term, $attribute_name: $attribute_value); )+ @@ -42,12 +42,12 @@ macro_rules! term { }; ($atom:ident) => { - Term::new(None, Some(Atom::$atom)) + $crate::Term::new(None, Some($crate::Atom::$atom)) }; ($($attribute_name:ident: $attribute_value:expr),+) => { { - let mut term = Term::default(); + let mut term = $crate::Term::default(); $( term!(@params term, $attribute_name: $attribute_value); )+ @@ -56,14 +56,14 @@ macro_rules! term { }; () => { - Term::default() + $crate::Term::default() }; } #[macro_export] macro_rules! terms { ($($term:expr),*) => { - std::borrow::Cow::<[Term]>::Owned(vec![$($term)*]) + std::borrow::Cow::<[$crate::Term]>::Owned(vec![$($term)*]) }; } diff --git a/crates/api/src/measurement/num_traits/pow.rs b/crates/api/src/measurement/num_traits/pow.rs index 1f96a0ad..ab86245f 100644 --- a/crates/api/src/measurement/num_traits/pow.rs +++ b/crates/api/src/measurement/num_traits/pow.rs @@ -33,3 +33,27 @@ impl<'a> Pow for &'a mut Measurement { self } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn owned_test() { + let subject = measurement!(10.0, "L"); + assert_eq!(Pow::pow(subject, 2), measurement!(100.0, "L2")); + } + + #[test] + fn borrowed_test() { + let subject = measurement!(10.0, "L"); + assert_eq!(Pow::pow(&subject, 2), measurement!(100.0, "L2")); + } + + #[test] + fn mut_borrowed_test() { + let mut subject = measurement!(10.0, "L"); + let _ = Pow::pow(&mut subject, 2); + assert_eq!(subject, measurement!(100.0, "L2")); + } +} diff --git a/crates/api/src/measurement/ops.rs b/crates/api/src/measurement/ops.rs index 192436d5..b66acf11 100644 --- a/crates/api/src/measurement/ops.rs +++ b/crates/api/src/measurement/ops.rs @@ -2,7 +2,41 @@ #![allow(clippy::result_large_err)] use crate::{convertible::Convertible, error::Error, measurement::Measurement}; -use std::ops::{Add, Div, Mul, Sub}; +use std::ops::{Add, Div, Mul, Neg, Sub}; + +// ╭──────────╮ +// │ impl Neg │ +// ╰──────────╯ +impl Neg for Measurement { + type Output = Self; + + fn neg(self) -> Self::Output { + Self { + value: self.value.neg(), + unit: self.unit, + } + } +} + +impl<'a> Neg for &'a Measurement { + type Output = Measurement; + + fn neg(self) -> Self::Output { + Measurement { + value: self.value.neg(), + unit: self.unit.clone(), + } + } +} + +impl<'a> Neg for &'a mut Measurement { + type Output = Self; + + fn neg(self) -> Self::Output { + self.value = self.value.neg(); + self + } +} //----------------------------------------------------------------------------- // impl Add @@ -327,8 +361,41 @@ mod tests { }; } + mod neg { + use std::ops::Neg; + + #[test] + fn owned_test() { + let subject = measurement!(10.0, "L"); + assert_eq!(Neg::neg(subject), measurement!(-10.0, "L")); + + let subject = measurement!(-10.0, "L"); + assert_eq!(Neg::neg(subject), measurement!(10.0, "L")); + } + + #[test] + fn borrowed_test() { + let subject = measurement!(10.0, "L"); + assert_eq!(Neg::neg(&subject), measurement!(-10.0, "L")); + + let subject = measurement!(-10.0, "L"); + assert_eq!(Neg::neg(&subject), measurement!(10.0, "L")); + } + + #[test] + fn mut_borrowed_test() { + let mut subject = measurement!(10.0, "L"); + let _ = Neg::neg(&mut subject); + assert_eq!(subject, measurement!(-10.0, "L")); + + let mut subject = measurement!(-10.0, "L"); + let _ = Neg::neg(&mut subject); + assert_eq!(subject, measurement!(10.0, "L")); + } + } /* neg */ + mod add { - use crate::{Term, Unit}; + use crate::Unit; use super::*; diff --git a/crates/api/src/parser/atom_test.rs b/crates/api/src/parser/atom_test.rs index 59ad27e7..e8e5bf5d 100644 --- a/crates/api/src/parser/atom_test.rs +++ b/crates/api/src/parser/atom_test.rs @@ -4,7 +4,7 @@ use crate::{ parser::{ - term::UNITY_ARRAY, Atom, Classification, Composable, Composition, Dimension, Prefix, Term, + term::UNITY_ARRAY, Atom, Classification, Composable, Composition, Dimension, Prefix, UcumSymbol, }, ucum_unit::UcumUnit, diff --git a/crates/api/src/parser/prefix.rs b/crates/api/src/parser/prefix.rs index 1af04c6a..d9ab6b88 100644 --- a/crates/api/src/parser/prefix.rs +++ b/crates/api/src/parser/prefix.rs @@ -48,8 +48,8 @@ pub(crate) mod u128 { pub(crate) const YOTTA: u128 = 1_000_000_000_000_000_000_000_000; pub(crate) const KIBI: u128 = 1024; - pub(crate) const GIBI: u128 = 1_073_741_824; pub(crate) const MEBI: u128 = 1_048_576; + pub(crate) const GIBI: u128 = 1_073_741_824; pub(crate) const TEBI: u128 = 1_099_511_627_776; } diff --git a/crates/api/src/parser/prefix/num_traits/cast.rs b/crates/api/src/parser/prefix/num_traits/cast.rs index 8a8f9914..8adbb4be 100644 --- a/crates/api/src/parser/prefix/num_traits/cast.rs +++ b/crates/api/src/parser/prefix/num_traits/cast.rs @@ -1,5 +1,4 @@ -use approx::ulps_eq; -use num_traits::{FromPrimitive, ToPrimitive}; +use num_traits::{FromPrimitive, ToPrimitive, Zero}; use crate::{parser::prefix, Prefix, UcumSymbol}; @@ -18,30 +17,31 @@ impl ToPrimitive for Prefix { fn to_u128(&self) -> Option { match self { - Self::Atto + Self::Deci | Self::Centi - | Self::Deci - | Self::Femto - | Self::Micro | Self::Milli + | Self::Micro | Self::Nano | Self::Pico - | Self::Yocto - | Self::Zepto => Some(0), - Self::Deka => Some(prefix::u128::DEKA), - Self::Exa => Some(prefix::u128::EXA), - Self::Gibi => Some(prefix::u128::GIBI), - Self::Giga => Some(prefix::u128::GIGA), - Self::Hecto => Some(prefix::u128::HECTO), - Self::Kibi => Some(prefix::u128::KIBI), - Self::Kilo => Some(prefix::u128::KILO), - Self::Mebi => Some(prefix::u128::MEBI), - Self::Mega => Some(prefix::u128::MEGA), - Self::Peta => Some(prefix::u128::PETA), - Self::Tebi => Some(prefix::u128::TEBI), - Self::Tera => Some(prefix::u128::TERA), - Self::Yotta => Some(prefix::u128::YOTTA), - Self::Zetta => Some(prefix::u128::ZETTA), + | Self::Femto + | Self::Atto + | Self::Zepto + | Self::Yocto => Some(0), + Self::Deka => Some(prefix::u128::DEKA), // 1e1 + Self::Hecto => Some(prefix::u128::HECTO), // 1e2 + Self::Kilo => Some(prefix::u128::KILO), // 1e3 + Self::Mega => Some(prefix::u128::MEGA), // 1e6 + Self::Giga => Some(prefix::u128::GIGA), // 1e9 + Self::Tera => Some(prefix::u128::TERA), // 1e12 + Self::Peta => Some(prefix::u128::PETA), // 1e15 + Self::Exa => Some(prefix::u128::EXA), // 1e18 + Self::Zetta => Some(prefix::u128::ZETTA), // 1e21 + Self::Yotta => Some(prefix::u128::YOTTA), // 1e24 + + Self::Kibi => Some(prefix::u128::KIBI), // 1K + Self::Mebi => Some(prefix::u128::MEBI), // 1M + Self::Gibi => Some(prefix::u128::GIBI), // 1G + Self::Tebi => Some(prefix::u128::TEBI), // 1T } } @@ -59,9 +59,8 @@ impl FromPrimitive for Prefix { FromPrimitive::from_i128(From::from(n)) } - #[allow(clippy::cast_sign_loss)] fn from_i128(n: i128) -> Option { - FromPrimitive::from_u128(n as u128) + u128::try_from(n).map_or(None, FromPrimitive::from_u128) } fn from_u128(n: u128) -> Option { @@ -83,33 +82,40 @@ impl FromPrimitive for Prefix { fn from_f64(n: f64) -> Option { macro_rules! try_translate { ($constant:ident => $variant:ident) => { - if ulps_eq!(n, prefix::$constant) { + // We use YOCTO here as the epsilon to be able to determine the difference between + // 0.0 and YOCTO; using std::f64::EPSILON doesn't not give enough precision. + if approx::ulps_eq!(n, prefix::$constant, epsilon = prefix::YOCTO) { return Some(Self::$variant); } }; } - try_translate!(DECI => Deci); // 1e-1 + if n.is_zero() { + return None; + } + try_translate!(DEKA => Deka); // 1e1 - try_translate!(CENTI => Centi); // 1e-2 try_translate!(HECTO => Hecto); // 1e2 - try_translate!(MILLI => Milli); // 1e-3 try_translate!(KILO => Kilo); // 1e3 - try_translate!(MICRO => Micro); // 1e-6 try_translate!(MEGA => Mega); // 1e6 - try_translate!(NANO => Nano); // 1e-9 try_translate!(GIGA => Giga); // 1e9 - try_translate!(PICO => Pico); // 1e-12 try_translate!(TERA => Tera); // 1e12 - try_translate!(FEMTO => Femto); // 1e-15 try_translate!(PETA => Peta); // 1e15 - try_translate!(ATTO => Atto); // 1e-18 try_translate!(EXA => Exa); // 1e18 - try_translate!(ZEPTO => Zepto); // 1e-21 try_translate!(ZETTA => Zetta); // 1e21 - try_translate!(YOCTO => Yocto); // 1e-24 try_translate!(YOTTA => Yotta); // 1e24 + try_translate!(YOCTO => Yocto); // 1e-24 + try_translate!(ZEPTO => Zepto); // 1e-21 + try_translate!(ATTO => Atto); // 1e-18 + try_translate!(FEMTO => Femto); // 1e-15 + try_translate!(PICO => Pico); // 1e-12 + try_translate!(NANO => Nano); // 1e-9 + try_translate!(MICRO => Micro); // 1e-6 + try_translate!(MILLI => Milli); // 1e-3 + try_translate!(CENTI => Centi); // 1e-2 + try_translate!(DECI => Deci); // 1e-1 + try_translate!(KIBI => Kibi); try_translate!(MEBI => Mebi); try_translate!(GIBI => Gibi); @@ -118,3 +124,243 @@ impl FromPrimitive for Prefix { None } } + +#[cfg(test)] +mod tests { + use super::*; + + mod to_primitive { + use approx::assert_ulps_eq; + + use super::*; + + #[test] + fn to_u128_test() { + assert_eq!(Prefix::Atto.to_u128().unwrap(), 0); + assert_eq!(Prefix::Centi.to_u128().unwrap(), 0); + assert_eq!(Prefix::Deci.to_u128().unwrap(), 0); + assert_eq!(Prefix::Femto.to_u128().unwrap(), 0); + assert_eq!(Prefix::Micro.to_u128().unwrap(), 0); + assert_eq!(Prefix::Milli.to_u128().unwrap(), 0); + assert_eq!(Prefix::Nano.to_u128().unwrap(), 0); + assert_eq!(Prefix::Pico.to_u128().unwrap(), 0); + assert_eq!(Prefix::Yocto.to_u128().unwrap(), 0); + assert_eq!(Prefix::Zepto.to_u128().unwrap(), 0); + + assert_eq!(Prefix::Deka.to_u128().unwrap(), 10); + assert_eq!(Prefix::Hecto.to_u128().unwrap(), 100); + assert_eq!(Prefix::Kilo.to_u128().unwrap(), 1000); + assert_eq!(Prefix::Mega.to_u128().unwrap(), 1_000_000); + assert_eq!(Prefix::Giga.to_u128().unwrap(), 1_000_000_000); + assert_eq!(Prefix::Tera.to_u128().unwrap(), 1_000_000_000_000); + assert_eq!(Prefix::Peta.to_u128().unwrap(), 1_000_000_000_000_000); + assert_eq!(Prefix::Exa.to_u128().unwrap(), 1_000_000_000_000_000_000); + assert_eq!( + Prefix::Zetta.to_u128().unwrap(), + 1_000_000_000_000_000_000_000 + ); + assert_eq!( + Prefix::Yotta.to_u128().unwrap(), + 1_000_000_000_000_000_000_000_000 + ); + + assert_eq!(Prefix::Kibi.to_u128().unwrap(), 1024); + assert_eq!(Prefix::Mebi.to_u128().unwrap(), 1_048_576); + assert_eq!(Prefix::Gibi.to_u128().unwrap(), 1_073_741_824); + assert_eq!(Prefix::Tebi.to_u128().unwrap(), 1_099_511_627_776); + } + + #[test] + fn to_i128_test() { + assert_eq!(Prefix::Atto.to_i128().unwrap(), 0); + assert_eq!(Prefix::Centi.to_i128().unwrap(), 0); + assert_eq!(Prefix::Deci.to_i128().unwrap(), 0); + assert_eq!(Prefix::Femto.to_i128().unwrap(), 0); + assert_eq!(Prefix::Micro.to_i128().unwrap(), 0); + assert_eq!(Prefix::Milli.to_i128().unwrap(), 0); + assert_eq!(Prefix::Nano.to_i128().unwrap(), 0); + assert_eq!(Prefix::Pico.to_i128().unwrap(), 0); + assert_eq!(Prefix::Yocto.to_i128().unwrap(), 0); + assert_eq!(Prefix::Zepto.to_i128().unwrap(), 0); + + assert_eq!(Prefix::Deka.to_i128().unwrap(), 10); + assert_eq!(Prefix::Hecto.to_i128().unwrap(), 100); + assert_eq!(Prefix::Kilo.to_i128().unwrap(), 1000); + assert_eq!(Prefix::Mega.to_i128().unwrap(), 1_000_000); + assert_eq!(Prefix::Giga.to_i128().unwrap(), 1_000_000_000); + assert_eq!(Prefix::Tera.to_i128().unwrap(), 1_000_000_000_000); + assert_eq!(Prefix::Peta.to_i128().unwrap(), 1_000_000_000_000_000); + assert_eq!(Prefix::Exa.to_i128().unwrap(), 1_000_000_000_000_000_000); + assert_eq!( + Prefix::Zetta.to_i128().unwrap(), + 1_000_000_000_000_000_000_000 + ); + assert_eq!( + Prefix::Yotta.to_i128().unwrap(), + 1_000_000_000_000_000_000_000_000 + ); + + assert_eq!(Prefix::Kibi.to_i128().unwrap(), 1024); + assert_eq!(Prefix::Mebi.to_i128().unwrap(), 1_048_576); + assert_eq!(Prefix::Gibi.to_i128().unwrap(), 1_073_741_824); + assert_eq!(Prefix::Tebi.to_i128().unwrap(), 1_099_511_627_776); + } + + #[test] + fn to_u64_test() { + assert_eq!(Prefix::Atto.to_u64().unwrap(), 0); + assert_eq!(Prefix::Centi.to_u64().unwrap(), 0); + assert_eq!(Prefix::Deci.to_u64().unwrap(), 0); + assert_eq!(Prefix::Femto.to_u64().unwrap(), 0); + assert_eq!(Prefix::Micro.to_u64().unwrap(), 0); + assert_eq!(Prefix::Milli.to_u64().unwrap(), 0); + assert_eq!(Prefix::Nano.to_u64().unwrap(), 0); + assert_eq!(Prefix::Pico.to_u64().unwrap(), 0); + assert_eq!(Prefix::Yocto.to_u64().unwrap(), 0); + assert_eq!(Prefix::Zepto.to_u64().unwrap(), 0); + + assert_eq!(Prefix::Deka.to_u64().unwrap(), 10); + assert_eq!(Prefix::Hecto.to_u64().unwrap(), 100); + assert_eq!(Prefix::Kilo.to_u64().unwrap(), 1000); + assert_eq!(Prefix::Mega.to_u64().unwrap(), 1_000_000); + assert_eq!(Prefix::Giga.to_u64().unwrap(), 1_000_000_000); + assert_eq!(Prefix::Tera.to_u64().unwrap(), 1_000_000_000_000); + assert_eq!(Prefix::Peta.to_u64().unwrap(), 1_000_000_000_000_000); + assert_eq!(Prefix::Exa.to_u64().unwrap(), 1_000_000_000_000_000_000); + assert!(Prefix::Zetta.to_u64().is_none(),); + assert!(Prefix::Yotta.to_u64().is_none(),); + + assert_eq!(Prefix::Kibi.to_u64().unwrap(), 1024); + assert_eq!(Prefix::Mebi.to_u64().unwrap(), 1_048_576); + assert_eq!(Prefix::Gibi.to_u64().unwrap(), 1_073_741_824); + assert_eq!(Prefix::Tebi.to_u64().unwrap(), 1_099_511_627_776); + } + + #[test] + fn to_i64_test() { + assert_eq!(Prefix::Atto.to_i64().unwrap(), 0); + assert_eq!(Prefix::Centi.to_i64().unwrap(), 0); + assert_eq!(Prefix::Deci.to_i64().unwrap(), 0); + assert_eq!(Prefix::Femto.to_i64().unwrap(), 0); + assert_eq!(Prefix::Micro.to_i64().unwrap(), 0); + assert_eq!(Prefix::Milli.to_i64().unwrap(), 0); + assert_eq!(Prefix::Nano.to_i64().unwrap(), 0); + assert_eq!(Prefix::Pico.to_i64().unwrap(), 0); + assert_eq!(Prefix::Yocto.to_i64().unwrap(), 0); + assert_eq!(Prefix::Zepto.to_i64().unwrap(), 0); + + assert_eq!(Prefix::Deka.to_i64().unwrap(), 10); + assert_eq!(Prefix::Hecto.to_i64().unwrap(), 100); + assert_eq!(Prefix::Kilo.to_i64().unwrap(), 1000); + assert_eq!(Prefix::Mega.to_i64().unwrap(), 1_000_000); + assert_eq!(Prefix::Giga.to_i64().unwrap(), 1_000_000_000); + assert_eq!(Prefix::Tera.to_i64().unwrap(), 1_000_000_000_000); + assert_eq!(Prefix::Peta.to_i64().unwrap(), 1_000_000_000_000_000); + assert_eq!(Prefix::Exa.to_i64().unwrap(), 1_000_000_000_000_000_000); + assert!(Prefix::Zetta.to_i64().is_none(),); + assert!(Prefix::Yotta.to_i64().is_none(),); + + assert_eq!(Prefix::Kibi.to_i64().unwrap(), 1024); + assert_eq!(Prefix::Mebi.to_i64().unwrap(), 1_048_576); + assert_eq!(Prefix::Gibi.to_i64().unwrap(), 1_073_741_824); + assert_eq!(Prefix::Tebi.to_i64().unwrap(), 1_099_511_627_776); + } + + #[test] + fn to_f64_test() { + assert_ulps_eq!(Prefix::Deci.to_f64().unwrap(), 1e-1); + assert_ulps_eq!(Prefix::Centi.to_f64().unwrap(), 1e-2); + assert_ulps_eq!(Prefix::Milli.to_f64().unwrap(), 1e-3); + assert_ulps_eq!(Prefix::Micro.to_f64().unwrap(), 1e-6); + assert_ulps_eq!(Prefix::Nano.to_f64().unwrap(), 1e-9); + assert_ulps_eq!(Prefix::Pico.to_f64().unwrap(), 1e-12); + assert_ulps_eq!(Prefix::Femto.to_f64().unwrap(), 1e-15); + assert_ulps_eq!(Prefix::Atto.to_f64().unwrap(), 1e-18); + assert_ulps_eq!(Prefix::Zepto.to_f64().unwrap(), 1e-21); + assert_ulps_eq!(Prefix::Yocto.to_f64().unwrap(), 1e-24); + + assert_ulps_eq!(Prefix::Deka.to_f64().unwrap(), 1e1); + assert_ulps_eq!(Prefix::Hecto.to_f64().unwrap(), 1e2); + assert_ulps_eq!(Prefix::Kilo.to_f64().unwrap(), 1e3); + assert_ulps_eq!(Prefix::Mega.to_f64().unwrap(), 1e6); + assert_ulps_eq!(Prefix::Giga.to_f64().unwrap(), 1e9); + assert_ulps_eq!(Prefix::Tera.to_f64().unwrap(), 1e12); + assert_ulps_eq!(Prefix::Peta.to_f64().unwrap(), 1e15); + assert_ulps_eq!(Prefix::Exa.to_f64().unwrap(), 1e18); + assert_ulps_eq!(Prefix::Zetta.to_f64().unwrap(), 1e21); + assert_ulps_eq!(Prefix::Yotta.to_f64().unwrap(), 1e24); + + assert_ulps_eq!(Prefix::Kibi.to_f64().unwrap(), 1024.0); + assert_ulps_eq!(Prefix::Mebi.to_f64().unwrap(), 1_048_576.0); + assert_ulps_eq!(Prefix::Gibi.to_f64().unwrap(), 1_073_741_824.0); + assert_ulps_eq!(Prefix::Tebi.to_f64().unwrap(), 1_099_511_627_776.0); + } + } /* to_primitive */ + + mod from_primitive { + use super::*; + + #[test] + fn from_u128_test() { + assert!(Prefix::from_u128(0).is_none()); + + assert_eq!(Prefix::from_u128(prefix::u128::DEKA).unwrap(), Prefix::Deka); + assert_eq!( + Prefix::from_u128(prefix::u128::HECTO).unwrap(), + Prefix::Hecto + ); + assert_eq!(Prefix::from_u128(prefix::u128::KILO).unwrap(), Prefix::Kilo); + assert_eq!(Prefix::from_u128(prefix::u128::MEGA).unwrap(), Prefix::Mega); + assert_eq!(Prefix::from_u128(prefix::u128::GIGA).unwrap(), Prefix::Giga); + assert_eq!(Prefix::from_u128(prefix::u128::TERA).unwrap(), Prefix::Tera); + assert_eq!(Prefix::from_u128(prefix::u128::PETA).unwrap(), Prefix::Peta); + assert_eq!(Prefix::from_u128(prefix::u128::EXA).unwrap(), Prefix::Exa); + assert_eq!( + Prefix::from_u128(prefix::u128::ZETTA).unwrap(), + Prefix::Zetta + ); + assert_eq!( + Prefix::from_u128(prefix::u128::YOTTA).unwrap(), + Prefix::Yotta + ); + } + + #[test] + #[allow(clippy::cast_possible_wrap)] + fn from_i128_test() { + assert!(Prefix::from_i128(-1).is_none()); + + assert_eq!( + Prefix::from_i128(prefix::u128::YOTTA as i128).unwrap(), + Prefix::Yotta + ); + } + + #[test] + fn from_f64_test() { + assert!(Prefix::from_f64(0.0).is_none()); + + assert_eq!(Prefix::from_f64(prefix::DECI).unwrap(), Prefix::Deci); + assert_eq!(Prefix::from_f64(prefix::CENTI).unwrap(), Prefix::Centi); + assert_eq!(Prefix::from_f64(prefix::MILLI).unwrap(), Prefix::Milli); + assert_eq!(Prefix::from_f64(prefix::MICRO).unwrap(), Prefix::Micro); + assert_eq!(Prefix::from_f64(prefix::NANO).unwrap(), Prefix::Nano); + assert_eq!(Prefix::from_f64(prefix::PICO).unwrap(), Prefix::Pico); + assert_eq!(Prefix::from_f64(prefix::FEMTO).unwrap(), Prefix::Femto); + assert_eq!(Prefix::from_f64(prefix::ATTO).unwrap(), Prefix::Atto); + assert_eq!(Prefix::from_f64(prefix::ZEPTO).unwrap(), Prefix::Zepto); + assert_eq!(Prefix::from_f64(prefix::YOCTO).unwrap(), Prefix::Yocto); + + assert_eq!(Prefix::from_f64(prefix::DEKA).unwrap(), Prefix::Deka); + assert_eq!(Prefix::from_f64(prefix::HECTO).unwrap(), Prefix::Hecto); + assert_eq!(Prefix::from_f64(prefix::KILO).unwrap(), Prefix::Kilo); + assert_eq!(Prefix::from_f64(prefix::MEGA).unwrap(), Prefix::Mega); + assert_eq!(Prefix::from_f64(prefix::GIGA).unwrap(), Prefix::Giga); + assert_eq!(Prefix::from_f64(prefix::TERA).unwrap(), Prefix::Tera); + assert_eq!(Prefix::from_f64(prefix::PETA).unwrap(), Prefix::Peta); + assert_eq!(Prefix::from_f64(prefix::EXA).unwrap(), Prefix::Exa); + assert_eq!(Prefix::from_f64(prefix::ZETTA).unwrap(), Prefix::Zetta); + assert_eq!(Prefix::from_f64(prefix::YOTTA).unwrap(), Prefix::Yotta); + } + } /* from_primitive */ +} diff --git a/crates/api/src/parser/term.rs b/crates/api/src/parser/term.rs index a6f6dcfc..7c469a58 100644 --- a/crates/api/src/parser/term.rs +++ b/crates/api/src/parser/term.rs @@ -4,7 +4,7 @@ mod display; mod field_eq; mod invert; mod is_compatible_with; -mod num_traits; +pub(crate) mod num_traits; mod partial_eq; mod reducible; mod ucum_unit; diff --git a/crates/api/src/parser/term/annotation_composable.rs b/crates/api/src/parser/term/annotation_composable.rs index 316a4d6c..dc876e20 100644 --- a/crates/api/src/parser/term/annotation_composable.rs +++ b/crates/api/src/parser/term/annotation_composable.rs @@ -40,10 +40,7 @@ impl<'a> AnnotationComposable for &'a [Term] { #[cfg(test)] mod tests { - use crate::parser::{ - annotation_composition::{AnnotationComposable, AnnotationComposition}, - Atom, Term, - }; + use crate::parser::annotation_composition::{AnnotationComposable, AnnotationComposition}; mod without_annotations { use super::*; diff --git a/crates/api/src/parser/term/composable.rs b/crates/api/src/parser/term/composable.rs index 47cf8927..3a796ff9 100644 --- a/crates/api/src/parser/term/composable.rs +++ b/crates/api/src/parser/term/composable.rs @@ -34,7 +34,7 @@ impl<'a> Composable for Cow<'a, [Term]> { #[cfg(test)] mod tests { - use crate::parser::{Atom, Composable, Composition, Dimension, Prefix, Term}; + use crate::parser::{Composable, Composition, Dimension, Prefix}; macro_rules! validate_composition { ($test_name:ident, $term:expr, $expected_value:expr) => { diff --git a/crates/api/src/parser/term/display.rs b/crates/api/src/parser/term/display.rs index 0be1b787..ad83f137 100644 --- a/crates/api/src/parser/term/display.rs +++ b/crates/api/src/parser/term/display.rs @@ -52,7 +52,7 @@ fn extract_term_string_atom(term_string: &mut String, term: &Term) { #[cfg(test)] mod tests { - use crate::parser::{term::UNITY, Atom, Prefix, Term}; + use crate::parser::{term::UNITY, Prefix, Term}; macro_rules! validate_display { ($test_name:ident, $term:expr, $output:expr) => { diff --git a/crates/api/src/parser/term/invert.rs b/crates/api/src/parser/term/invert.rs index f04d93ee..18dec191 100644 --- a/crates/api/src/parser/term/invert.rs +++ b/crates/api/src/parser/term/invert.rs @@ -67,10 +67,7 @@ impl<'a> ToInverse for Cow<'a, [Term]> { #[cfg(test)] mod tests { mod term { - use crate::{ - invert::{Invert, ToInverse}, - Atom, Term, - }; + use crate::invert::{Invert, ToInverse}; #[test] fn validate_invert_numerator_no_exponent() { @@ -116,10 +113,7 @@ mod tests { } mod terms { - use crate::{ - invert::{Invert, ToInverse}, - Atom, Prefix, Term, - }; + use crate::invert::{Invert, ToInverse}; #[test] fn validate_invert_numerator_no_exponent() { diff --git a/crates/api/src/parser/term/is_compatible_with.rs b/crates/api/src/parser/term/is_compatible_with.rs index 3710805a..b72c4b8f 100644 --- a/crates/api/src/parser/term/is_compatible_with.rs +++ b/crates/api/src/parser/term/is_compatible_with.rs @@ -52,10 +52,7 @@ impl<'a> IsCompatibleWith for Cow<'a, [Term]> { #[cfg(test)] mod tests { - use crate::{ - is_compatible_with::IsCompatibleWith, - parser::{Atom, Prefix, Term}, - }; + use crate::{is_compatible_with::IsCompatibleWith, parser::Prefix}; mod without_annotations { use super::*; diff --git a/crates/api/src/parser/term/num_traits.rs b/crates/api/src/parser/term/num_traits.rs index 5b217aca..8a7561fa 100644 --- a/crates/api/src/parser/term/num_traits.rs +++ b/crates/api/src/parser/term/num_traits.rs @@ -1,2 +1,2 @@ -mod inv; +pub(crate) mod inv; mod pow; diff --git a/crates/api/src/parser/term/num_traits/inv.rs b/crates/api/src/parser/term/num_traits/inv.rs index eb8b0820..256a82e8 100644 --- a/crates/api/src/parser/term/num_traits/inv.rs +++ b/crates/api/src/parser/term/num_traits/inv.rs @@ -39,10 +39,22 @@ impl<'a> Inv for &'a mut Term { } } +// This solves not being able to `impl Inv for &mut Vec`. +// +pub(crate) fn inv_terms(terms: &mut Vec) { + for term in terms { + let _ = term.inv(); + } +} + +// This solves not being able to `impl Inv for Vec`. +// +pub(crate) fn inv_terms_into(terms: Vec) -> Vec { + terms.into_iter().map(num_traits::Inv::inv).collect() +} + #[cfg(test)] mod tests { - use crate::{Atom, Term}; - use super::*; macro_rules! test_inv { diff --git a/crates/api/src/parser/term/num_traits/pow.rs b/crates/api/src/parser/term/num_traits/pow.rs index 95e2ec17..c8e0c8d7 100644 --- a/crates/api/src/parser/term/num_traits/pow.rs +++ b/crates/api/src/parser/term/num_traits/pow.rs @@ -43,3 +43,65 @@ impl<'a> Pow for &'a mut Term { self } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn owned_no_exponent_test() { + let subject = term!(Liter); + assert_eq!(Pow::pow(subject, 2), term!(Liter, exponent: 2)); + } + + #[test] + fn owned_negative_exponent_test() { + let subject = term!(Liter, exponent: -1); + assert_eq!(Pow::pow(subject, 2), term!(Liter, exponent: -2)); + } + + #[test] + fn owned_positive_exponent_test() { + let subject = term!(Liter, exponent: 1); + assert_eq!(Pow::pow(subject, 2), term!(Liter, exponent: 2)); + } + + #[test] + fn borrowed_no_exponent_test() { + let subject = term!(Liter); + assert_eq!(Pow::pow(&subject, 2), term!(Liter, exponent: 2)); + } + + #[test] + fn borrowed_negative_exponent_test() { + let subject = term!(Liter, exponent: -1); + assert_eq!(Pow::pow(&subject, 2), term!(Liter, exponent: -2)); + } + + #[test] + fn borrowed_positive_exponent_test() { + let subject = term!(Liter, exponent: 1); + assert_eq!(Pow::pow(&subject, 2), term!(Liter, exponent: 2)); + } + + #[test] + fn mut_borrowed_no_exponent_test() { + let mut subject = term!(Liter); + let _ = Pow::pow(&mut subject, 2); + assert_eq!(subject, term!(Liter, exponent: 2)); + } + + #[test] + fn mut_borrowed_negative_exponent_test() { + let mut subject = term!(Liter, exponent: -1); + let _ = Pow::pow(&mut subject, 2); + assert_eq!(subject, term!(Liter, exponent: -2)); + } + + #[test] + fn mut_borrowed_positive_exponent_test() { + let mut subject = term!(Liter, exponent: 1); + let _ = Pow::pow(&mut subject, 2); + assert_eq!(subject, term!(Liter, exponent: 2)); + } +} diff --git a/crates/api/src/parser/term/reducible.rs b/crates/api/src/parser/term/reducible.rs index 9e53f04d..7e969dab 100644 --- a/crates/api/src/parser/term/reducible.rs +++ b/crates/api/src/parser/term/reducible.rs @@ -56,10 +56,7 @@ fn combine_term_values( #[cfg(test)] mod tests { - use crate::{ - parser::{Atom, Prefix, Term}, - reducible::Reducible, - }; + use crate::{parser::Prefix, reducible::Reducible}; use approx::assert_relative_eq; macro_rules! validate_reduce_value { diff --git a/crates/api/src/parser/terms/mapper.rs b/crates/api/src/parser/terms/mapper.rs index 146797c3..1d434d7b 100644 --- a/crates/api/src/parser/terms/mapper.rs +++ b/crates/api/src/parser/terms/mapper.rs @@ -52,7 +52,7 @@ mod tests { use super::*; use crate::parser::{ terms::term_parser::{Rule, TermParser}, - Atom, Prefix, Term, + Prefix, }; use pest::Parser; diff --git a/crates/api/src/parser/terms/mapper/ast_term.rs b/crates/api/src/parser/terms/mapper/ast_term.rs index 2356a189..0c68800b 100644 --- a/crates/api/src/parser/terms/mapper/ast_term.rs +++ b/crates/api/src/parser/terms/mapper/ast_term.rs @@ -39,19 +39,18 @@ impl AstTerm { match pairs.next() { Some(third) => match third.as_rule() { Rule::term => { - let new_terms: Vec = Self::visit(third)?.finish(); - let mut u = crate::Unit::new(new_terms); + let mut new_terms: Vec = Self::visit(third)?.finish(); match op { SecondToken::Dot => (), SecondToken::Slash => { - let _ = Inv::inv(&mut u); + crate::parser::term::num_traits::inv::inv_terms(&mut new_terms); } } Ok(Self { component, - terms: u.into_terms().to_vec(), + terms: new_terms, }) } _ => unreachable!(), diff --git a/crates/api/src/unit/num_traits/pow.rs b/crates/api/src/unit/num_traits/pow.rs index 976b3f8a..2efe55cf 100644 --- a/crates/api/src/unit/num_traits/pow.rs +++ b/crates/api/src/unit/num_traits/pow.rs @@ -39,3 +39,29 @@ impl<'a> Pow for &'a mut Unit { self } } + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use super::*; + + #[test] + fn owned_test() { + let subject = Unit::from_str("L").unwrap(); + assert_eq!(Pow::pow(subject, 2), Unit::from_str("L2").unwrap()); + } + + #[test] + fn borrowed_test() { + let subject = Unit::from_str("L").unwrap(); + assert_eq!(Pow::pow(&subject, 2), Unit::from_str("L2").unwrap()); + } + + #[test] + fn mut_borrowed_test() { + let mut subject = Unit::from_str("L").unwrap(); + let _ = Pow::pow(&mut subject, 2); + assert_eq!(subject, Unit::from_str("L2").unwrap()); + } +} diff --git a/crates/api/src/unit/to_reduced.rs b/crates/api/src/unit/to_reduced.rs index f9bb4a05..0d6a85c4 100644 --- a/crates/api/src/unit/to_reduced.rs +++ b/crates/api/src/unit/to_reduced.rs @@ -64,10 +64,10 @@ impl ToReduced for Unit { let mut new_terms: Vec = Vec::with_capacity(new_numerators.len() + new_denominators.len()); new_terms.extend_from_slice(&new_numerators); - let denom_unit = Self { - terms: Cow::Owned(new_denominators), - }; - new_terms.extend_from_slice(&denom_unit.inv().terms); + + let new_denominators = + crate::parser::term::num_traits::inv::inv_terms_into(new_denominators); + new_terms.extend_from_slice(&new_denominators); Self::new(super::term_reducing::reduce_terms(&new_terms)) } From dc93be0d97f670b697737fbc3d052abeec693923 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Wed, 14 Feb 2024 13:35:51 -0800 Subject: [PATCH 42/80] Add missing Inv impls on &T --- crates/api/src/measurement/num_traits/inv.rs | 16 +++++++++++++ crates/api/src/unit/num_traits/inv.rs | 25 ++++++++++++++++---- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/crates/api/src/measurement/num_traits/inv.rs b/crates/api/src/measurement/num_traits/inv.rs index 7dbae8c1..18f1a791 100644 --- a/crates/api/src/measurement/num_traits/inv.rs +++ b/crates/api/src/measurement/num_traits/inv.rs @@ -13,6 +13,17 @@ impl Inv for Measurement { } } +impl<'a> Inv for &'a Measurement { + type Output = Measurement; + + fn inv(self) -> Self::Output { + Measurement { + value: self.value.inv(), + unit: self.unit.clone().inv(), + } + } +} + impl<'a> Inv for &'a mut Measurement { type Output = Self; @@ -37,6 +48,11 @@ mod tests { let _ = Inv::inv(&mut mut_borrowed); assert_eq!(mut_borrowed, $expected); + // Test &Measurement impl + let owned = $subject; + let inverted = Inv::inv(&owned); + assert_eq!(inverted, $expected); + // Test Measurement impl let owned = $subject; let inverted = Inv::inv(owned); diff --git a/crates/api/src/unit/num_traits/inv.rs b/crates/api/src/unit/num_traits/inv.rs index 7b359b39..863f01ae 100644 --- a/crates/api/src/unit/num_traits/inv.rs +++ b/crates/api/src/unit/num_traits/inv.rs @@ -1,13 +1,25 @@ +use std::borrow::Cow; + use num_traits::Inv; -use crate::Unit; +use crate::{parser::term, Unit}; impl Inv for Unit { type Output = Self; fn inv(self) -> Self::Output { Self { - terms: self.terms.iter().map(Inv::inv).collect(), + terms: Cow::Owned(term::num_traits::inv::inv_terms_into(self.terms.to_vec())), + } + } +} + +impl<'a> Inv for &'a Unit { + type Output = Unit; + + fn inv(self) -> Self::Output { + Unit { + terms: Cow::Owned(term::num_traits::inv::inv_terms_into(self.terms.to_vec())), } } } @@ -16,9 +28,7 @@ impl<'a> Inv for &'a mut Unit { type Output = Self; fn inv(self) -> Self::Output { - for term in self.terms.to_mut().iter_mut() { - let _ = term.inv(); - } + term::num_traits::inv::inv_terms(self.terms.to_mut()); self } @@ -39,6 +49,11 @@ mod tests { let _ = Inv::inv(&mut mut_borrowed); assert_eq!(mut_borrowed, $expected); + // Test &Unit impl + let owned = $subject; + let inverted = Inv::inv(&owned); + assert_eq!(inverted, $expected); + // Test Unit impl let owned = $subject; let inverted = Inv::inv(owned); From f318fd406e3ed14f671bd756f0f1c7c796d934cd Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Thu, 21 Mar 2024 16:45:46 -0700 Subject: [PATCH 43/80] PLCC-299 Add term::{Factor, Exponent} type aliases --- crates/api/CHANGELOG.md | 2 + crates/api/src/measurement/num_traits/pow.rs | 14 ++-- .../api/src/parser/annotation_composition.rs | 4 +- crates/api/src/parser/composition.rs | 64 +++++++++---------- crates/api/src/parser/term.rs | 11 ++-- crates/api/src/parser/term/display.rs | 5 +- crates/api/src/parser/term/num_traits/pow.rs | 14 ++-- crates/api/src/parser/term/reducible.rs | 6 +- crates/api/src/parser/terms/mapper.rs | 2 +- .../src/parser/terms/mapper/annotatable.rs | 10 +-- .../parser/terms/mapper/basic_component.rs | 10 +-- .../api/src/parser/terms/mapper/component.rs | 8 ++- .../api/src/parser/terms/mapper/exponent.rs | 10 +-- crates/api/src/parser/terms/mapper/factor.rs | 8 +-- crates/api/src/unit/num_traits/pow.rs | 14 ++-- crates/api/src/unit/term_reducing.rs | 16 +++-- 16 files changed, 108 insertions(+), 90 deletions(-) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index e36754c8..4cbb432c 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -22,6 +22,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Added `unit` constant: `UNITY` - Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. - Added `measurement!()` macro for wrapping `Measurement::try_new().unwrap()`. +- Added `crate::parser::term::Factor` type alias for `u32`. +- Added `crate::parser::term::Exponent` type alias for `i32`. ### Changed diff --git a/crates/api/src/measurement/num_traits/pow.rs b/crates/api/src/measurement/num_traits/pow.rs index ab86245f..3c2dbd6d 100644 --- a/crates/api/src/measurement/num_traits/pow.rs +++ b/crates/api/src/measurement/num_traits/pow.rs @@ -1,11 +1,11 @@ use num_traits::Pow; -use crate::Measurement; +use crate::{parser::term::Exponent, Measurement}; -impl Pow for Measurement { +impl Pow for Measurement { type Output = Self; - fn pow(self, rhs: i32) -> Self::Output { + fn pow(self, rhs: Exponent) -> Self::Output { Self { value: self.value.pow(rhs), unit: self.unit.pow(rhs), @@ -13,10 +13,10 @@ impl Pow for Measurement { } } -impl<'a> Pow for &'a Measurement { +impl<'a> Pow for &'a Measurement { type Output = Measurement; - fn pow(self, rhs: i32) -> Self::Output { + fn pow(self, rhs: Exponent) -> Self::Output { Measurement { value: self.value.pow(rhs), unit: self.unit.clone().pow(rhs), @@ -24,10 +24,10 @@ impl<'a> Pow for &'a Measurement { } } -impl<'a> Pow for &'a mut Measurement { +impl<'a> Pow for &'a mut Measurement { type Output = Self; - fn pow(self, rhs: i32) -> Self::Output { + fn pow(self, rhs: Exponent) -> Self::Output { self.value = self.value.pow(rhs); let _ = Pow::pow(&mut self.unit, rhs); self diff --git a/crates/api/src/parser/annotation_composition.rs b/crates/api/src/parser/annotation_composition.rs index 0c5f6d4b..adfeb887 100644 --- a/crates/api/src/parser/annotation_composition.rs +++ b/crates/api/src/parser/annotation_composition.rs @@ -1,6 +1,8 @@ use std::collections::HashMap; -pub type AnnotationComposition = HashMap; +use super::term::Exponent; + +pub type AnnotationComposition = HashMap; /// Similar to `Composable`, this is only to allow for checking compatibility on `Unit`s that have /// annotations. For those cases, we want to be able to ensure that, for example, `m{foo}` is not diff --git a/crates/api/src/parser/composition.rs b/crates/api/src/parser/composition.rs index 8289ee39..fb278ed9 100644 --- a/crates/api/src/parser/composition.rs +++ b/crates/api/src/parser/composition.rs @@ -1,8 +1,6 @@ -use super::Dimension; +use super::{term::Exponent, Dimension}; use std::{fmt, ops::Mul}; -type Exponent = i32; - pub const DIMLESS: Composition = Composition::new_dimless(); pub const ELECTRIC_CHARGE: Composition = Composition::new_electric_charge(1); @@ -78,8 +76,8 @@ pub struct Composition { macro_rules! def_mul_exponent { ($meth_name:ident, $composition_method:ident) => { fn $meth_name( - original_value: Option, - exponent: i32, + original_value: Option, + exponent: Exponent, new_composition: &mut Composition, ) { if let Some(self_exponent) = original_value { @@ -107,7 +105,7 @@ macro_rules! insert_exponent { macro_rules! def_add_dimension { ($meth_name:ident, $composition_method:ident) => { fn $meth_name( - original_value: Option, + original_value: Option, rhs_composition: Composition, new_composition: &mut Composition, ) { @@ -122,7 +120,7 @@ macro_rules! def_add_dimension { impl Composition { #[must_use] - pub const fn new(dimension: Dimension, exponent: i32) -> Self { + pub const fn new(dimension: Dimension, exponent: Exponent) -> Self { match dimension { Dimension::ElectricCharge => Self::new_electric_charge(exponent), Dimension::Length => Self::new_length(exponent), @@ -148,7 +146,7 @@ impl Composition { } #[must_use] - pub const fn new_electric_charge(exponent: i32) -> Self { + pub const fn new_electric_charge(exponent: Exponent) -> Self { Self { electric_charge: Some(exponent), length: None, @@ -161,7 +159,7 @@ impl Composition { } #[must_use] - pub const fn new_length(exponent: i32) -> Self { + pub const fn new_length(exponent: Exponent) -> Self { Self { electric_charge: None, length: Some(exponent), @@ -174,7 +172,7 @@ impl Composition { } #[must_use] - pub const fn new_luminous_intensity(exponent: i32) -> Self { + pub const fn new_luminous_intensity(exponent: Exponent) -> Self { Self { electric_charge: None, length: None, @@ -187,7 +185,7 @@ impl Composition { } #[must_use] - pub const fn new_mass(exponent: i32) -> Self { + pub const fn new_mass(exponent: Exponent) -> Self { Self { electric_charge: None, length: None, @@ -200,7 +198,7 @@ impl Composition { } #[must_use] - pub const fn new_plane_angle(exponent: i32) -> Self { + pub const fn new_plane_angle(exponent: Exponent) -> Self { Self { electric_charge: None, length: None, @@ -213,7 +211,7 @@ impl Composition { } #[must_use] - pub const fn new_temperature(exponent: i32) -> Self { + pub const fn new_temperature(exponent: Exponent) -> Self { Self { electric_charge: None, length: None, @@ -226,7 +224,7 @@ impl Composition { } #[must_use] - pub const fn new_time(exponent: i32) -> Self { + pub const fn new_time(exponent: Exponent) -> Self { Self { electric_charge: None, length: None, @@ -240,13 +238,13 @@ impl Composition { #[must_use] pub const fn new_any( - electric_charge: Option, - length: Option, - luminous_intensity: Option, - mass: Option, - plane_angle: Option, - temperature: Option, - time: Option, + electric_charge: Option, + length: Option, + luminous_intensity: Option, + mass: Option, + plane_angle: Option, + temperature: Option, + time: Option, ) -> Self { Self { electric_charge, @@ -259,7 +257,7 @@ impl Composition { } } - pub fn insert(&mut self, dimension: Dimension, exponent: i32) { + pub fn insert(&mut self, dimension: Dimension, exponent: Exponent) { if exponent == 0 { return; } @@ -275,31 +273,31 @@ impl Composition { } } - fn insert_electric_charge(&mut self, exponent: i32) { + fn insert_electric_charge(&mut self, exponent: Exponent) { self.electric_charge = insert_exponent!(self, electric_charge, exponent); } - fn insert_length(&mut self, exponent: i32) { + fn insert_length(&mut self, exponent: Exponent) { self.length = insert_exponent!(self, length, exponent); } - fn insert_luminous_intensity(&mut self, exponent: i32) { + fn insert_luminous_intensity(&mut self, exponent: Exponent) { self.luminous_intensity = insert_exponent!(self, luminous_intensity, exponent); } - fn insert_mass(&mut self, exponent: i32) { + fn insert_mass(&mut self, exponent: Exponent) { self.mass = insert_exponent!(self, mass, exponent); } - fn insert_plane_angle(&mut self, exponent: i32) { + fn insert_plane_angle(&mut self, exponent: Exponent) { self.plane_angle = insert_exponent!(self, plane_angle, exponent); } - fn insert_temperature(&mut self, exponent: i32) { + fn insert_temperature(&mut self, exponent: Exponent) { self.temperature = insert_exponent!(self, temperature, exponent); } - fn insert_time(&mut self, exponent: i32) { + fn insert_time(&mut self, exponent: Exponent) { self.time = insert_exponent!(self, time, exponent); } @@ -337,7 +335,7 @@ impl fmt::Display for Composition { } fn push_display_expression( - composition_value: Option, + composition_value: Option, expressions: &mut Vec, dimension_str: &str, ) { @@ -399,10 +397,10 @@ def_add_dimension!(add_time, time); /// assert_eq!(&t.composition().to_string(), "L6"); /// ``` /// -impl Mul for Composition { +impl Mul for Composition { type Output = Self; - fn mul(self, rhs: i32) -> Self::Output { + fn mul(self, rhs: Exponent) -> Self::Output { let mut new_composition = Self::default(); mul_electric_charge(self.electric_charge, rhs, &mut new_composition); @@ -428,7 +426,7 @@ def_mul_exponent!(mul_time, time); /// Used internally for disallowing setting any of the dimensions' exponents to 0 (it should /// be `None` in that case). /// -const fn set_exponent(exponent: i32) -> Option { +const fn set_exponent(exponent: Exponent) -> Option { if exponent == 0 { None } else { diff --git a/crates/api/src/parser/term.rs b/crates/api/src/parser/term.rs index 7c469a58..19c66608 100644 --- a/crates/api/src/parser/term.rs +++ b/crates/api/src/parser/term.rs @@ -23,6 +23,9 @@ pub const UNITY: Term = { pub const UNITY_ARRAY: [Term; 1] = [UNITY]; pub const UNITY_ARRAY_REF: &[Term; 1] = &UNITY_ARRAY; +pub type Factor = u32; +pub type Exponent = i32; + /// A Term makes up an Atom (at its core) along with any Atom modifiers /// (anything that can change its scalar). It is, however, possible to have an /// Atom-less Term, which would simple be a Factor (with or without an @@ -30,10 +33,10 @@ pub const UNITY_ARRAY_REF: &[Term; 1] = &UNITY_ARRAY; /// #[derive(Clone, Debug, Eq, Default)] pub struct Term { - pub factor: Option, + pub factor: Option, pub prefix: Option, pub atom: Option, - pub exponent: Option, + pub exponent: Option, pub annotation: Option, } @@ -115,7 +118,7 @@ impl Term { } } - pub fn factor_and_is_not_one(&self, f: F) { + pub fn factor_and_is_not_one(&self, f: F) { if let Some(factor) = self.factor { if factor != 1 { f(factor); @@ -124,7 +127,7 @@ impl Term { } #[must_use] - pub fn factor_as_u32(&self) -> u32 { + pub fn factor_as_u32(&self) -> Factor { self.factor.unwrap_or(1) } } diff --git a/crates/api/src/parser/term/display.rs b/crates/api/src/parser/term/display.rs index ad83f137..568ddff2 100644 --- a/crates/api/src/parser/term/display.rs +++ b/crates/api/src/parser/term/display.rs @@ -1,6 +1,7 @@ -use super::Term; use std::fmt; +use super::{Factor, Term}; + impl fmt::Display for Term { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", extract_term_string(self)) @@ -23,7 +24,7 @@ fn extract_term_string(term: &Term) -> String { term_string } -fn extract_term_string_factor(term_string: &mut String, term_factor: Option) { +fn extract_term_string_factor(term_string: &mut String, term_factor: Option) { if let Some(factor) = term_factor { if factor != 1 { term_string.push_str(&factor.to_string()); diff --git a/crates/api/src/parser/term/num_traits/pow.rs b/crates/api/src/parser/term/num_traits/pow.rs index c8e0c8d7..5338a0f1 100644 --- a/crates/api/src/parser/term/num_traits/pow.rs +++ b/crates/api/src/parser/term/num_traits/pow.rs @@ -1,11 +1,11 @@ use num_traits::Pow; -use crate::Term; +use crate::{parser::term::Exponent, Term}; -impl Pow for Term { +impl Pow for Term { type Output = Self; - fn pow(self, rhs: i32) -> Self::Output { + fn pow(self, rhs: Exponent) -> Self::Output { let exponent = self.exponent.map_or(rhs, |exp| exp * rhs); Self { @@ -18,10 +18,10 @@ impl Pow for Term { } } -impl<'a> Pow for &'a Term { +impl<'a> Pow for &'a Term { type Output = Term; - fn pow(self, rhs: i32) -> Self::Output { + fn pow(self, rhs: Exponent) -> Self::Output { let exponent = self.exponent.map_or(rhs, |exp| exp * rhs); Term { @@ -34,10 +34,10 @@ impl<'a> Pow for &'a Term { } } -impl<'a> Pow for &'a mut Term { +impl<'a> Pow for &'a mut Term { type Output = Self; - fn pow(self, rhs: i32) -> Self::Output { + fn pow(self, rhs: Exponent) -> Self::Output { self.exponent = Some(self.exponent.map_or(rhs, |exp| exp * rhs)); self diff --git a/crates/api/src/parser/term/reducible.rs b/crates/api/src/parser/term/reducible.rs index 7e969dab..f9f77e58 100644 --- a/crates/api/src/parser/term/reducible.rs +++ b/crates/api/src/parser/term/reducible.rs @@ -4,7 +4,7 @@ use num_traits::One; use crate::{parser::ucum_symbol::UcumSymbol, reducible::Reducible}; -use super::Term; +use super::{Exponent, Factor, Term}; impl Reducible for Term { fn reduce_value(&self, value: f64) -> f64 { @@ -40,8 +40,8 @@ impl<'a> Reducible for Cow<'a, [Term]> { fn combine_term_values( calculated_atom: f64, calculated_prefix: f64, - factor: Option, - exponent: Option, + factor: Option, + exponent: Option, ) -> f64 { let a_p_product = calculated_atom * calculated_prefix; diff --git a/crates/api/src/parser/terms/mapper.rs b/crates/api/src/parser/terms/mapper.rs index 1d434d7b..108b0619 100644 --- a/crates/api/src/parser/terms/mapper.rs +++ b/crates/api/src/parser/terms/mapper.rs @@ -18,7 +18,7 @@ mod simple_unit; use self::{ annotatable::Annotatable, annotation::Annotation, ast_term::AstTerm, basic_component::BasicComponent, component::Component, digits::Digits, exponent::Exponent, - factor::Factor, finishable::Finishable, main_term::MainTerm, simple_unit::SimpleUnit, + finishable::Finishable, main_term::MainTerm, simple_unit::SimpleUnit, }; use crate::parser::{terms::term_parser::Rule, Atom, Error, Prefix, Term, Visit}; use pest::iterators::{Pair, Pairs}; diff --git a/crates/api/src/parser/terms/mapper/annotatable.rs b/crates/api/src/parser/terms/mapper/annotatable.rs index 2aba521b..bd26f724 100644 --- a/crates/api/src/parser/terms/mapper/annotatable.rs +++ b/crates/api/src/parser/terms/mapper/annotatable.rs @@ -1,12 +1,14 @@ -use super::{Atom, Error, Exponent, Prefix, SimpleUnit, Visit}; -use crate::parser::terms::term_parser::Rule as TermRule; use pest::iterators::Pair; +use crate::parser::{term::Exponent as IExponent, terms::term_parser::Rule as TermRule}; + +use super::{Atom, Error, Exponent, Prefix, SimpleUnit, Visit}; + pub(super) enum Annotatable { PrefixedWithExponent { prefix: Prefix, atom: Atom, - exponent: i32, + exponent: IExponent, }, Prefixed { prefix: Prefix, @@ -14,7 +16,7 @@ pub(super) enum Annotatable { }, BasicWithExponent { atom: Atom, - exponent: i32, + exponent: IExponent, }, Basic { atom: Atom, diff --git a/crates/api/src/parser/terms/mapper/basic_component.rs b/crates/api/src/parser/terms/mapper/basic_component.rs index 71b37813..1dfcde79 100644 --- a/crates/api/src/parser/terms/mapper/basic_component.rs +++ b/crates/api/src/parser/terms/mapper/basic_component.rs @@ -1,9 +1,11 @@ -use super::{Annotatable, Annotation, AstTerm, Error, Factor, Finishable, Term, Visit}; -use crate::parser::terms::term_parser::Rule; use pest::iterators::Pair; +use crate::parser::{term::Factor, terms::term_parser::Rule}; + +use super::{Annotatable, Annotation, AstTerm, Error, Finishable, Term, Visit}; + pub(super) struct BasicComponent { - pub(super) factor: Option, + pub(super) factor: Option, pub(super) annotatable: Option, pub(super) annotation: Option, pub(super) terms: Vec, @@ -68,7 +70,7 @@ impl Visit for BasicComponent { enum FirstToken { Annotatable(Annotatable), - Factor(u32), + Factor(Factor), } impl Finishable for BasicComponent { diff --git a/crates/api/src/parser/terms/mapper/component.rs b/crates/api/src/parser/terms/mapper/component.rs index 00b1aaf2..d54de3d7 100644 --- a/crates/api/src/parser/terms/mapper/component.rs +++ b/crates/api/src/parser/terms/mapper/component.rs @@ -1,9 +1,11 @@ -use super::{BasicComponent, Error, Factor, Finishable, Term, Visit}; -use crate::parser::terms::term_parser::Rule; use pest::iterators::Pair; +use crate::parser::{term::Factor, terms::term_parser::Rule}; + +use super::{BasicComponent, Error, Finishable, Term, Visit}; + pub(super) struct Component { - pub(super) factor: Option, + pub(super) factor: Option, pub(super) terms: Vec, } diff --git a/crates/api/src/parser/terms/mapper/exponent.rs b/crates/api/src/parser/terms/mapper/exponent.rs index 96c0417e..0bf47f78 100644 --- a/crates/api/src/parser/terms/mapper/exponent.rs +++ b/crates/api/src/parser/terms/mapper/exponent.rs @@ -1,8 +1,10 @@ -use super::{Digits, Error, Visit}; -use crate::parser::terms::term_parser::Rule as TermRule; use pest::iterators::Pair; -pub(super) struct Exponent(pub(super) i32); +use crate::parser::{term, terms::term_parser::Rule as TermRule}; + +use super::{Digits, Error, Visit}; + +pub(super) struct Exponent(pub(super) term::Exponent); impl Visit for Exponent { fn visit(pair: Pair<'_, TermRule>) -> Result { @@ -48,5 +50,5 @@ fn parse_second_token(next: Option>) -> Result enum FirstToken { PositiveSign, NegativeSign, - Exponent(i32), + Exponent(term::Exponent), } diff --git a/crates/api/src/parser/terms/mapper/factor.rs b/crates/api/src/parser/terms/mapper/factor.rs index c1b3a88f..d32fe75e 100644 --- a/crates/api/src/parser/terms/mapper/factor.rs +++ b/crates/api/src/parser/terms/mapper/factor.rs @@ -1,10 +1,10 @@ -use super::{Error, Visit}; -use crate::parser::terms::term_parser::Rule as TermRule; use pest::iterators::Pair; -pub(super) type Factor = u32; +use crate::parser::{term, terms::term_parser::Rule as TermRule}; + +use super::{Error, Visit}; -impl Visit for Factor { +impl Visit for term::Factor { fn visit(pair: Pair<'_, TermRule>) -> Result { pair.as_span().as_str().parse::().map_err(Error::from) } diff --git a/crates/api/src/unit/num_traits/pow.rs b/crates/api/src/unit/num_traits/pow.rs index 2efe55cf..7d6910a0 100644 --- a/crates/api/src/unit/num_traits/pow.rs +++ b/crates/api/src/unit/num_traits/pow.rs @@ -1,11 +1,11 @@ use num_traits::Pow; -use crate::Unit; +use crate::{parser::term::Exponent, Unit}; -impl Pow for Unit { +impl Pow for Unit { type Output = Self; - fn pow(self, rhs: i32) -> Self::Output { + fn pow(self, rhs: Exponent) -> Self::Output { Self::new( self.terms .iter() @@ -16,10 +16,10 @@ impl Pow for Unit { } } -impl<'a> Pow for &'a Unit { +impl<'a> Pow for &'a Unit { type Output = Unit; - fn pow(self, rhs: i32) -> Self::Output { + fn pow(self, rhs: Exponent) -> Self::Output { Unit::new( self.terms .iter() @@ -29,10 +29,10 @@ impl<'a> Pow for &'a Unit { } } -impl<'a> Pow for &'a mut Unit { +impl<'a> Pow for &'a mut Unit { type Output = Self; - fn pow(self, rhs: i32) -> Self::Output { + fn pow(self, rhs: Exponent) -> Self::Output { self.terms.to_mut().iter_mut().for_each(|term| { let _ = Pow::pow(term, rhs); }); diff --git a/crates/api/src/unit/term_reducing.rs b/crates/api/src/unit/term_reducing.rs index 7317a2d0..2e6f9031 100644 --- a/crates/api/src/unit/term_reducing.rs +++ b/crates/api/src/unit/term_reducing.rs @@ -1,13 +1,17 @@ +use std::collections::BTreeMap; + use num_traits::Zero; -use crate::parser::{term, Atom, Prefix, Term}; -use std::collections::BTreeMap; +use crate::parser::{ + term::{self, Exponent, Factor}, + Atom, Prefix, Term, +}; /// Internal struct used for reducing `Term`s. /// #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] struct ComposableTerm { - factor: Option, + factor: Option, prefix: Option, atom: Option, annotation: Option, @@ -30,7 +34,7 @@ impl<'a> From<&'a Term> for ComposableTerm { } } -type Parts = (ComposableTerm, i32); +type Parts = (ComposableTerm, Exponent); impl From for Term { fn from(parts: Parts) -> Self { @@ -64,7 +68,7 @@ pub(super) fn reduce_terms(terms: &[Term]) -> Vec { /// uniqueness (`atom`, `prefix`, `factor`), and sums those exponents. This is the destructuring /// part of `reduce_terms()`. /// -fn reduce_to_map(terms: &[Term]) -> BTreeMap { +fn reduce_to_map(terms: &[Term]) -> BTreeMap { terms .iter() .map(|term| { @@ -74,7 +78,7 @@ fn reduce_to_map(terms: &[Term]) -> BTreeMap { ) }) .fold( - BTreeMap::::new(), + BTreeMap::::new(), |mut map, (key, exponent)| { let _ = map .entry(key) From d2307783adb12fd59cd6ad4dc2f2b1db82793e45 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 22 Mar 2024 17:25:00 -0700 Subject: [PATCH 44/80] PLCC-299 Constantize many Definitions; use unreachable --- crates/api/CHANGELOG.md | 2 + crates/api/src/parser/atom.rs | 790 ++++---- crates/api/src/parser/atom_test.rs | 3 +- crates/api/src/parser/definition.rs | 67 +- crates/api/src/parser/definition/consts.rs | 1663 +++++++++++++++++ .../api/src/parser/terms/mapper/ast_term.rs | 1 - crates/api/src/unit/to_reduced.rs | 4 - 7 files changed, 2026 insertions(+), 504 deletions(-) create mode 100644 crates/api/src/parser/definition/consts.rs diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 4cbb432c..f949dd14 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -24,6 +24,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Added `measurement!()` macro for wrapping `Measurement::try_new().unwrap()`. - Added `crate::parser::term::Factor` type alias for `u32`. - Added `crate::parser::term::Exponent` type alias for `i32`. +- (Internal) Added constants for many but not all internal `Definition`s. ### Changed @@ -31,6 +32,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - (Internal) Rust Codegen is now using `quote` instead of `handlebars` (the pest parser grammar is still generated using `handlebars`). - (Internal) `Definition` is now an enum and is generic over value type `V`. +- (Internal) `Definition` resolution uses `uncreachable!()` for all `Definition` unit strings. ### Deprecated diff --git a/crates/api/src/parser/atom.rs b/crates/api/src/parser/atom.rs index 65e4c9e9..5542f0e3 100644 --- a/crates/api/src/parser/atom.rs +++ b/crates/api/src/parser/atom.rs @@ -16,6 +16,9 @@ use crate::{ reducible::Reducible, UcumUnit, Unit, }; + +use super::definition::consts::*; + #[derive(Clone, Copy, Debug, Eq, PartialOrd, Ord)] pub enum Atom { Meter, @@ -331,241 +334,213 @@ pub enum Atom { } impl Atom { pub(crate) fn definition(self) -> Definition { - let result = match self { - Self::Meter => Ok(Definition::Base), - Self::Second => Ok(Definition::Base), - Self::Gram => Ok(Definition::Base), - Self::Radian => Ok(Definition::Base), - Self::Kelvin => Ok(Definition::Base), - Self::Coulomb => Ok(Definition::Base), - Self::Candela => Ok(Definition::Base), - Self::TheNumberTenForArbitraryPowersStar => Ok(Definition::NonDimensional(10f64)), - Self::TheNumberTenForArbitraryPowersCaret => Ok(Definition::NonDimensional(10f64)), - Self::TheNumberPi => Ok(Definition::NonDimensional(::std::f64::consts::PI)), - Self::Percent => Ok(Definition::NonDimensional(0.01)), - Self::PartsPerThousand => Definition::try_new_dimensional(1f64, "10*-3"), - Self::PartsPerMillion => Definition::try_new_dimensional(1f64, "10*-6"), - Self::PartsPerBillion => Definition::try_new_dimensional(1f64, "10*-9"), - Self::PartsPerTrillion => Definition::try_new_dimensional(1f64, "10*-12"), - Self::Mole => Definition::try_new_dimensional(6.0221367f64, "10*23"), - Self::Steradian => Definition::try_new_dimensional(1f64, "rad2"), - Self::Hertz => Definition::try_new_dimensional(1f64, "s-1"), - Self::Newton => Definition::try_new_dimensional(1f64, "kg.m/s2"), - Self::Pascal => Definition::try_new_dimensional(1f64, "N/m2"), - Self::Joule => Definition::try_new_dimensional(1f64, "N.m"), - Self::Watt => Definition::try_new_dimensional(1f64, "J/s"), - Self::Ampere => Definition::try_new_dimensional(1f64, "C/s"), - Self::Volt => Definition::try_new_dimensional(1f64, "J/C"), - Self::Farad => Definition::try_new_dimensional(1f64, "C/V"), - Self::Ohm => Definition::try_new_dimensional(1f64, "V/A"), - Self::Siemens => Definition::try_new_dimensional(1f64, "Ohm-1"), - Self::Weber => Definition::try_new_dimensional(1f64, "V.s"), - Self::DegreeCelsius => Definition::try_new_dimensional_special( - 1f64, - "K", - FunctionSet { - convert_from: |value: f64| value - 273.15, - convert_to: |value: f64| value + 273.15, - }, - ), - Self::Tesla => Definition::try_new_dimensional(1f64, "Wb/m2"), - Self::Henry => Definition::try_new_dimensional(1f64, "Wb/A"), - Self::Lumen => Definition::try_new_dimensional(1f64, "cd.sr"), - Self::Lux => Definition::try_new_dimensional(1f64, "lm/m2"), - Self::Becquerel => Definition::try_new_dimensional(1f64, "s-1"), - Self::Gray => Definition::try_new_dimensional(1f64, "J/kg"), - Self::Sievert => Definition::try_new_dimensional(1f64, "J/kg"), - Self::Gon => Definition::try_new_dimensional(0.9f64, "deg"), - Self::Degree => Definition::try_new_dimensional(2f64, "[pi].rad/360"), - Self::MinuteAngle => Definition::try_new_dimensional(1f64, "deg/60"), - Self::SecondAngle => Definition::try_new_dimensional(1f64, "'/60"), - Self::Liter => Definition::try_new_dimensional(1f64, "dm3"), - Self::LiterSecondary => Definition::try_new_dimensional(1f64, "l"), - Self::Are => Definition::try_new_dimensional(100f64, "m2"), - Self::Minute => Definition::try_new_dimensional(60f64, "s"), - Self::Hour => Definition::try_new_dimensional(60f64, "min"), - Self::Day => Definition::try_new_dimensional(24f64, "h"), - Self::TropicalYear => Definition::try_new_dimensional(365.24219f64, "d"), - Self::MeanJulianYear => Definition::try_new_dimensional(365.25f64, "d"), - Self::MeanGregorianYear => Definition::try_new_dimensional(365.2425f64, "d"), - Self::Year => Definition::try_new_dimensional(1f64, "a_j"), - Self::Week => Definition::try_new_dimensional(7f64, "d"), - Self::SynodalMonth => Definition::try_new_dimensional(29.53059f64, "d"), - Self::MeanJulianMonth => Definition::try_new_dimensional(1f64, "a_j/12"), - Self::MeanGregorianMonth => Definition::try_new_dimensional(1f64, "a_g/12"), - Self::Month => Definition::try_new_dimensional(1f64, "mo_j"), - Self::Tonne => Definition::try_new_dimensional(1000f64, "kg"), - Self::Bar => Definition::try_new_dimensional(100000f64, "Pa"), - Self::UnifiedAtomicMassUnit => { - Definition::try_new_dimensional(0.0000000000000000000000016605402f64, "g") + match self { + Self::Meter => Definition::Base, + Self::Second => Definition::Base, + Self::Gram => Definition::Base, + Self::Radian => Definition::Base, + Self::Kelvin => Definition::Base, + Self::Coulomb => Definition::Base, + Self::Candela => Definition::Base, + Self::TheNumberTenForArbitraryPowersStar => Definition::Value(10f64), + Self::TheNumberTenForArbitraryPowersCaret => Definition::Value(10f64), + Self::TheNumberPi => Definition::Value(::std::f64::consts::PI), + Self::Percent => Definition::Value(0.01), + Self::PartsPerThousand => PARTS_PER_THOUSAND, + Self::PartsPerMillion => PARTS_PER_MILLION, + Self::PartsPerBillion => PARTS_PER_BILLION, + Self::PartsPerTrillion => PARTS_PER_TRILLION, + Self::Mole => MOLE, + Self::Steradian => STERADIAN, + Self::Hertz => HERTZ, + Self::Newton => Definition::new_value_terms(1f64, "kg.m/s2"), + Self::Pascal => Definition::new_value_terms(1f64, "N/m2"), + Self::Joule => Definition::new_value_terms(1f64, "N.m"), + Self::Watt => Definition::new_value_terms(1f64, "J/s"), + Self::Ampere => Definition::new_value_terms(1f64, "C/s"), + Self::Volt => Definition::new_value_terms(1f64, "J/C"), + Self::Farad => Definition::new_value_terms(1f64, "C/V"), + Self::Ohm => Definition::new_value_terms(1f64, "V/A"), + Self::Siemens => SIEMENS, + Self::Weber => Definition::new_value_terms(1f64, "V.s"), + Self::DegreeCelsius => DEGREE_CELSIUS, + Self::Tesla => Definition::new_value_terms(1f64, "Wb/m2"), + Self::Henry => Definition::new_value_terms(1f64, "Wb/A"), + Self::Lumen => Definition::new_value_terms(1f64, "cd.sr"), + Self::Lux => Definition::new_value_terms(1f64, "lm/m2"), + Self::Becquerel => BECQUEREL, + Self::Gray => Definition::new_value_terms(1f64, "J/kg"), + Self::Sievert => Definition::new_value_terms(1f64, "J/kg"), + Self::Gon => GON, + Self::Degree => Definition::new_value_terms(2f64, "[pi].rad/360"), + Self::MinuteAngle => Definition::new_value_terms(1f64, "deg/60"), + Self::SecondAngle => Definition::new_value_terms(1f64, "'/60"), + Self::Liter => LITER, + Self::LiterSecondary => LITER, + Self::Are => ARE, + Self::Minute => MINUTE, + Self::Hour => HOUR, + Self::Day => DAY, + Self::TropicalYear => TROPICAL_YEAR, + Self::MeanJulianYear => MEAN_JULIAN_YEAR, + Self::MeanGregorianYear => MEAN_GREGORIAN_YEAR, + Self::Year => YEAR, + Self::Week => WEEK, + Self::SynodalMonth => SYNODAL_MONTH, + Self::MeanJulianMonth => Definition::new_value_terms(1f64, "a_j/12"), + Self::MeanGregorianMonth => Definition::new_value_terms(1f64, "a_g/12"), + Self::Month => MONTH, + Self::Tonne => TONNE, + Self::Bar => BAR, + Self::UnifiedAtomicMassUnit => UNIFIED_ATOMIC_MASS_UNIT, + Self::Electronvolt => Definition::new_value_terms(1f64, "[e].V"), + Self::AstronomicUnit => ASTRONOMIC_UNIT, + Self::Parsec => PARSEC, + Self::VelocityOfLight => Definition::new_value_terms(299792458f64, "m/s"), + Self::PlanckConstant => { + Definition::new_value_terms(0.00000000000000000000000000000000066260755f64, "J.s") } - Self::Electronvolt => Definition::try_new_dimensional(1f64, "[e].V"), - Self::AstronomicUnit => Definition::try_new_dimensional(149597.870691f64, "Mm"), - Self::Parsec => Definition::try_new_dimensional(30856780000000000f64, "m"), - Self::VelocityOfLight => Definition::try_new_dimensional(299792458f64, "m/s"), - Self::PlanckConstant => Definition::try_new_dimensional( - 0.00000000000000000000000000000000066260755f64, - "J.s", - ), Self::BoltzmannConstant => { - Definition::try_new_dimensional(0.00000000000000000000001380658f64, "J/K") + Definition::new_value_terms(0.00000000000000000000001380658f64, "J/K") } Self::PermittivityOfVacuum => { - Definition::try_new_dimensional(0.000000000008854187817f64, "F/m") - } - Self::PermeabilityOfVacuum => { - Definition::try_new_dimensional(1f64, "4.[pi].10*-7.N/A2") - } - Self::ElementaryCharge => { - Definition::try_new_dimensional(0.000000000000000000160217733f64, "C") - } - Self::ElectronMass => { - Definition::try_new_dimensional(0.00000000000000000000000000091093897f64, "g") - } - Self::ProtonMass => { - Definition::try_new_dimensional(0.0000000000000000000000016726231f64, "g") + Definition::new_value_terms(0.000000000008854187817f64, "F/m") } + Self::PermeabilityOfVacuum => Definition::new_value_terms(1f64, "4.[pi].10*-7.N/A2"), + Self::ElementaryCharge => ELEMENTARY_CHARGE, + Self::ElectronMass => ELECTRON_MASS, + Self::ProtonMass => PROTON_MASS, Self::NewtonianConstantOfGravitation => { - Definition::try_new_dimensional(0.0000000000667259f64, "m3.kg-1.s-2") - } - Self::StandardAccelerationOfFreeFall => { - Definition::try_new_dimensional(9.80665f64, "m/s2") - } - Self::StandardAtmosphere => Definition::try_new_dimensional(101325f64, "Pa"), - Self::LightYear => Definition::try_new_dimensional(1f64, "[c].a_j"), - Self::GramForce => Definition::try_new_dimensional(1f64, "g.[g]"), - Self::PoundForceAvoirdupois => Definition::try_new_dimensional(1f64, "[lb_av].[g]"), - Self::Kayser => Definition::try_new_dimensional(1f64, "cm-1"), - Self::Gal => Definition::try_new_dimensional(1f64, "cm/s2"), - Self::Dyne => Definition::try_new_dimensional(1f64, "g.cm/s2"), - Self::Erg => Definition::try_new_dimensional(1f64, "dyn.cm"), - Self::Poise => Definition::try_new_dimensional(1f64, "dyn.s/cm2"), - Self::Biot => Definition::try_new_dimensional(10f64, "A"), - Self::Stokes => Definition::try_new_dimensional(1f64, "cm2/s"), - Self::Maxwell => Definition::try_new_dimensional(0.00000001f64, "Wb"), - Self::Gauss => Definition::try_new_dimensional(0.0001f64, "T"), - Self::Oersted => Definition::try_new_dimensional(250f64, "/[pi].A/m"), - Self::Gilbert => Definition::try_new_dimensional(1f64, "Oe.cm"), - Self::Stilb => Definition::try_new_dimensional(1f64, "cd/cm2"), - Self::Lambert => Definition::try_new_dimensional(1f64, "cd/cm2/[pi]"), - Self::Phot => Definition::try_new_dimensional(0.0001f64, "lx"), - Self::Curie => Definition::try_new_dimensional(37000000000f64, "Bq"), - Self::Roentgen => Definition::try_new_dimensional(0.000258f64, "C/kg"), - Self::RadiationAbsorbedDose => Definition::try_new_dimensional(100f64, "erg/g"), - Self::RadiationEquivalentMan => Definition::try_new_dimensional(1f64, "RAD"), - Self::InchInternational => Definition::try_new_dimensional(2.54f64, "cm"), - Self::FootInternational => Definition::try_new_dimensional(12f64, "[in_i]"), - Self::YardInternational => Definition::try_new_dimensional(3f64, "[ft_i]"), - Self::MileInternational => Definition::try_new_dimensional(5280f64, "[ft_i]"), - Self::FathomInternational => Definition::try_new_dimensional(6f64, "[ft_i]"), - Self::NauticalMileInternational => Definition::try_new_dimensional(1852f64, "m"), - Self::KnotInternational => Definition::try_new_dimensional(1f64, "[nmi_i]/h"), - Self::SquareInchInternational => Definition::try_new_dimensional(1f64, "[in_i]2"), - Self::SquareFootInternational => Definition::try_new_dimensional(1f64, "[ft_i]2"), - Self::SquareYardInternational => Definition::try_new_dimensional(1f64, "[yd_i]2"), - Self::CubicInchInternational => Definition::try_new_dimensional(1f64, "[in_i]3"), - Self::CubicFootInternational => Definition::try_new_dimensional(1f64, "[ft_i]3"), - Self::CubicYardInternational => Definition::try_new_dimensional(1f64, "[yd_i]3"), - Self::BoardFootInternational => Definition::try_new_dimensional(144f64, "[in_i]3"), - Self::CordInternational => Definition::try_new_dimensional(128f64, "[ft_i]3"), - Self::MilInternational => Definition::try_new_dimensional(0.001f64, "[in_i]"), - Self::CircularMilInternational => { - Definition::try_new_dimensional(1f64, "[pi]/4.[mil_i]2") - } - Self::HandInternational => Definition::try_new_dimensional(4f64, "[in_i]"), - Self::FootUS => Definition::try_new_dimensional(1200f64, "m/3937"), - Self::YardUS => Definition::try_new_dimensional(3f64, "[ft_us]"), - Self::InchUS => Definition::try_new_dimensional(1f64, "[ft_us]/12"), - Self::RodUS => Definition::try_new_dimensional(16.5f64, "[ft_us]"), - Self::GuntersChainUS => Definition::try_new_dimensional(4f64, "[rd_us]"), - Self::LinkForGuntersChainUS => Definition::try_new_dimensional(1f64, "[ch_us]/100"), - Self::RamdensChainUS => Definition::try_new_dimensional(100f64, "[ft_us]"), - Self::LinkForRamdensChainUS => Definition::try_new_dimensional(1f64, "[rch_us]/100"), - Self::FathomUS => Definition::try_new_dimensional(6f64, "[ft_us]"), - Self::FurlongUS => Definition::try_new_dimensional(40f64, "[rd_us]"), - Self::MileUS => Definition::try_new_dimensional(8f64, "[fur_us]"), - Self::AcreUS => Definition::try_new_dimensional(160f64, "[rd_us]2"), - Self::SquareRodUS => Definition::try_new_dimensional(1f64, "[rd_us]2"), - Self::SquareMileUS => Definition::try_new_dimensional(1f64, "[mi_us]2"), - Self::Section => Definition::try_new_dimensional(1f64, "[mi_us]2"), - Self::Township => Definition::try_new_dimensional(36f64, "[sct]"), - Self::MilUS => Definition::try_new_dimensional(0.001f64, "[in_us]"), - Self::InchBritish => Definition::try_new_dimensional(2.539998f64, "cm"), - Self::FootBritish => Definition::try_new_dimensional(12f64, "[in_br]"), - Self::RodBritish => Definition::try_new_dimensional(16.5f64, "[ft_br]"), - Self::GuntersChainBritish => Definition::try_new_dimensional(4f64, "[rd_br]"), - Self::LinkForGuntersChainBritish => { - Definition::try_new_dimensional(1f64, "[ch_br]/100") - } - Self::FathomBritish => Definition::try_new_dimensional(6f64, "[ft_br]"), - Self::PaceBritish => Definition::try_new_dimensional(2.5f64, "[ft_br]"), - Self::YardBritish => Definition::try_new_dimensional(3f64, "[ft_br]"), - Self::MileBritish => Definition::try_new_dimensional(5280f64, "[ft_br]"), - Self::NauticalMileBritish => Definition::try_new_dimensional(6080f64, "[ft_br]"), - Self::KnotBritish => Definition::try_new_dimensional(1f64, "[nmi_br]/h"), - Self::AcreBritish => Definition::try_new_dimensional(4840f64, "[yd_br]2"), - Self::QueenAnnesWineGallonUS => Definition::try_new_dimensional(231f64, "[in_i]3"), - Self::BarrelUS => Definition::try_new_dimensional(42f64, "[gal_us]"), - Self::QuartUS => Definition::try_new_dimensional(1f64, "[gal_us]/4"), - Self::PintUS => Definition::try_new_dimensional(1f64, "[qt_us]/2"), - Self::GillUS => Definition::try_new_dimensional(1f64, "[pt_us]/4"), - Self::FluidOunceUS => Definition::try_new_dimensional(1f64, "[gil_us]/4"), - Self::FluidDramUS => Definition::try_new_dimensional(1f64, "[foz_us]/8"), - Self::MinimUS => Definition::try_new_dimensional(1f64, "[fdr_us]/60"), - Self::CordUS => Definition::try_new_dimensional(128f64, "[ft_i]3"), - Self::BushelUS => Definition::try_new_dimensional(2150.42f64, "[in_i]3"), - Self::HistoricalWinchesterGallon => Definition::try_new_dimensional(1f64, "[bu_us]/8"), - Self::PeckUS => Definition::try_new_dimensional(1f64, "[bu_us]/4"), - Self::DryQuartUS => Definition::try_new_dimensional(1f64, "[pk_us]/8"), - Self::DryPintUS => Definition::try_new_dimensional(1f64, "[dqt_us]/2"), - Self::TablespoonUS => Definition::try_new_dimensional(1f64, "[foz_us]/2"), - Self::TeaspoonUS => Definition::try_new_dimensional(1f64, "[tbs_us]/3"), - Self::CupUS => Definition::try_new_dimensional(16f64, "[tbs_us]"), - Self::MetricFluidOunce => Definition::try_new_dimensional(30f64, "mL"), - Self::MetricCup => Definition::try_new_dimensional(240f64, "mL"), - Self::MetricTeaspoon => Definition::try_new_dimensional(5f64, "mL"), - Self::MetricTablespoon => Definition::try_new_dimensional(15f64, "mL"), - Self::GallonBritish => Definition::try_new_dimensional(4.54609f64, "l"), - Self::PeckBritish => Definition::try_new_dimensional(2f64, "[gal_br]"), - Self::BushelBritish => Definition::try_new_dimensional(4f64, "[pk_br]"), - Self::QuartBritish => Definition::try_new_dimensional(1f64, "[gal_br]/4"), - Self::PintBritish => Definition::try_new_dimensional(1f64, "[qt_br]/2"), - Self::GillBritish => Definition::try_new_dimensional(1f64, "[pt_br]/4"), - Self::FluidOunceBritish => Definition::try_new_dimensional(1f64, "[gil_br]/5"), - Self::FluidDramBritish => Definition::try_new_dimensional(1f64, "[foz_br]/8"), - Self::MinimBritish => Definition::try_new_dimensional(1f64, "[fdr_br]/60"), - Self::Grain => Definition::try_new_dimensional(64.79891f64, "mg"), - Self::PoundAvoirdupois => Definition::try_new_dimensional(7000f64, "[gr]"), - Self::OunceAvoirdupois => Definition::try_new_dimensional(1f64, "[lb_av]/16"), - Self::DramAvoirdupois => Definition::try_new_dimensional(1f64, "[oz_av]/16"), - Self::ShortHundredweightAvoirdupois => { - Definition::try_new_dimensional(100f64, "[lb_av]") - } - Self::LongHunderdweightAvoirdupois => { - Definition::try_new_dimensional(112f64, "[lb_av]") - } - Self::ShortTonAvoirdupois => Definition::try_new_dimensional(20f64, "[scwt_av]"), - Self::LongTonAvoirdupois => Definition::try_new_dimensional(20f64, "[lcwt_av]"), - Self::StoneAvoirdupois => Definition::try_new_dimensional(14f64, "[lb_av]"), - Self::PennyweightTroy => Definition::try_new_dimensional(24f64, "[gr]"), - Self::OunceTroy => Definition::try_new_dimensional(20f64, "[pwt_tr]"), - Self::PoundTroy => Definition::try_new_dimensional(12f64, "[oz_tr]"), - Self::ScrupleApothecaries => Definition::try_new_dimensional(20f64, "[gr]"), - Self::DramApothecaries => Definition::try_new_dimensional(3f64, "[sc_ap]"), - Self::OunceApothecaries => Definition::try_new_dimensional(8f64, "[dr_ap]"), - Self::PoundApothecaries => Definition::try_new_dimensional(12f64, "[oz_ap]"), - Self::MetricOunce => Definition::try_new_dimensional(28f64, "g"), - Self::Line => Definition::try_new_dimensional(1f64, "[in_i]/12"), - Self::Point => Definition::try_new_dimensional(1f64, "[lne]/6"), - Self::Pica => Definition::try_new_dimensional(12f64, "[pnt]"), - Self::PrintersPoint => Definition::try_new_dimensional(0.013837f64, "[in_i]"), - Self::PrintersPica => Definition::try_new_dimensional(12f64, "[pnt_pr]"), - Self::Pied => Definition::try_new_dimensional(32.48f64, "cm"), - Self::Pouce => Definition::try_new_dimensional(1f64, "[pied]/12"), - Self::Ligne => Definition::try_new_dimensional(1f64, "[pouce]/12"), - Self::Didot => Definition::try_new_dimensional(1f64, "[ligne]/6"), - Self::Cicero => Definition::try_new_dimensional(12f64, "[didot]"), - Self::DegreeFahrenheit => Definition::try_new_dimensional_special( + Definition::new_value_terms(0.0000000000667259f64, "m3.kg-1.s-2") + } + Self::StandardAccelerationOfFreeFall => Definition::new_value_terms(9.80665f64, "m/s2"), + Self::StandardAtmosphere => STANDARD_ATMOSPHERE, + Self::LightYear => Definition::new_value_terms(1f64, "[c].a_j"), + Self::GramForce => Definition::new_value_terms(1f64, "g.[g]"), + Self::PoundForceAvoirdupois => Definition::new_value_terms(1f64, "[lb_av].[g]"), + Self::Kayser => KAYSER, + Self::Gal => Definition::new_value_terms(1f64, "cm/s2"), + Self::Dyne => Definition::new_value_terms(1f64, "g.cm/s2"), + Self::Erg => Definition::new_value_terms(1f64, "dyn.cm"), + Self::Poise => Definition::new_value_terms(1f64, "dyn.s/cm2"), + Self::Biot => BIOT, + Self::Stokes => Definition::new_value_terms(1f64, "cm2/s"), + Self::Maxwell => MAXWELL, + Self::Gauss => GAUSS, + Self::Oersted => Definition::new_value_terms(250f64, "/[pi].A/m"), + Self::Gilbert => Definition::new_value_terms(1f64, "Oe.cm"), + Self::Stilb => Definition::new_value_terms(1f64, "cd/cm2"), + Self::Lambert => Definition::new_value_terms(1f64, "cd/cm2/[pi]"), + Self::Phot => PHOT, + Self::Curie => CURIE, + Self::Roentgen => Definition::new_value_terms(0.000258f64, "C/kg"), + Self::RadiationAbsorbedDose => Definition::new_value_terms(100f64, "erg/g"), + Self::RadiationEquivalentMan => Definition::new_value_terms(1f64, "RAD"), + Self::InchInternational => INCH_INTERNATIONAL, + Self::FootInternational => FOOT_INTERNATIONAL, + Self::YardInternational => YARD_INTERNATIONAL, + Self::MileInternational => MILE_INTERNATIONAL, + Self::FathomInternational => FATHOM_INTERNATIONAL, + Self::NauticalMileInternational => NAUTICAL_MILE_INTERNATIONAL, + Self::KnotInternational => Definition::new_value_terms(1f64, "[nmi_i]/h"), + Self::SquareInchInternational => SQUARE_INCH_INTERNATIONAL, + Self::SquareFootInternational => SQUARE_FOOT_INTERNATIONAL, + Self::SquareYardInternational => SQUARE_YARD_INTERNATIONAL, + Self::CubicInchInternational => CUBIC_INCH_INTERNATIONAL, + Self::CubicFootInternational => CUBIC_FOOT_INTERNATIONAL, + Self::CubicYardInternational => CUBIC_YARD_INTERNATIONAL, + Self::BoardFootInternational => BOARD_FOOT_INTERNATIONAL, + Self::CordInternational => CORD_INTERNATIONAL, + Self::MilInternational => MIL_INTERNATIONAL, + Self::CircularMilInternational => Definition::new_value_terms(1f64, "[pi]/4.[mil_i]2"), + Self::HandInternational => HAND_INTERNATIONAL, + Self::FootUS => Definition::new_value_terms(1200f64, "m/3937"), + Self::YardUS => YARD_US, + Self::InchUS => Definition::new_value_terms(1f64, "[ft_us]/12"), + Self::RodUS => ROD_US, + Self::GuntersChainUS => GUNTERS_CHAIN_US, + Self::LinkForGuntersChainUS => Definition::new_value_terms(1f64, "[ch_us]/100"), + Self::RamdensChainUS => RAMDENS_CHAIN_US, + Self::LinkForRamdensChainUS => Definition::new_value_terms(1f64, "[rch_us]/100"), + Self::FathomUS => FATHOM_US, + Self::FurlongUS => FURLONG_US, + Self::MileUS => MILE_US, + Self::AcreUS => ACRE_US, + Self::SquareRodUS => SQUARE_ROD_US, + Self::SquareMileUS => SQUARE_MILE_US, + Self::Section => SECTION, + Self::Township => TOWNSHIP, + Self::MilUS => MIL_US, + Self::InchBritish => INCH_BRITISH, + Self::FootBritish => FOOT_BRITISH, + Self::RodBritish => ROD_BRITISH, + Self::GuntersChainBritish => GUNTERS_CHAIN_BRITISH, + Self::LinkForGuntersChainBritish => Definition::new_value_terms(1f64, "[ch_br]/100"), + Self::FathomBritish => FATHOM_BRITISH, + Self::PaceBritish => PACE_BRITISH, + Self::YardBritish => YARD_BRITISH, + Self::MileBritish => MILE_BRITISH, + Self::NauticalMileBritish => NAUTICLE_MILE_BRITISH, + Self::KnotBritish => Definition::new_value_terms(1f64, "[nmi_br]/h"), + Self::AcreBritish => ACRE_BRITISH, + Self::QueenAnnesWineGallonUS => QUEEN_ANNES_WINE_GALLON_US, + Self::BarrelUS => BARREL_US, + Self::QuartUS => Definition::new_value_terms(1f64, "[gal_us]/4"), + Self::PintUS => Definition::new_value_terms(1f64, "[qt_us]/2"), + Self::GillUS => Definition::new_value_terms(1f64, "[pt_us]/4"), + Self::FluidOunceUS => Definition::new_value_terms(1f64, "[gil_us]/4"), + Self::FluidDramUS => Definition::new_value_terms(1f64, "[foz_us]/8"), + Self::MinimUS => Definition::new_value_terms(1f64, "[fdr_us]/60"), + Self::CordUS => CORD_US, + Self::BushelUS => BUSHEL_US, + Self::HistoricalWinchesterGallon => Definition::new_value_terms(1f64, "[bu_us]/8"), + Self::PeckUS => Definition::new_value_terms(1f64, "[bu_us]/4"), + Self::DryQuartUS => Definition::new_value_terms(1f64, "[pk_us]/8"), + Self::DryPintUS => Definition::new_value_terms(1f64, "[dqt_us]/2"), + Self::TablespoonUS => Definition::new_value_terms(1f64, "[foz_us]/2"), + Self::TeaspoonUS => Definition::new_value_terms(1f64, "[tbs_us]/3"), + Self::CupUS => CUP_US, + Self::MetricFluidOunce => METRIC_FLUID_OUNCE, + Self::MetricCup => METRIC_CUP, + Self::MetricTeaspoon => METRIC_TEASPOON, + Self::MetricTablespoon => METRIC_TABLESPOON, + Self::GallonBritish => GALLON_BRITISH, + Self::PeckBritish => PECK_BRITISH, + Self::BushelBritish => BUSHEL_BRITISH, + Self::QuartBritish => Definition::new_value_terms(1f64, "[gal_br]/4"), + Self::PintBritish => Definition::new_value_terms(1f64, "[qt_br]/2"), + Self::GillBritish => Definition::new_value_terms(1f64, "[pt_br]/4"), + Self::FluidOunceBritish => Definition::new_value_terms(1f64, "[gil_br]/5"), + Self::FluidDramBritish => Definition::new_value_terms(1f64, "[foz_br]/8"), + Self::MinimBritish => Definition::new_value_terms(1f64, "[fdr_br]/60"), + Self::Grain => GRAIN, + Self::PoundAvoirdupois => POUND_AVOIRDUPOIS, + Self::OunceAvoirdupois => Definition::new_value_terms(1f64, "[lb_av]/16"), + Self::DramAvoirdupois => Definition::new_value_terms(1f64, "[oz_av]/16"), + Self::ShortHundredweightAvoirdupois => SHORT_HUNDREDWEIGHT_AVOIRDUPOIS, + Self::LongHunderdweightAvoirdupois => LONG_HUNDREDWEIGHT_AVOIRDUPOIS, + Self::ShortTonAvoirdupois => SHORT_TON_AVOIRDUPOIS, + Self::LongTonAvoirdupois => LONG_TON_AVOIRDUPOIS, + Self::StoneAvoirdupois => STONE_AVOIRDUPOIS, + Self::PennyweightTroy => PENNYWEIGHT_TROY, + Self::OunceTroy => OUNCE_TROY, + Self::PoundTroy => POUND_TROY, + Self::ScrupleApothecaries => SCUPLE_APOTHECARIES, + Self::DramApothecaries => DRAM_APOTHECARIES, + Self::OunceApothecaries => OUNCE_APOTHECARIES, + Self::PoundApothecaries => POUND_APOTHECARIES, + Self::MetricOunce => METRIC_OUNCE, + Self::Line => Definition::new_value_terms(1f64, "[in_i]/12"), + Self::Point => Definition::new_value_terms(1f64, "[lne]/6"), + Self::Pica => PICA, + Self::PrintersPoint => PRINTERS_POINT, + Self::PrintersPica => PRINTERS_PICA, + Self::Pied => PIED, + Self::Pouce => Definition::new_value_terms(1f64, "[pied]/12"), + Self::Ligne => Definition::new_value_terms(1f64, "[pouce]/12"), + Self::Didot => Definition::new_value_terms(1f64, "[ligne]/6"), + Self::Cicero => CICERO, + Self::DegreeFahrenheit => Definition::new_value_terms_special( 5f64, "K/9", FunctionSet { @@ -573,8 +548,8 @@ impl Atom { convert_to: |value: f64| 5.0 / 9.0 * (value + 459.67), }, ), - Self::DegreeRankine => Definition::try_new_dimensional(5f64, "K/9"), - Self::DegreeReaumur => Definition::try_new_dimensional_special( + Self::DegreeRankine => Definition::new_value_terms(5f64, "K/9"), + Self::DegreeReaumur => Definition::new_value_terms_special( 5f64, "K/4", FunctionSet { @@ -582,120 +557,62 @@ impl Atom { convert_to: |value: f64| (value / 0.8) + 273.15, }, ), - Self::CalorieAt15C => Definition::try_new_dimensional(4.1858f64, "J"), - Self::CalorieAt20C => Definition::try_new_dimensional(4.1819f64, "J"), - Self::MeanCalorie => Definition::try_new_dimensional(4.19002f64, "J"), - Self::InternationalTableCalorie => Definition::try_new_dimensional(4.1868f64, "J"), - Self::ThermochemicalCalorie => Definition::try_new_dimensional(4.184f64, "J"), - Self::Calorie => Definition::try_new_dimensional(1f64, "cal_th"), - Self::NutritionLabelCalories => Definition::try_new_dimensional(1f64, "kcal_th"), - Self::BritishThermalUnitAt39F => Definition::try_new_dimensional(1.05967f64, "kJ"), - Self::BritishThermalUnitAt59F => Definition::try_new_dimensional(1.0548f64, "kJ"), - Self::BritishThermalUnitAt60F => Definition::try_new_dimensional(1.05468f64, "kJ"), - Self::MeanBritishThermalUnit => Definition::try_new_dimensional(1.05587f64, "kJ"), - Self::InternationalTableBritishThermalUnit => { - Definition::try_new_dimensional(1.05505585262f64, "kJ") - } - Self::ThermochemicalBritishThermalUnit => { - Definition::try_new_dimensional(1.05435f64, "kJ") - } - Self::BritishThermalUnit => Definition::try_new_dimensional(1f64, "[Btu_th]"), - Self::Horsepower => Definition::try_new_dimensional(550f64, "[ft_i].[lbf_av]/s"), - Self::Tex => Definition::try_new_dimensional(1f64, "g/km"), - Self::Denier => Definition::try_new_dimensional(1f64, "g/9/km"), - Self::MeterOfWaterColumn => Definition::try_new_dimensional(9.80665f64, "kPa"), - Self::MeterOfMercuryColumn => Definition::try_new_dimensional(133.322f64, "kPa"), - Self::InchOfWaterColumn => Definition::try_new_dimensional(1f64, "m[H2O].[in_i]/m"), - Self::InchOfMercuryColumn => Definition::try_new_dimensional(1f64, "m[Hg].[in_i]/m"), + Self::CalorieAt15C => CALORIE_AT_15C, + Self::CalorieAt20C => CALORIE_AT_20C, + Self::MeanCalorie => MEAN_CALORIE, + Self::InternationalTableCalorie => INTERNATIONAL_TABLE_CALORIE, + Self::ThermochemicalCalorie => THERMOCHEMICAL_CALORIE, + Self::Calorie => CALORIE, + Self::NutritionLabelCalories => NUTRITION_LABEL_CALORIES, + Self::BritishThermalUnitAt39F => BRITISH_THERMAL_UNIT_AT_39F, + Self::BritishThermalUnitAt59F => BRITISH_THERMAL_UNIT_AT_59F, + Self::BritishThermalUnitAt60F => BRITISH_THERMAL_UNIT_AT_60F, + Self::MeanBritishThermalUnit => MEAN_BRITISH_THERMAL_UNIT, + Self::InternationalTableBritishThermalUnit => INTERNATIONAL_TABLE_BRITISH_THERMAL_UNIT, + Self::ThermochemicalBritishThermalUnit => THERMOCHEMICAL_BRITISH_THERMAL_UNIT, + Self::BritishThermalUnit => BRITISH_THERMAL_UNIT, + Self::Horsepower => Definition::new_value_terms(550f64, "[ft_i].[lbf_av]/s"), + Self::Tex => Definition::new_value_terms(1f64, "g/km"), + Self::Denier => Definition::new_value_terms(1f64, "g/9/km"), + Self::MeterOfWaterColumn => METER_OF_WATER_COLUMN, + Self::MeterOfMercuryColumn => METER_OF_MERCURY_COLUMN, + Self::InchOfWaterColumn => Definition::new_value_terms(1f64, "m[H2O].[in_i]/m"), + Self::InchOfMercuryColumn => Definition::new_value_terms(1f64, "m[Hg].[in_i]/m"), Self::PeripheralVascularResistanceUnit => { - Definition::try_new_dimensional(1f64, "mm[Hg].s/ml") - } - Self::WoodUnit => Definition::try_new_dimensional(1f64, "mm[Hg].min/L"), - Self::Diopter => Definition::try_new_dimensional(1f64, "/m"), - Self::PrismDiopter => Definition::try_new_dimensional_special( - 1f64, - "rad", - FunctionSet { - convert_from: |value: f64| (value / 100.0).atan(), - convert_to: |value: f64| value.tan() * 100.0, - }, - ), - Self::PercentOfSlope => Definition::try_new_dimensional_special( - 1f64, - "deg", - FunctionSet { - convert_from: |value: f64| (value / 100.0).atan(), - convert_to: |value: f64| value.tan() * 100.0, - }, - ), - Self::MeshInternational => Definition::try_new_dimensional(1f64, "/[in_i]"), - Self::Charriere => Definition::try_new_dimensional(1f64, "mm/3"), - Self::Drop => Definition::try_new_dimensional(1f64, "ml/20"), - Self::HounsfieldUnit => Ok(Definition::NonDimensional(1.0)), - Self::MetabolicEquivalent => Definition::try_new_dimensional(3.5f64, "mL/min/kg"), + Definition::new_value_terms(1f64, "mm[Hg].s/ml") + } + Self::WoodUnit => Definition::new_value_terms(1f64, "mm[Hg].min/L"), + Self::Diopter => Definition::new_value_terms(1f64, "/m"), + Self::PrismDiopter => PRISM_DIOPTER, + Self::PercentOfSlope => PERCENT_OF_SLOPE, + Self::MeshInternational => Definition::new_value_terms(1f64, "/[in_i]"), + Self::Charriere => Definition::new_value_terms(1f64, "mm/3"), + Self::Drop => Definition::new_value_terms(1f64, "ml/20"), + Self::HounsfieldUnit => ONE, + Self::MetabolicEquivalent => Definition::new_value_terms(3.5f64, "mL/min/kg"), Self::HomeopathicPotencyOfDecimalSeriesRetired => { - Ok(Definition::NonDimensionalSpecial { - value: 1f64, - function_set: FunctionSet { - convert_from: |value: f64| -value.log10(), - convert_to: |value: f64| 10_f64.powf(-value), - }, - }) + HOMEOPATHIC_POTENCY_OF_DECIMAL_SERIES_RETIRED } Self::HomeopathicPotencyOfCentesimalSeriesRetired => { - Ok(Definition::NonDimensionalSpecial { - value: 1f64, - function_set: FunctionSet { - convert_from: |value: f64| -value.ln() / 100_f64.ln(), - convert_to: |value: f64| 100_f64.powf(-value), - }, - }) + HOMEOPATHIC_POTENCY_OF_CENTESIMAL_SERIES_RETIRED } Self::HomeopathicPotencyOfMillesimalSeriesRetired => { - Ok(Definition::NonDimensionalSpecial { - value: 1f64, - function_set: FunctionSet { - convert_from: |value: f64| -value.ln() / 1_000_f64.ln(), - convert_to: |value: f64| 1_000_f64.powf(-value), - }, - }) + HOMEOPATHIC_POTENCY_OF_MILLESIMAL_SERIES_RETIRED } Self::HomeopathicPotencyOfQuintamillesimalSeriesRetired => { - Ok(Definition::NonDimensionalSpecial { - value: 1f64, - function_set: FunctionSet { - convert_from: |value: f64| -value.ln() / 50_000_f64.ln(), - convert_to: |value: f64| 50_000_f64.powf(-value), - }, - }) - } - Self::HomeopathicPotencyOfDecimalHahnemannianSeries => { - Ok(Definition::NonDimensional(1.0)) - } - Self::HomeopathicPotencyOfCentesimalHahnemannianSeries => { - Ok(Definition::NonDimensional(1.0)) - } - Self::HomeopathicPotencyOfMillesimalHahnemannianSeries => { - Ok(Definition::NonDimensional(1.0)) - } - Self::HomeopathicPotencyOfQuintamillesimalHahnemannianSeries => { - Ok(Definition::NonDimensional(1.0)) - } - Self::HomeopathicPotencyOfDecimalKorsakovianSeries => { - Ok(Definition::NonDimensional(1.0)) - } - Self::HomeopathicPotencyOfCentesimalKorsakovianSeries => { - Ok(Definition::NonDimensional(1.0)) - } - Self::HomeopathicPotencyOfMillesimalKorsakovianSeries => { - Ok(Definition::NonDimensional(1.0)) - } - Self::HomeopathicPotencyOfQuintamillesimalKorsakovianSeries => { - Ok(Definition::NonDimensional(1.0)) - } - Self::Equivalents => Definition::try_new_dimensional(1f64, "mol"), - Self::Osmole => Definition::try_new_dimensional(1f64, "mol"), - Self::PH => Definition::try_new_dimensional_special( + HOMEOPATHIC_POTENCY_OF_QUINTMILLESIMAL_SERIES_RETIRED + } + Self::HomeopathicPotencyOfDecimalHahnemannianSeries => ONE, + Self::HomeopathicPotencyOfCentesimalHahnemannianSeries => ONE, + Self::HomeopathicPotencyOfMillesimalHahnemannianSeries => ONE, + Self::HomeopathicPotencyOfQuintamillesimalHahnemannianSeries => ONE, + Self::HomeopathicPotencyOfDecimalKorsakovianSeries => ONE, + Self::HomeopathicPotencyOfCentesimalKorsakovianSeries => ONE, + Self::HomeopathicPotencyOfMillesimalKorsakovianSeries => ONE, + Self::HomeopathicPotencyOfQuintamillesimalKorsakovianSeries => ONE, + Self::Equivalents => EQUIVALENTS, + Self::Osmole => OSMOLE, + Self::PH => Definition::new_value_terms_special( 1f64, "mol/l", FunctionSet { @@ -703,60 +620,48 @@ impl Atom { convert_to: |value: f64| -value.log10(), }, ), - Self::GramPercent => Definition::try_new_dimensional(1f64, "g/dl"), - Self::SvedbergUnit => Definition::try_new_dimensional(1f64, "10*-13.s"), - Self::HighPowerField => Ok(Definition::NonDimensional(1.0)), - Self::LowPowerField => Ok(Definition::NonDimensional(100.0)), - Self::Katal => Definition::try_new_dimensional(1f64, "mol/s"), - Self::Unit => Definition::try_new_dimensional(1f64, "umol/min"), - Self::InternationalUnit => Ok(Definition::NonDimensional(1.0)), - Self::InternationalUnitSecondary => Definition::try_new_dimensional(1f64, "[iU]"), - Self::ArbitraryUnit => Ok(Definition::NonDimensional(1.0)), - Self::UnitedStatesPharmacopeiaUnit => Ok(Definition::NonDimensional(1.0)), - Self::GplUnit => Ok(Definition::NonDimensional(1.0)), - Self::MplUnit => Ok(Definition::NonDimensional(1.0)), - Self::AplUnit => Ok(Definition::NonDimensional(1.0)), - Self::BethesdaUnit => Ok(Definition::NonDimensional(1.0)), - Self::AntiFactorXaUnit => Ok(Definition::NonDimensional(1.0)), - Self::ToddUnit => Ok(Definition::NonDimensional(1.0)), - Self::DyeUnit => Ok(Definition::NonDimensional(1.0)), - Self::SomogyiUnit => Ok(Definition::NonDimensional(1.0)), - Self::BodanskyUnit => Ok(Definition::NonDimensional(1.0)), - Self::KingArmstrongUnit => Ok(Definition::NonDimensional(1.0)), - Self::KunkelUnit => Ok(Definition::NonDimensional(1.0)), - Self::MacLaganUnit => Ok(Definition::NonDimensional(1.0)), - Self::TuberculinUnit => Ok(Definition::NonDimensional(1.0)), - Self::CellCultureInfectiousDose => Ok(Definition::NonDimensional(1.0)), - Self::TissueCultureInfectiousDose => Ok(Definition::NonDimensional(1.0)), - Self::EmbryoInfectiousDose => Ok(Definition::NonDimensional(1.0)), - Self::PlaqueFormingUnits => Ok(Definition::NonDimensional(1.0)), - Self::FocusFormingUnits => Ok(Definition::NonDimensional(1.0)), - Self::ColonyFormingUnits => Ok(Definition::NonDimensional(1.0)), - Self::IndexOfReactivity => Ok(Definition::NonDimensional(1.0)), - Self::BioequivalentAllergenUnit => Ok(Definition::NonDimensional(1.0)), - Self::AllergenUnit => Ok(Definition::NonDimensional(1.0)), - Self::AllergenUnitForAmbrosiaArtemisiifolia => Ok(Definition::NonDimensional(1.0)), - Self::ProteinNitrogenUnit => Ok(Definition::NonDimensional(1.0)), - Self::LimitOfFlocculation => Ok(Definition::NonDimensional(1.0)), - Self::DAntigenUnit => Ok(Definition::NonDimensional(1.0)), - Self::FibrinogenEquivalentUnit => Ok(Definition::NonDimensional(1.0)), - Self::ElisaUnit => Ok(Definition::NonDimensional(1.0)), - Self::EhrlichUnit => Ok(Definition::NonDimensional(1.0)), - Self::Neper => Ok(Definition::NonDimensionalSpecial { - value: 1.0, - function_set: FunctionSet { - convert_from: f64::ln, - convert_to: f64::exp, - }, - }), - Self::Bel => Ok(Definition::NonDimensionalSpecial { - value: 1.0, - function_set: FunctionSet { - convert_from: f64::log10, - convert_to: |value: f64| 10_f64.powf(value), - }, - }), - Self::BelSoundPressure => Definition::try_new_dimensional_special( + Self::GramPercent => Definition::new_value_terms(1f64, "g/dl"), + Self::SvedbergUnit => Definition::new_value_terms(1f64, "10*-13.s"), + Self::HighPowerField => ONE, + Self::LowPowerField => Definition::Value(100.0), + Self::Katal => Definition::new_value_terms(1f64, "mol/s"), + Self::Unit => Definition::new_value_terms(1f64, "umol/min"), + Self::InternationalUnit => ONE, + Self::InternationalUnitSecondary => INTERNATIONAL_UNIT_SECONDARY, + Self::ArbitraryUnit => ONE, + Self::UnitedStatesPharmacopeiaUnit => ONE, + Self::GplUnit => ONE, + Self::MplUnit => ONE, + Self::AplUnit => ONE, + Self::BethesdaUnit => ONE, + Self::AntiFactorXaUnit => ONE, + Self::ToddUnit => ONE, + Self::DyeUnit => ONE, + Self::SomogyiUnit => ONE, + Self::BodanskyUnit => ONE, + Self::KingArmstrongUnit => ONE, + Self::KunkelUnit => ONE, + Self::MacLaganUnit => ONE, + Self::TuberculinUnit => ONE, + Self::CellCultureInfectiousDose => ONE, + Self::TissueCultureInfectiousDose => ONE, + Self::EmbryoInfectiousDose => ONE, + Self::PlaqueFormingUnits => ONE, + Self::FocusFormingUnits => ONE, + Self::ColonyFormingUnits => ONE, + Self::IndexOfReactivity => ONE, + Self::BioequivalentAllergenUnit => ONE, + Self::AllergenUnit => ONE, + Self::AllergenUnitForAmbrosiaArtemisiifolia => ONE, + Self::ProteinNitrogenUnit => ONE, + Self::LimitOfFlocculation => ONE, + Self::DAntigenUnit => ONE, + Self::FibrinogenEquivalentUnit => ONE, + Self::ElisaUnit => ONE, + Self::EhrlichUnit => ONE, + Self::Neper => NEPER, + Self::Bel => BEL, + Self::BelSoundPressure => Definition::new_value_terms_special( 2f64, "10*-5.Pa", FunctionSet { @@ -764,87 +669,36 @@ impl Atom { convert_to: |value: f64| 10_f64.powf(value / 2.0), }, ), - Self::BelVolt => Definition::try_new_dimensional_special( - 1f64, - "V", - FunctionSet { - convert_from: |value: f64| 2.0 * value.log10(), - convert_to: |value: f64| 10_f64.powf(value / 2.0), - }, - ), - Self::BelMillivolt => Definition::try_new_dimensional_special( - 1f64, - "mV", - FunctionSet { - convert_from: |value: f64| 2.0 * value.log10(), - convert_to: |value: f64| 10_f64.powf(value / 2.0), - }, - ), - Self::BelMicrovolt => Definition::try_new_dimensional_special( + Self::BelVolt => BEL_VOLT, + Self::BelMillivolt => BEL_MILLIVOLT, + Self::BelMicrovolt => BEL_MICROVOLT, + Self::Bel10Nanovolt => BEL_10_NANOVOLT, + Self::BelWatt => BEL_WATT, + Self::BelKilowatt => BEL_KILOWATT, + Self::Stere => STERE, + Self::Angstrom => ANGSTROM, + Self::Barn => BARN, + Self::TechnicalAtmosphere => Definition::new_value_terms(1f64, "kgf/cm2"), + Self::Mho => MHO, + Self::PoundPerSqareInch => Definition::new_value_terms(1f64, "[lbf_av]/[in_i]2"), + Self::Circle => Definition::new_value_terms(2f64, "[pi].rad"), + Self::Spere => Definition::new_value_terms(4f64, "[pi].sr"), + Self::MetricCarat => METRIC_CARAT, + Self::CaratOfGoldAlloys => Definition::new_value_terms(1f64, "/24"), + Self::Smoot => SMOOT, + Self::MeterPerSquareSecondsPerSquareRootOfHertz => Definition::new_value_terms_special( 1f64, - "uV", + "m2/s4/Hz", FunctionSet { - convert_from: |value: f64| 2.0 * value.log10(), - convert_to: |value: f64| 10_f64.powf(value / 2.0), + convert_from: f64::sqrt, + convert_to: |value: f64| value * value, }, ), - Self::Bel10Nanovolt => Definition::try_new_dimensional_special( - 10f64, - "nV", - FunctionSet { - convert_from: |value: f64| 2.0 * value.log10(), - convert_to: |value: f64| 10_f64.powf(value / 2.0), - }, - ), - Self::BelWatt => Definition::try_new_dimensional_special( - 1f64, - "W", - FunctionSet { - convert_from: f64::log10, - convert_to: |value: f64| 10_f64.powf(value), - }, - ), - Self::BelKilowatt => Definition::try_new_dimensional_special( - 1f64, - "kW", - FunctionSet { - convert_from: f64::log10, - convert_to: |value: f64| 10_f64.powf(value), - }, - ), - Self::Stere => Definition::try_new_dimensional(1f64, "m3"), - Self::Angstrom => Definition::try_new_dimensional(0.1f64, "nm"), - Self::Barn => Definition::try_new_dimensional(100f64, "fm2"), - Self::TechnicalAtmosphere => Definition::try_new_dimensional(1f64, "kgf/cm2"), - Self::Mho => Definition::try_new_dimensional(1f64, "S"), - Self::PoundPerSqareInch => Definition::try_new_dimensional(1f64, "[lbf_av]/[in_i]2"), - Self::Circle => Definition::try_new_dimensional(2f64, "[pi].rad"), - Self::Spere => Definition::try_new_dimensional(4f64, "[pi].sr"), - Self::MetricCarat => Definition::try_new_dimensional(0.2f64, "g"), - Self::CaratOfGoldAlloys => Definition::try_new_dimensional(1f64, "/24"), - Self::Smoot => Definition::try_new_dimensional(67f64, "[in_i]"), - Self::MeterPerSquareSecondsPerSquareRootOfHertz => { - Definition::try_new_dimensional_special( - 1f64, - "m2/s4/Hz", - FunctionSet { - convert_from: f64::sqrt, - convert_to: |value: f64| value * value, - }, - ) - } - Self::BitLogarithmusDualis => Ok(Definition::NonDimensionalSpecial { - value: 1f64, - function_set: FunctionSet { - convert_from: f64::log2, - convert_to: f64::exp2, - }, - }), - Self::Bit => Ok(Definition::NonDimensional(1.0)), - Self::Byte => Definition::try_new_dimensional(8f64, "bit"), - Self::Baud => Definition::try_new_dimensional(1f64, "/s"), - }; - result.expect("BUG! Bad Atom -> Definition mapping!") + Self::BitLogarithmusDualis => BIT_LOGARITHMUS_DUALIS, + Self::Bit => ONE, + Self::Byte => BYTE, + Self::Baud => Definition::new_value_terms(1f64, "/s"), + } } #[must_use] pub const fn property(self) -> Property { diff --git a/crates/api/src/parser/atom_test.rs b/crates/api/src/parser/atom_test.rs index e8e5bf5d..180b055d 100644 --- a/crates/api/src/parser/atom_test.rs +++ b/crates/api/src/parser/atom_test.rs @@ -2,6 +2,8 @@ //! #![cfg(test)] +use approx::{assert_relative_eq, assert_ulps_eq}; + use crate::{ parser::{ term::UNITY_ARRAY, Atom, Classification, Composable, Composition, Dimension, Prefix, @@ -9,7 +11,6 @@ use crate::{ }, ucum_unit::UcumUnit, }; -use approx::{assert_relative_eq, assert_ulps_eq}; macro_rules! validate_definition { ( diff --git a/crates/api/src/parser/definition.rs b/crates/api/src/parser/definition.rs index 7e163eef..d9f646fa 100644 --- a/crates/api/src/parser/definition.rs +++ b/crates/api/src/parser/definition.rs @@ -1,12 +1,14 @@ #![allow(clippy::large_enum_variant)] #![allow(clippy::result_large_err)] -use std::borrow::Cow; +pub(super) mod consts; + +use std::{borrow::Cow, str::FromStr}; use num_traits::One; use crate::{ - parser::{function_set::FunctionSet, Error, Term}, + parser::{function_set::FunctionSet, Term}, reducible::Reducible, }; @@ -18,16 +20,16 @@ use super::term; /// pub(crate) enum Definition { Base, - NonDimensional(V), - NonDimensionalSpecial { + Value(V), + ValueSpecial { value: V, function_set: FunctionSet, }, - Dimensional { + ValueTerms { value: V, terms: Cow<'static, [Term]>, }, - DimensionalSpecial { + ValueTermsSpecial { value: V, terms: Cow<'static, [Term]>, function_set: FunctionSet, @@ -35,23 +37,29 @@ pub(crate) enum Definition { } impl Definition { - pub(crate) fn try_new_dimensional(value: V, expression: &'static str) -> Result { - Ok(Self::Dimensional { + pub(crate) fn new_value_terms(value: V, expression: &'static str) -> Self { + Self::ValueTerms { value, - terms: Cow::Owned(super::parse(expression)?), - }) + terms: crate::Unit::from_str(expression).map_or_else( + |_| unreachable!("expected valid unit definition string: {expression}"), + crate::Unit::into_terms, + ), + } } - pub(crate) fn try_new_dimensional_special( + pub(crate) fn new_value_terms_special( value: V, expression: &'static str, function_set: FunctionSet, - ) -> Result { - Ok(Self::DimensionalSpecial { + ) -> Self { + Self::ValueTermsSpecial { value, - terms: Cow::Owned(super::parse(expression)?), + terms: crate::Unit::from_str(expression).map_or_else( + |_| unreachable!("expected valid unit definition string: {expression}"), + crate::Unit::into_terms, + ), function_set, - }) + } } pub(crate) fn value(&self) -> V @@ -60,20 +68,19 @@ impl Definition { { match self { Self::Base => ::one(), - Self::NonDimensional(value) => value.clone(), - Self::NonDimensionalSpecial { value, .. } - | Self::Dimensional { value, .. } - | Self::DimensionalSpecial { value, .. } => (*value).clone(), + Self::Value(value) => value.clone(), + Self::ValueSpecial { value, .. } + | Self::ValueTerms { value, .. } + | Self::ValueTermsSpecial { value, .. } => (*value).clone(), } } pub(crate) const fn terms(&self) -> &Cow<'static, [Term]> { match self { - Self::Base => &Cow::Borrowed(term::UNITY_ARRAY_REF), - Self::NonDimensional(_) | Self::NonDimensionalSpecial { .. } => { + Self::Value(_) | Self::ValueSpecial { .. } | Self::Base => { &Cow::Borrowed(term::UNITY_ARRAY_REF) } - Self::Dimensional { terms, .. } | Self::DimensionalSpecial { terms, .. } => terms, + Self::ValueTerms { terms, .. } | Self::ValueTermsSpecial { terms, .. } => terms, } } } @@ -82,10 +89,10 @@ impl Reducible for Definition { fn reduce_value(&self, other_value: f64) -> f64 { match self { Self::Base => One::one(), - Self::NonDimensional(value) => *value, - Self::Dimensional { value, terms } => value * terms.reduce_value(other_value), - Self::NonDimensionalSpecial { function_set, .. } - | Self::DimensionalSpecial { function_set, .. } => { + Self::Value(value) => *value, + Self::ValueTerms { value, terms } => value * terms.reduce_value(other_value), + Self::ValueSpecial { function_set, .. } + | Self::ValueTermsSpecial { function_set, .. } => { (function_set.convert_to)(other_value) } } @@ -94,10 +101,10 @@ impl Reducible for Definition { fn calculate_magnitude(&self, other_value: f64) -> f64 { match self { Self::Base => One::one(), - Self::NonDimensional(value) => *value, - Self::Dimensional { value, terms } => value * terms.calculate_magnitude(other_value), - Self::NonDimensionalSpecial { function_set, .. } - | Self::DimensionalSpecial { function_set, .. } => { + Self::Value(value) => *value, + Self::ValueTerms { value, terms } => value * terms.calculate_magnitude(other_value), + Self::ValueSpecial { function_set, .. } + | Self::ValueTermsSpecial { function_set, .. } => { (function_set.convert_from)(other_value) } } diff --git a/crates/api/src/parser/definition/consts.rs b/crates/api/src/parser/definition/consts.rs new file mode 100644 index 00000000..358875c4 --- /dev/null +++ b/crates/api/src/parser/definition/consts.rs @@ -0,0 +1,1663 @@ +use std::borrow::Cow; + +use crate::{parser::function_set::FunctionSet, Atom, Prefix, Term}; + +use super::Definition; + +pub(in crate::parser) const ONE: Definition = Definition::Value(1.0); + +pub(in crate::parser) const PARTS_PER_THOUSAND: Definition = Definition::ValueTerms { + value: 1_f64, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::TheNumberTenForArbitraryPowersStar), + exponent: Some(-3), + annotation: None, + }]), +}; + +pub(in crate::parser) const PARTS_PER_MILLION: Definition = Definition::ValueTerms { + value: 1_f64, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::TheNumberTenForArbitraryPowersStar), + exponent: Some(-6), + annotation: None, + }]), +}; + +pub(in crate::parser) const PARTS_PER_BILLION: Definition = Definition::ValueTerms { + value: 1_f64, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::TheNumberTenForArbitraryPowersStar), + exponent: Some(-9), + annotation: None, + }]), +}; + +pub(in crate::parser) const PARTS_PER_TRILLION: Definition = Definition::ValueTerms { + value: 1_f64, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::TheNumberTenForArbitraryPowersStar), + exponent: Some(-12), + annotation: None, + }]), +}; + +pub(in crate::parser) const MOLE: Definition = Definition::ValueTerms { + value: 6.022_136_7_f64, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::TheNumberTenForArbitraryPowersStar), + exponent: Some(23), + annotation: None, + }]), +}; + +pub(in crate::parser) const STERADIAN: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Radian), + exponent: Some(2), + annotation: None, + }]), +}; + +pub(in crate::parser) const HERTZ: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Second), + exponent: Some(-1), + annotation: None, + }]), +}; + +pub(in crate::parser) const SIEMENS: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Ohm), + exponent: Some(-1), + annotation: None, + }]), +}; + +pub(in crate::parser) const DEGREE_CELSIUS: Definition = Definition::ValueTermsSpecial { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Kelvin), + exponent: None, + annotation: None, + }]), + function_set: FunctionSet { + convert_from: |value: f64| value - 273.15, + convert_to: |value: f64| value + 273.15, + }, +}; + +pub(in crate::parser) const BECQUEREL: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Second), + exponent: Some(-1), + annotation: None, + }]), +}; + +pub(in crate::parser) const GON: Definition = Definition::ValueTerms { + value: 0.9, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Degree), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const LITER: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Deci), + atom: Some(Atom::Meter), + exponent: Some(3), + annotation: None, + }]), +}; + +pub(in crate::parser) const ARE: Definition = Definition::ValueTerms { + value: 100.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Meter), + exponent: Some(2), + annotation: None, + }]), +}; + +pub(in crate::parser) const MINUTE: Definition = Definition::ValueTerms { + value: 60.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Second), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const HOUR: Definition = Definition::ValueTerms { + value: 60.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Minute), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const DAY: Definition = Definition::ValueTerms { + value: 24.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Hour), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const TROPICAL_YEAR: Definition = Definition::ValueTerms { + value: 365.242_19, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Day), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const MEAN_JULIAN_YEAR: Definition = Definition::ValueTerms { + value: 365.25, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Day), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const MEAN_GREGORIAN_YEAR: Definition = Definition::ValueTerms { + value: 365.2425, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Day), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const YEAR: Definition = MEAN_JULIAN_YEAR; + +pub(in crate::parser) const WEEK: Definition = Definition::ValueTerms { + value: 7.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Day), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const SYNODAL_MONTH: Definition = Definition::ValueTerms { + value: 29.530_59, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Day), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const MONTH: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::MeanJulianMonth), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const TONNE: Definition = Definition::ValueTerms { + value: 1000.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Kilo), + atom: Some(Atom::Gram), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const BAR: Definition = Definition::ValueTerms { + value: 100_000.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Pascal), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const UNIFIED_ATOMIC_MASS_UNIT: Definition = Definition::ValueTerms { + value: 0.000_000_000_000_000_000_000_001_660_540_2, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Gram), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const ASTRONOMIC_UNIT: Definition = Definition::ValueTerms { + value: 149_597.870_691, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Mega), + atom: Some(Atom::Meter), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const PARSEC: Definition = Definition::ValueTerms { + value: 30_856_780_000_000_000.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Meter), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const ELEMENTARY_CHARGE: Definition = Definition::ValueTerms { + value: 0.000_000_000_000_000_000_160_217_733, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Coulomb), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const ELECTRON_MASS: Definition = Definition::ValueTerms { + value: 0.000_000_000_000_000_000_000_000_000_910_938_97, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Gram), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const PROTON_MASS: Definition = Definition::ValueTerms { + value: 0.000_000_000_000_000_000_000_001_672_623_1, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Gram), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const STANDARD_ATMOSPHERE: Definition = Definition::ValueTerms { + value: 101_325.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Pascal), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const KAYSER: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Centi), + atom: Some(Atom::Meter), + exponent: Some(-1), + annotation: None, + }]), +}; + +pub(in crate::parser) const BIOT: Definition = Definition::ValueTerms { + value: 10.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Ampere), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const MAXWELL: Definition = Definition::ValueTerms { + value: 0.000_000_01, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Weber), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const GAUSS: Definition = Definition::ValueTerms { + value: 0.000_1, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Tesla), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const PHOT: Definition = Definition::ValueTerms { + value: 0.000_1, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Lux), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const CURIE: Definition = Definition::ValueTerms { + value: 37_000_000_000.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Becquerel), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const INCH_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 2.54, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Centi), + atom: Some(Atom::Meter), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const FOOT_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 12.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::InchInternational), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const YARD_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 3.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootInternational), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const MILE_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 5280.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootInternational), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const FATHOM_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 6.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootInternational), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const NAUTICAL_MILE_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 1852.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Meter), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const SQUARE_INCH_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::InchInternational), + exponent: Some(2), + annotation: None, + }]), +}; + +pub(in crate::parser) const SQUARE_FOOT_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootInternational), + exponent: Some(2), + annotation: None, + }]), +}; + +pub(in crate::parser) const SQUARE_YARD_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::YardInternational), + exponent: Some(2), + annotation: None, + }]), +}; + +pub(in crate::parser) const CUBIC_INCH_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::InchInternational), + exponent: Some(3), + annotation: None, + }]), +}; + +pub(in crate::parser) const CUBIC_FOOT_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootInternational), + exponent: Some(3), + annotation: None, + }]), +}; + +pub(in crate::parser) const CUBIC_YARD_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::YardInternational), + exponent: Some(3), + annotation: None, + }]), +}; + +pub(in crate::parser) const BOARD_FOOT_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 144.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::InchInternational), + exponent: Some(3), + annotation: None, + }]), +}; + +pub(in crate::parser) const CORD_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 128.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootInternational), + exponent: Some(3), + annotation: None, + }]), +}; + +pub(in crate::parser) const MIL_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 0.001, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::InchInternational), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const HAND_INTERNATIONAL: Definition = Definition::ValueTerms { + value: 4.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::InchInternational), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const YARD_US: Definition = Definition::ValueTerms { + value: 3.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootUS), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const ROD_US: Definition = Definition::ValueTerms { + value: 16.5, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootUS), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const GUNTERS_CHAIN_US: Definition = Definition::ValueTerms { + value: 4.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::RodUS), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const RAMDENS_CHAIN_US: Definition = Definition::ValueTerms { + value: 100.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootUS), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const FATHOM_US: Definition = Definition::ValueTerms { + value: 6.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootUS), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const FURLONG_US: Definition = Definition::ValueTerms { + value: 40.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::RodUS), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const MILE_US: Definition = Definition::ValueTerms { + value: 8.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FurlongUS), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const ACRE_US: Definition = Definition::ValueTerms { + value: 160.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::RodUS), + exponent: Some(2), + annotation: None, + }]), +}; + +pub(in crate::parser) const SQUARE_ROD_US: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::RodUS), + exponent: Some(2), + annotation: None, + }]), +}; + +pub(in crate::parser) const SQUARE_MILE_US: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::MileUS), + exponent: Some(2), + annotation: None, + }]), +}; + +pub(in crate::parser) const SECTION: Definition = SQUARE_MILE_US; + +pub(in crate::parser) const TOWNSHIP: Definition = Definition::ValueTerms { + value: 36.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Section), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const MIL_US: Definition = Definition::ValueTerms { + value: 0.001, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::InchUS), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const INCH_BRITISH: Definition = Definition::ValueTerms { + value: 2.539998, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Centi), + atom: Some(Atom::Meter), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const FOOT_BRITISH: Definition = Definition::ValueTerms { + value: 12.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::InchBritish), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const ROD_BRITISH: Definition = Definition::ValueTerms { + value: 16.5, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootBritish), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const GUNTERS_CHAIN_BRITISH: Definition = Definition::ValueTerms { + value: 4.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::RodBritish), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const FATHOM_BRITISH: Definition = Definition::ValueTerms { + value: 6.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootBritish), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const PACE_BRITISH: Definition = Definition::ValueTerms { + value: 2.5, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootBritish), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const YARD_BRITISH: Definition = Definition::ValueTerms { + value: 3.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootBritish), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const MILE_BRITISH: Definition = Definition::ValueTerms { + value: 5280.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootBritish), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const NAUTICLE_MILE_BRITISH: Definition = Definition::ValueTerms { + value: 6080.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootBritish), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const ACRE_BRITISH: Definition = Definition::ValueTerms { + value: 4840.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::YardBritish), + exponent: Some(2), + annotation: None, + }]), +}; + +pub(in crate::parser) const QUEEN_ANNES_WINE_GALLON_US: Definition = Definition::ValueTerms { + value: 231.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::InchInternational), + exponent: Some(3), + annotation: None, + }]), +}; + +pub(in crate::parser) const BARREL_US: Definition = Definition::ValueTerms { + value: 42.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::QueenAnnesWineGallonUS), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const CORD_US: Definition = Definition::ValueTerms { + value: 128.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::FootInternational), + exponent: Some(3), + annotation: None, + }]), +}; + +pub(in crate::parser) const BUSHEL_US: Definition = Definition::ValueTerms { + value: 2150.42, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::InchInternational), + exponent: Some(3), + annotation: None, + }]), +}; + +pub(in crate::parser) const CUP_US: Definition = Definition::ValueTerms { + value: 16.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::TablespoonUS), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const METRIC_FLUID_OUNCE: Definition = Definition::ValueTerms { + value: 30.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Milli), + atom: Some(Atom::Liter), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const METRIC_CUP: Definition = Definition::ValueTerms { + value: 240.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Milli), + atom: Some(Atom::Liter), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const METRIC_TEASPOON: Definition = Definition::ValueTerms { + value: 5.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Milli), + atom: Some(Atom::Liter), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const METRIC_TABLESPOON: Definition = Definition::ValueTerms { + value: 15.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Milli), + atom: Some(Atom::Liter), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const GALLON_BRITISH: Definition = Definition::ValueTerms { + value: 4.54609, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Liter), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const PECK_BRITISH: Definition = Definition::ValueTerms { + value: 2.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::GallonBritish), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const BUSHEL_BRITISH: Definition = Definition::ValueTerms { + value: 4.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::PeckBritish), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const GRAIN: Definition = Definition::ValueTerms { + value: 64.798_91, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Milli), + atom: Some(Atom::Gram), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const POUND_AVOIRDUPOIS: Definition = Definition::ValueTerms { + value: 7000.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Grain), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const SHORT_HUNDREDWEIGHT_AVOIRDUPOIS: Definition = + Definition::ValueTerms { + value: 100.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::PoundAvoirdupois), + exponent: None, + annotation: None, + }]), + }; + +pub(in crate::parser) const LONG_HUNDREDWEIGHT_AVOIRDUPOIS: Definition = + Definition::ValueTerms { + value: 112.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::PoundAvoirdupois), + exponent: None, + annotation: None, + }]), + }; + +pub(in crate::parser) const SHORT_TON_AVOIRDUPOIS: Definition = Definition::ValueTerms { + value: 20.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::ShortHundredweightAvoirdupois), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const LONG_TON_AVOIRDUPOIS: Definition = Definition::ValueTerms { + value: 20.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::LongHunderdweightAvoirdupois), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const STONE_AVOIRDUPOIS: Definition = Definition::ValueTerms { + value: 14.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::PoundAvoirdupois), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const PENNYWEIGHT_TROY: Definition = Definition::ValueTerms { + value: 24.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Grain), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const OUNCE_TROY: Definition = Definition::ValueTerms { + value: 20.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::PennyweightTroy), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const POUND_TROY: Definition = Definition::ValueTerms { + value: 12.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::OunceTroy), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const SCUPLE_APOTHECARIES: Definition = Definition::ValueTerms { + value: 20.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Grain), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const DRAM_APOTHECARIES: Definition = Definition::ValueTerms { + value: 3.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::ScrupleApothecaries), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const OUNCE_APOTHECARIES: Definition = Definition::ValueTerms { + value: 8.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::DramApothecaries), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const POUND_APOTHECARIES: Definition = Definition::ValueTerms { + value: 12.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::OunceApothecaries), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const METRIC_OUNCE: Definition = Definition::ValueTerms { + value: 28.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Gram), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const PICA: Definition = Definition::ValueTerms { + value: 12.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Point), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const PRINTERS_POINT: Definition = Definition::ValueTerms { + value: 0.013_837, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::InchInternational), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const PRINTERS_PICA: Definition = Definition::ValueTerms { + value: 12.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::PrintersPoint), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const PIED: Definition = Definition::ValueTerms { + value: 32.48, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Centi), + atom: Some(Atom::Meter), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const CICERO: Definition = Definition::ValueTerms { + value: 12.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Didot), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const CALORIE_AT_15C: Definition = Definition::ValueTerms { + value: 4.1858, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Joule), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const CALORIE_AT_20C: Definition = Definition::ValueTerms { + value: 4.1819, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Joule), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const MEAN_CALORIE: Definition = Definition::ValueTerms { + value: 4.190_02, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Joule), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const INTERNATIONAL_TABLE_CALORIE: Definition = Definition::ValueTerms { + value: 4.1868, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Joule), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const THERMOCHEMICAL_CALORIE: Definition = Definition::ValueTerms { + value: 4.184, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Joule), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const CALORIE: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::ThermochemicalCalorie), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const NUTRITION_LABEL_CALORIES: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Kilo), + atom: Some(Atom::ThermochemicalCalorie), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const BRITISH_THERMAL_UNIT_AT_39F: Definition = Definition::ValueTerms { + value: 1.059_67, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Kilo), + atom: Some(Atom::Joule), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const BRITISH_THERMAL_UNIT_AT_59F: Definition = Definition::ValueTerms { + value: 1.0548, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Kilo), + atom: Some(Atom::Joule), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const BRITISH_THERMAL_UNIT_AT_60F: Definition = Definition::ValueTerms { + value: 1.05468, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Kilo), + atom: Some(Atom::Joule), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const MEAN_BRITISH_THERMAL_UNIT: Definition = Definition::ValueTerms { + value: 1.055_87, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Kilo), + atom: Some(Atom::Joule), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const INTERNATIONAL_TABLE_BRITISH_THERMAL_UNIT: Definition = + Definition::ValueTerms { + value: 1.05505585262, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Kilo), + atom: Some(Atom::Joule), + exponent: None, + annotation: None, + }]), + }; + +pub(in crate::parser) const THERMOCHEMICAL_BRITISH_THERMAL_UNIT: Definition = + Definition::ValueTerms { + value: 1.054_35, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Kilo), + atom: Some(Atom::Joule), + exponent: None, + annotation: None, + }]), + }; + +pub(in crate::parser) const BRITISH_THERMAL_UNIT: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::ThermochemicalBritishThermalUnit), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const METER_OF_WATER_COLUMN: Definition = Definition::ValueTerms { + value: 9.806_65, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Kilo), + atom: Some(Atom::Pascal), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const METER_OF_MERCURY_COLUMN: Definition = Definition::ValueTerms { + value: 133.322, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Kilo), + atom: Some(Atom::Pascal), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const PRISM_DIOPTER: Definition = Definition::ValueTermsSpecial { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Radian), + exponent: None, + annotation: None, + }]), + function_set: FunctionSet { + convert_from: |value: f64| (value / 100.0).atan(), + convert_to: |value: f64| value.tan() * 100.0, + }, +}; + +pub(in crate::parser) const PERCENT_OF_SLOPE: Definition = Definition::ValueTermsSpecial { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Degree), + exponent: None, + annotation: None, + }]), + function_set: FunctionSet { + convert_from: |value: f64| (value / 100.0).atan(), + convert_to: |value: f64| value.tan() * 100.0, + }, +}; + +pub(in crate::parser) const HOMEOPATHIC_POTENCY_OF_DECIMAL_SERIES_RETIRED: Definition = + Definition::ValueSpecial { + value: 1f64, + function_set: FunctionSet { + convert_from: |value: f64| -value.log10(), + convert_to: |value: f64| 10_f64.powf(-value), + }, + }; + +pub(in crate::parser) const HOMEOPATHIC_POTENCY_OF_CENTESIMAL_SERIES_RETIRED: Definition = + Definition::ValueSpecial { + value: 1f64, + function_set: FunctionSet { + convert_from: |value: f64| -value.ln() / 100_f64.ln(), + convert_to: |value: f64| 100_f64.powf(-value), + }, + }; + +pub(in crate::parser) const HOMEOPATHIC_POTENCY_OF_MILLESIMAL_SERIES_RETIRED: Definition = + Definition::ValueSpecial { + value: 1f64, + function_set: FunctionSet { + convert_from: |value: f64| -value.ln() / 1_000_f64.ln(), + convert_to: |value: f64| 1_000_f64.powf(-value), + }, + }; + +pub(in crate::parser) const HOMEOPATHIC_POTENCY_OF_QUINTMILLESIMAL_SERIES_RETIRED: Definition = + Definition::ValueSpecial { + value: 1f64, + function_set: FunctionSet { + convert_from: |value: f64| -value.ln() / 50_000_f64.ln(), + convert_to: |value: f64| 50_000_f64.powf(-value), + }, + }; + +pub(in crate::parser) const EQUIVALENTS: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Mole), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const OSMOLE: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Mole), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const INTERNATIONAL_UNIT_SECONDARY: Definition = + Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::InternationalUnit), + exponent: None, + annotation: None, + }]), + }; + +pub(in crate::parser) const NEPER: Definition = Definition::ValueSpecial { + value: 1.0, + function_set: FunctionSet { + convert_from: f64::ln, + convert_to: f64::exp, + }, +}; + +pub(in crate::parser) const BEL: Definition = Definition::ValueSpecial { + value: 1.0, + function_set: FunctionSet { + convert_from: f64::log10, + convert_to: |value: f64| 10_f64.powf(value), + }, +}; + +pub(in crate::parser) const BEL_VOLT: Definition = Definition::ValueTermsSpecial { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Volt), + exponent: None, + annotation: None, + }]), + function_set: FunctionSet { + convert_from: |value: f64| 2.0 * value.log10(), + convert_to: |value: f64| 10_f64.powf(value / 2.0), + }, +}; + +pub(in crate::parser) const BEL_MILLIVOLT: Definition = Definition::ValueTermsSpecial { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Milli), + atom: Some(Atom::Volt), + exponent: None, + annotation: None, + }]), + function_set: FunctionSet { + convert_from: |value: f64| 2.0 * value.log10(), + convert_to: |value: f64| 10_f64.powf(value / 2.0), + }, +}; + +pub(in crate::parser) const BEL_MICROVOLT: Definition = Definition::ValueTermsSpecial { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Micro), + atom: Some(Atom::Volt), + exponent: None, + annotation: None, + }]), + function_set: FunctionSet { + convert_from: |value: f64| 2.0 * value.log10(), + convert_to: |value: f64| 10_f64.powf(value / 2.0), + }, +}; + +pub(in crate::parser) const BEL_10_NANOVOLT: Definition = Definition::ValueTermsSpecial { + value: 10.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Nano), + atom: Some(Atom::Volt), + exponent: None, + annotation: None, + }]), + function_set: FunctionSet { + convert_from: |value: f64| 2.0 * value.log10(), + convert_to: |value: f64| 10_f64.powf(value / 2.0), + }, +}; + +pub(in crate::parser) const BEL_WATT: Definition = Definition::ValueTermsSpecial { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Watt), + exponent: None, + annotation: None, + }]), + function_set: FunctionSet { + convert_from: f64::log10, + convert_to: |value: f64| 10_f64.powf(value), + }, +}; + +pub(in crate::parser) const BEL_KILOWATT: Definition = Definition::ValueTermsSpecial { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Kilo), + atom: Some(Atom::Watt), + exponent: None, + annotation: None, + }]), + function_set: FunctionSet { + convert_from: f64::log10, + convert_to: |value: f64| 10_f64.powf(value), + }, +}; + +pub(in crate::parser) const STERE: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Meter), + exponent: Some(3), + annotation: None, + }]), +}; + +pub(in crate::parser) const ANGSTROM: Definition = Definition::ValueTerms { + value: 0.1, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Nano), + atom: Some(Atom::Meter), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const BARN: Definition = Definition::ValueTerms { + value: 100.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Femto), + atom: Some(Atom::Meter), + exponent: Some(2), + annotation: None, + }]), +}; + +pub(in crate::parser) const MHO: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Siemens), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const METRIC_CARAT: Definition = Definition::ValueTerms { + value: 0.2, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Gram), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const SMOOT: Definition = Definition::ValueTerms { + value: 67.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::InchInternational), + exponent: None, + annotation: None, + }]), +}; + +pub(in crate::parser) const BIT_LOGARITHMUS_DUALIS: Definition = Definition::ValueSpecial { + value: 1.0, + function_set: FunctionSet { + convert_from: f64::log2, + convert_to: f64::exp2, + }, +}; + +pub(in crate::parser) const BYTE: Definition = Definition::ValueTerms { + value: 8.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Bit), + exponent: None, + annotation: None, + }]), +}; diff --git a/crates/api/src/parser/terms/mapper/ast_term.rs b/crates/api/src/parser/terms/mapper/ast_term.rs index 0c68800b..c81eed50 100644 --- a/crates/api/src/parser/terms/mapper/ast_term.rs +++ b/crates/api/src/parser/terms/mapper/ast_term.rs @@ -1,4 +1,3 @@ -use num_traits::Inv; use pest::iterators::Pair; use crate::parser::terms::term_parser::Rule; diff --git a/crates/api/src/unit/to_reduced.rs b/crates/api/src/unit/to_reduced.rs index 0d6a85c4..a6df2565 100644 --- a/crates/api/src/unit/to_reduced.rs +++ b/crates/api/src/unit/to_reduced.rs @@ -1,7 +1,3 @@ -use std::borrow::Cow; - -use num_traits::Inv; - use crate::{ as_fraction::AsFraction, parser::{Composable, Composition}, From eb5465f2e319620ba78adab1d08c1451d5457ae3 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 22 Mar 2024 17:26:03 -0700 Subject: [PATCH 45/80] Clippy auto-fixes --- crates/api/src/measurement.rs | 2 +- crates/api/src/parser/definition/consts.rs | 4 ++-- crates/atom_generator/src/generator.rs | 16 ++++++++-------- crates/ffi/src/measurement.rs | 20 ++++++++++---------- crates/ffi/src/unit.rs | 8 ++++---- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/crates/api/src/measurement.rs b/crates/api/src/measurement.rs index c4362ed5..b2482e56 100644 --- a/crates/api/src/measurement.rs +++ b/crates/api/src/measurement.rs @@ -302,7 +302,7 @@ mod tests { let scalar = 123.456; let expression = "kg/[lb_av]"; let unit = crate::unit::custom_ffi::unit_init(core::ffi_string!(expression)); - let unit_for_measurement = crate::unit::custom_ffi::clone_unit(unit) as *mut Unit; + let unit_for_measurement = crate::unit::custom_ffi::clone_unit(unit).cast_mut(); let measurement = measurement_ffi::measurement_rust_ffi_init(scalar, unit_for_measurement); let retrieved_value = measurement_ffi::get_measurement_value(measurement); diff --git a/crates/api/src/parser/definition/consts.rs b/crates/api/src/parser/definition/consts.rs index 358875c4..c3f8ff9e 100644 --- a/crates/api/src/parser/definition/consts.rs +++ b/crates/api/src/parser/definition/consts.rs @@ -730,7 +730,7 @@ pub(in crate::parser) const MIL_US: Definition = Definition::ValueTerms { }; pub(in crate::parser) const INCH_BRITISH: Definition = Definition::ValueTerms { - value: 2.539998, + value: 2.539_998, terms: Cow::Borrowed(&[Term { factor: None, prefix: Some(Prefix::Centi), @@ -1316,7 +1316,7 @@ pub(in crate::parser) const MEAN_BRITISH_THERMAL_UNIT: Definition = Definit pub(in crate::parser) const INTERNATIONAL_TABLE_BRITISH_THERMAL_UNIT: Definition = Definition::ValueTerms { - value: 1.05505585262, + value: 1.055_055_852_62, terms: Cow::Borrowed(&[Term { factor: None, prefix: Some(Prefix::Kilo), diff --git a/crates/atom_generator/src/generator.rs b/crates/atom_generator/src/generator.rs index e42ee007..b9840ea1 100644 --- a/crates/atom_generator/src/generator.rs +++ b/crates/atom_generator/src/generator.rs @@ -6,15 +6,15 @@ //! consuming library or application. //! -pub(self) mod atom; -pub(self) mod classification; -pub(self) mod handlebars; -pub(self) mod property; -pub(self) mod symbol_grammar; + mod atom; + mod classification; + mod handlebars; + mod property; + mod symbol_grammar; use proc_macro2::TokenStream; -pub(self) use self::handlebars::HANDLEBARS; + use self::handlebars::HANDLEBARS; use crate::rust_structs::RustAtomList; use std::{ @@ -24,7 +24,7 @@ use std::{ process::Command, }; -pub(self) const BANNER: &str = + const BANNER: &str = "//----------------------------------------------------------------------------- // DO NOT EDIT THIS FILE! // This is generated by wise_units-atom_generator. @@ -89,7 +89,7 @@ fn write_project_file(file_path: &Path, file_body: &str, do_format: bool) { } } -pub(self) fn pretty_format(token_stream: &TokenStream) -> String { + fn pretty_format(token_stream: &TokenStream) -> String { let token_string = token_stream.to_string(); // Run the output through `prettyplease`. This should catch some syntactical mess-ups. diff --git a/crates/ffi/src/measurement.rs b/crates/ffi/src/measurement.rs index 21dad56e..0eed7421 100644 --- a/crates/ffi/src/measurement.rs +++ b/crates/ffi/src/measurement.rs @@ -43,7 +43,7 @@ pub unsafe extern "C" fn measurement_new( /// #[no_mangle] pub unsafe extern "C" fn measurement_destroy(data: *const Measurement) { - drop(Box::from_raw(data as *mut Measurement)); + drop(Box::from_raw(data.cast_mut())); } /// Essentially checks if the two `Measurement`'s scalar values are equal. @@ -312,7 +312,7 @@ mod tests { let expression = CString::new("m").expect("CString::new failed"); unsafe { let m = measurement_new(value, expression.as_ptr()); - let boxed_m = Box::from_raw(m as *mut Measurement); + let boxed_m = Box::from_raw(m.cast_mut()); assert_relative_eq!(value, boxed_m.value()); assert_ulps_eq!(value, boxed_m.value()); } @@ -345,7 +345,7 @@ mod tests { unsafe { let m = measurement_new(1.0, expression_c.as_ptr()); let unit = measurement_get_unit(m); - let boxed_unit = Box::from_raw(unit as *mut Unit); + let boxed_unit = Box::from_raw(unit.cast_mut()); assert_eq!(expression, boxed_unit.expression()); } } @@ -392,7 +392,7 @@ mod tests { unsafe { let m = measurement_new(value, expression1.as_ptr()); let converted = - Box::from_raw(measurement_convert_to(m, expression2.as_ptr()) as *mut Measurement); + Box::from_raw(measurement_convert_to(m, expression2.as_ptr()).cast_mut()); assert_relative_eq!(converted.value(), expected); assert_ulps_eq!(converted.value(), expected); } @@ -423,7 +423,7 @@ mod tests { unsafe { let m1 = measurement_new(value1, expression1.as_ptr()); let m2 = measurement_new(value2, expression2.as_ptr()); - let result = Box::from_raw(measurement_add(m1, m2) as *mut Measurement); + let result = Box::from_raw(measurement_add(m1, m2).cast_mut()); assert_relative_eq!(result.value(), expected); assert_ulps_eq!(result.value(), expected); } @@ -439,7 +439,7 @@ mod tests { unsafe { let m1 = measurement_new(value1, expression1.as_ptr()); let m2 = measurement_new(value2, expression2.as_ptr()); - let result = Box::from_raw(measurement_sub(m1, m2) as *mut Measurement); + let result = Box::from_raw(measurement_sub(m1, m2).cast_mut()); assert_relative_eq!(result.value(), expected); assert_ulps_eq!(result.value(), expected); } @@ -455,7 +455,7 @@ mod tests { unsafe { let m1 = measurement_new(value1, expression1.as_ptr()); let m2 = measurement_new(value2, expression2.as_ptr()); - let result = Box::from_raw(measurement_mul(m1, m2) as *mut Measurement); + let result = Box::from_raw(measurement_mul(m1, m2).cast_mut()); assert_relative_eq!(result.value(), expected); assert_ulps_eq!(result.value(), expected); } @@ -469,7 +469,7 @@ mod tests { let expected = 204.683_834; unsafe { let m1 = measurement_new(value1, expression.as_ptr()); - let result = Box::from_raw(measurement_mul_scalar(m1, scalar) as *mut Measurement); + let result = Box::from_raw(measurement_mul_scalar(m1, scalar).cast_mut()); assert_relative_eq!(result.value(), expected); assert_ulps_eq!(result.value(), expected); } @@ -485,7 +485,7 @@ mod tests { unsafe { let m1 = measurement_new(value1, expression1.as_ptr()); let m2 = measurement_new(value2, expression2.as_ptr()); - let result = Box::from_raw(measurement_div(m1, m2) as *mut Measurement); + let result = Box::from_raw(measurement_div(m1, m2).cast_mut()); assert_relative_eq!(result.value(), expected); assert_ulps_eq!(result.value(), expected); } @@ -499,7 +499,7 @@ mod tests { let expected = 8.792_439_378_238_342; unsafe { let m1 = measurement_new(value1, expression.as_ptr()); - let result = Box::from_raw(measurement_div_scalar(m1, scalar) as *mut Measurement); + let result = Box::from_raw(measurement_div_scalar(m1, scalar).cast_mut()); assert_relative_eq!(result.value(), expected); assert_ulps_eq!(result.value(), expected); } diff --git a/crates/ffi/src/unit.rs b/crates/ffi/src/unit.rs index eb8e2e16..b879281b 100644 --- a/crates/ffi/src/unit.rs +++ b/crates/ffi/src/unit.rs @@ -48,7 +48,7 @@ pub unsafe extern "C" fn unit_new(expression: *const c_char) -> *const Unit { /// #[no_mangle] pub unsafe extern "C" fn unit_destroy(data: *const Unit) { - drop(Box::from_raw(data as *mut Unit)); + drop(Box::from_raw(data.cast_mut())); } /// Essentially checks if the two `Unit`'s scalar values are equal. @@ -274,7 +274,7 @@ mod tests { let expression_c = CString::new(expression).expect("CString::new failed"); unsafe { let u = unit_new(expression_c.as_ptr()); - let boxed_u = Box::from_raw(u as *mut Unit); + let boxed_u = Box::from_raw(u.cast_mut()); assert_eq!(expression, boxed_u.expression()); } } @@ -417,7 +417,7 @@ mod tests { let u = unit_new(base_expression.as_ptr()); let d = unit_new(divisor_expression.as_ptr()); let result = unit_div(u, d); - assert_eq!(expected, Box::from_raw(result as *mut Unit).expression()); + assert_eq!(expected, Box::from_raw(result.cast_mut()).expression()); } } @@ -429,7 +429,7 @@ mod tests { unsafe { let u = unit_new(base_expression.as_ptr()); let m = unit_new(multiplier_expression.as_ptr()); - let result = Box::from_raw(unit_mul(u, m) as *mut Unit); + let result = Box::from_raw(unit_mul(u, m).cast_mut()); assert_eq!(expected, result.expression()); } } From 118248f9a1501515e4ca231c586bf131385dd8ce Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 25 Mar 2024 14:02:45 -0700 Subject: [PATCH 46/80] PLCC-299 Move Atom to root --- crates/api/src/{parser => }/atom.rs | 16 +- crates/api/src/{parser => atom}/atom_test.rs | 6 +- .../api/src/{parser => }/atom/composable.rs | 0 crates/api/src/{parser => atom}/definition.rs | 4 +- .../src/{parser => atom}/definition/consts.rs | 323 +++++++++--------- crates/api/src/{parser => }/atom/display.rs | 0 .../api/src/{parser => atom}/function_set.rs | 0 crates/api/src/{parser => }/atom/hash.rs | 0 .../api/src/{parser => }/atom/partial_eq.rs | 0 crates/api/src/{parser => }/atom/reducible.rs | 0 crates/api/src/lib.rs | 6 +- crates/api/src/macros.rs | 5 +- crates/api/src/measurement.rs | 12 +- crates/api/src/parser.rs | 12 +- crates/api/src/unit/term_reducing.rs | 4 +- crates/atom_generator/src/generator.rs | 18 +- crates/atom_generator/src/generator/atom.rs | 10 +- .../atom_generator/src/generator/property.rs | 2 +- 18 files changed, 215 insertions(+), 203 deletions(-) rename crates/api/src/{parser => }/atom.rs (99%) rename crates/api/src/{parser => atom}/atom_test.rs (99%) rename crates/api/src/{parser => }/atom/composable.rs (100%) rename crates/api/src/{parser => atom}/definition.rs (98%) rename crates/api/src/{parser => atom}/definition/consts.rs (73%) rename crates/api/src/{parser => }/atom/display.rs (100%) rename crates/api/src/{parser => atom}/function_set.rs (100%) rename crates/api/src/{parser => }/atom/hash.rs (100%) rename crates/api/src/{parser => }/atom/partial_eq.rs (100%) rename crates/api/src/{parser => }/atom/reducible.rs (100%) diff --git a/crates/api/src/parser/atom.rs b/crates/api/src/atom.rs similarity index 99% rename from crates/api/src/parser/atom.rs rename to crates/api/src/atom.rs index 5542f0e3..2eabf985 100644 --- a/crates/api/src/parser/atom.rs +++ b/crates/api/src/atom.rs @@ -4,20 +4,28 @@ //----------------------------------------------------------------------------- mod composable; +mod definition; mod display; +mod function_set; mod hash; mod partial_eq; mod reducible; + +#[cfg(test)] +mod atom_test; + use crate::{ is_compatible_with::DefaultCompatibility, - parser::{ - definition::Definition, function_set::FunctionSet, Classification, Property, UcumSymbol, - }, + parser::{Classification, Property, UcumSymbol}, reducible::Reducible, UcumUnit, Unit, }; -use super::definition::consts::*; +#[allow(clippy::wildcard_imports)] +use self::{ + definition::{consts::*, Definition}, + function_set::FunctionSet, +}; #[derive(Clone, Copy, Debug, Eq, PartialOrd, Ord)] pub enum Atom { diff --git a/crates/api/src/parser/atom_test.rs b/crates/api/src/atom/atom_test.rs similarity index 99% rename from crates/api/src/parser/atom_test.rs rename to crates/api/src/atom/atom_test.rs index 180b055d..8bb7690a 100644 --- a/crates/api/src/parser/atom_test.rs +++ b/crates/api/src/atom/atom_test.rs @@ -5,11 +5,9 @@ use approx::{assert_relative_eq, assert_ulps_eq}; use crate::{ - parser::{ - term::UNITY_ARRAY, Atom, Classification, Composable, Composition, Dimension, Prefix, - UcumSymbol, - }, + parser::{term::UNITY_ARRAY, Classification, Composition, Dimension, Prefix, UcumSymbol}, ucum_unit::UcumUnit, + Atom, Composable, }; macro_rules! validate_definition { diff --git a/crates/api/src/parser/atom/composable.rs b/crates/api/src/atom/composable.rs similarity index 100% rename from crates/api/src/parser/atom/composable.rs rename to crates/api/src/atom/composable.rs diff --git a/crates/api/src/parser/definition.rs b/crates/api/src/atom/definition.rs similarity index 98% rename from crates/api/src/parser/definition.rs rename to crates/api/src/atom/definition.rs index d9f646fa..135d9506 100644 --- a/crates/api/src/parser/definition.rs +++ b/crates/api/src/atom/definition.rs @@ -8,11 +8,11 @@ use std::{borrow::Cow, str::FromStr}; use num_traits::One; use crate::{ - parser::{function_set::FunctionSet, Term}, + parser::{term, Term}, reducible::Reducible, }; -use super::term; +use super::function_set::FunctionSet; /// A `Definition` is a slimmed-down version of a `Measurement` that is used to /// define `Atom`s in terms of other `Atom`s (ex. an `"[in_i]"` has a diff --git a/crates/api/src/parser/definition/consts.rs b/crates/api/src/atom/definition/consts.rs similarity index 73% rename from crates/api/src/parser/definition/consts.rs rename to crates/api/src/atom/definition/consts.rs index c3f8ff9e..8e735d77 100644 --- a/crates/api/src/parser/definition/consts.rs +++ b/crates/api/src/atom/definition/consts.rs @@ -1,12 +1,12 @@ use std::borrow::Cow; -use crate::{parser::function_set::FunctionSet, Atom, Prefix, Term}; +use crate::{atom::function_set::FunctionSet, Atom, Prefix, Term}; use super::Definition; -pub(in crate::parser) const ONE: Definition = Definition::Value(1.0); +pub(in crate::atom) const ONE: Definition = Definition::Value(1.0); -pub(in crate::parser) const PARTS_PER_THOUSAND: Definition = Definition::ValueTerms { +pub(in crate::atom) const PARTS_PER_THOUSAND: Definition = Definition::ValueTerms { value: 1_f64, terms: Cow::Borrowed(&[Term { factor: None, @@ -17,7 +17,7 @@ pub(in crate::parser) const PARTS_PER_THOUSAND: Definition = Definition::Va }]), }; -pub(in crate::parser) const PARTS_PER_MILLION: Definition = Definition::ValueTerms { +pub(in crate::atom) const PARTS_PER_MILLION: Definition = Definition::ValueTerms { value: 1_f64, terms: Cow::Borrowed(&[Term { factor: None, @@ -28,7 +28,7 @@ pub(in crate::parser) const PARTS_PER_MILLION: Definition = Definition::Val }]), }; -pub(in crate::parser) const PARTS_PER_BILLION: Definition = Definition::ValueTerms { +pub(in crate::atom) const PARTS_PER_BILLION: Definition = Definition::ValueTerms { value: 1_f64, terms: Cow::Borrowed(&[Term { factor: None, @@ -39,7 +39,7 @@ pub(in crate::parser) const PARTS_PER_BILLION: Definition = Definition::Val }]), }; -pub(in crate::parser) const PARTS_PER_TRILLION: Definition = Definition::ValueTerms { +pub(in crate::atom) const PARTS_PER_TRILLION: Definition = Definition::ValueTerms { value: 1_f64, terms: Cow::Borrowed(&[Term { factor: None, @@ -50,7 +50,7 @@ pub(in crate::parser) const PARTS_PER_TRILLION: Definition = Definition::Va }]), }; -pub(in crate::parser) const MOLE: Definition = Definition::ValueTerms { +pub(in crate::atom) const MOLE: Definition = Definition::ValueTerms { value: 6.022_136_7_f64, terms: Cow::Borrowed(&[Term { factor: None, @@ -61,7 +61,7 @@ pub(in crate::parser) const MOLE: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const STERADIAN: Definition = Definition::ValueTerms { +pub(in crate::atom) const STERADIAN: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -72,7 +72,7 @@ pub(in crate::parser) const STERADIAN: Definition = Definition::ValueTerms }]), }; -pub(in crate::parser) const HERTZ: Definition = Definition::ValueTerms { +pub(in crate::atom) const HERTZ: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -83,7 +83,7 @@ pub(in crate::parser) const HERTZ: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const SIEMENS: Definition = Definition::ValueTerms { +pub(in crate::atom) const SIEMENS: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -94,7 +94,7 @@ pub(in crate::parser) const SIEMENS: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const DEGREE_CELSIUS: Definition = Definition::ValueTermsSpecial { +pub(in crate::atom) const DEGREE_CELSIUS: Definition = Definition::ValueTermsSpecial { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -109,7 +109,7 @@ pub(in crate::parser) const DEGREE_CELSIUS: Definition = Definition::ValueT }, }; -pub(in crate::parser) const BECQUEREL: Definition = Definition::ValueTerms { +pub(in crate::atom) const BECQUEREL: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -120,7 +120,7 @@ pub(in crate::parser) const BECQUEREL: Definition = Definition::ValueTerms }]), }; -pub(in crate::parser) const GON: Definition = Definition::ValueTerms { +pub(in crate::atom) const GON: Definition = Definition::ValueTerms { value: 0.9, terms: Cow::Borrowed(&[Term { factor: None, @@ -131,7 +131,7 @@ pub(in crate::parser) const GON: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const LITER: Definition = Definition::ValueTerms { +pub(in crate::atom) const LITER: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -142,7 +142,7 @@ pub(in crate::parser) const LITER: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const ARE: Definition = Definition::ValueTerms { +pub(in crate::atom) const ARE: Definition = Definition::ValueTerms { value: 100.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -153,7 +153,7 @@ pub(in crate::parser) const ARE: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const MINUTE: Definition = Definition::ValueTerms { +pub(in crate::atom) const MINUTE: Definition = Definition::ValueTerms { value: 60.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -164,7 +164,7 @@ pub(in crate::parser) const MINUTE: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const HOUR: Definition = Definition::ValueTerms { +pub(in crate::atom) const HOUR: Definition = Definition::ValueTerms { value: 60.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -175,7 +175,7 @@ pub(in crate::parser) const HOUR: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const DAY: Definition = Definition::ValueTerms { +pub(in crate::atom) const DAY: Definition = Definition::ValueTerms { value: 24.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -186,7 +186,7 @@ pub(in crate::parser) const DAY: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const TROPICAL_YEAR: Definition = Definition::ValueTerms { +pub(in crate::atom) const TROPICAL_YEAR: Definition = Definition::ValueTerms { value: 365.242_19, terms: Cow::Borrowed(&[Term { factor: None, @@ -197,7 +197,7 @@ pub(in crate::parser) const TROPICAL_YEAR: Definition = Definition::ValueTe }]), }; -pub(in crate::parser) const MEAN_JULIAN_YEAR: Definition = Definition::ValueTerms { +pub(in crate::atom) const MEAN_JULIAN_YEAR: Definition = Definition::ValueTerms { value: 365.25, terms: Cow::Borrowed(&[Term { factor: None, @@ -208,7 +208,7 @@ pub(in crate::parser) const MEAN_JULIAN_YEAR: Definition = Definition::Valu }]), }; -pub(in crate::parser) const MEAN_GREGORIAN_YEAR: Definition = Definition::ValueTerms { +pub(in crate::atom) const MEAN_GREGORIAN_YEAR: Definition = Definition::ValueTerms { value: 365.2425, terms: Cow::Borrowed(&[Term { factor: None, @@ -219,9 +219,9 @@ pub(in crate::parser) const MEAN_GREGORIAN_YEAR: Definition = Definition::V }]), }; -pub(in crate::parser) const YEAR: Definition = MEAN_JULIAN_YEAR; +pub(in crate::atom) const YEAR: Definition = MEAN_JULIAN_YEAR; -pub(in crate::parser) const WEEK: Definition = Definition::ValueTerms { +pub(in crate::atom) const WEEK: Definition = Definition::ValueTerms { value: 7.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -232,7 +232,7 @@ pub(in crate::parser) const WEEK: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const SYNODAL_MONTH: Definition = Definition::ValueTerms { +pub(in crate::atom) const SYNODAL_MONTH: Definition = Definition::ValueTerms { value: 29.530_59, terms: Cow::Borrowed(&[Term { factor: None, @@ -243,7 +243,7 @@ pub(in crate::parser) const SYNODAL_MONTH: Definition = Definition::ValueTe }]), }; -pub(in crate::parser) const MONTH: Definition = Definition::ValueTerms { +pub(in crate::atom) const MONTH: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -254,7 +254,7 @@ pub(in crate::parser) const MONTH: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const TONNE: Definition = Definition::ValueTerms { +pub(in crate::atom) const TONNE: Definition = Definition::ValueTerms { value: 1000.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -265,7 +265,7 @@ pub(in crate::parser) const TONNE: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const BAR: Definition = Definition::ValueTerms { +pub(in crate::atom) const BAR: Definition = Definition::ValueTerms { value: 100_000.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -276,7 +276,7 @@ pub(in crate::parser) const BAR: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const UNIFIED_ATOMIC_MASS_UNIT: Definition = Definition::ValueTerms { +pub(in crate::atom) const UNIFIED_ATOMIC_MASS_UNIT: Definition = Definition::ValueTerms { value: 0.000_000_000_000_000_000_000_001_660_540_2, terms: Cow::Borrowed(&[Term { factor: None, @@ -287,7 +287,7 @@ pub(in crate::parser) const UNIFIED_ATOMIC_MASS_UNIT: Definition = Definiti }]), }; -pub(in crate::parser) const ASTRONOMIC_UNIT: Definition = Definition::ValueTerms { +pub(in crate::atom) const ASTRONOMIC_UNIT: Definition = Definition::ValueTerms { value: 149_597.870_691, terms: Cow::Borrowed(&[Term { factor: None, @@ -298,7 +298,7 @@ pub(in crate::parser) const ASTRONOMIC_UNIT: Definition = Definition::Value }]), }; -pub(in crate::parser) const PARSEC: Definition = Definition::ValueTerms { +pub(in crate::atom) const PARSEC: Definition = Definition::ValueTerms { value: 30_856_780_000_000_000.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -309,7 +309,7 @@ pub(in crate::parser) const PARSEC: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const ELEMENTARY_CHARGE: Definition = Definition::ValueTerms { +pub(in crate::atom) const ELEMENTARY_CHARGE: Definition = Definition::ValueTerms { value: 0.000_000_000_000_000_000_160_217_733, terms: Cow::Borrowed(&[Term { factor: None, @@ -320,7 +320,7 @@ pub(in crate::parser) const ELEMENTARY_CHARGE: Definition = Definition::Val }]), }; -pub(in crate::parser) const ELECTRON_MASS: Definition = Definition::ValueTerms { +pub(in crate::atom) const ELECTRON_MASS: Definition = Definition::ValueTerms { value: 0.000_000_000_000_000_000_000_000_000_910_938_97, terms: Cow::Borrowed(&[Term { factor: None, @@ -331,7 +331,7 @@ pub(in crate::parser) const ELECTRON_MASS: Definition = Definition::ValueTe }]), }; -pub(in crate::parser) const PROTON_MASS: Definition = Definition::ValueTerms { +pub(in crate::atom) const PROTON_MASS: Definition = Definition::ValueTerms { value: 0.000_000_000_000_000_000_000_001_672_623_1, terms: Cow::Borrowed(&[Term { factor: None, @@ -342,7 +342,7 @@ pub(in crate::parser) const PROTON_MASS: Definition = Definition::ValueTerm }]), }; -pub(in crate::parser) const STANDARD_ATMOSPHERE: Definition = Definition::ValueTerms { +pub(in crate::atom) const STANDARD_ATMOSPHERE: Definition = Definition::ValueTerms { value: 101_325.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -353,7 +353,7 @@ pub(in crate::parser) const STANDARD_ATMOSPHERE: Definition = Definition::V }]), }; -pub(in crate::parser) const KAYSER: Definition = Definition::ValueTerms { +pub(in crate::atom) const KAYSER: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -364,7 +364,7 @@ pub(in crate::parser) const KAYSER: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const BIOT: Definition = Definition::ValueTerms { +pub(in crate::atom) const BIOT: Definition = Definition::ValueTerms { value: 10.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -375,7 +375,7 @@ pub(in crate::parser) const BIOT: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const MAXWELL: Definition = Definition::ValueTerms { +pub(in crate::atom) const MAXWELL: Definition = Definition::ValueTerms { value: 0.000_000_01, terms: Cow::Borrowed(&[Term { factor: None, @@ -386,7 +386,7 @@ pub(in crate::parser) const MAXWELL: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const GAUSS: Definition = Definition::ValueTerms { +pub(in crate::atom) const GAUSS: Definition = Definition::ValueTerms { value: 0.000_1, terms: Cow::Borrowed(&[Term { factor: None, @@ -397,7 +397,7 @@ pub(in crate::parser) const GAUSS: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const PHOT: Definition = Definition::ValueTerms { +pub(in crate::atom) const PHOT: Definition = Definition::ValueTerms { value: 0.000_1, terms: Cow::Borrowed(&[Term { factor: None, @@ -408,7 +408,7 @@ pub(in crate::parser) const PHOT: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const CURIE: Definition = Definition::ValueTerms { +pub(in crate::atom) const CURIE: Definition = Definition::ValueTerms { value: 37_000_000_000.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -419,7 +419,7 @@ pub(in crate::parser) const CURIE: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const INCH_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const INCH_INTERNATIONAL: Definition = Definition::ValueTerms { value: 2.54, terms: Cow::Borrowed(&[Term { factor: None, @@ -430,7 +430,7 @@ pub(in crate::parser) const INCH_INTERNATIONAL: Definition = Definition::Va }]), }; -pub(in crate::parser) const FOOT_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const FOOT_INTERNATIONAL: Definition = Definition::ValueTerms { value: 12.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -441,7 +441,7 @@ pub(in crate::parser) const FOOT_INTERNATIONAL: Definition = Definition::Va }]), }; -pub(in crate::parser) const YARD_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const YARD_INTERNATIONAL: Definition = Definition::ValueTerms { value: 3.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -452,7 +452,7 @@ pub(in crate::parser) const YARD_INTERNATIONAL: Definition = Definition::Va }]), }; -pub(in crate::parser) const MILE_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const MILE_INTERNATIONAL: Definition = Definition::ValueTerms { value: 5280.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -463,7 +463,7 @@ pub(in crate::parser) const MILE_INTERNATIONAL: Definition = Definition::Va }]), }; -pub(in crate::parser) const FATHOM_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const FATHOM_INTERNATIONAL: Definition = Definition::ValueTerms { value: 6.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -474,7 +474,7 @@ pub(in crate::parser) const FATHOM_INTERNATIONAL: Definition = Definition:: }]), }; -pub(in crate::parser) const NAUTICAL_MILE_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const NAUTICAL_MILE_INTERNATIONAL: Definition = Definition::ValueTerms { value: 1852.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -485,7 +485,7 @@ pub(in crate::parser) const NAUTICAL_MILE_INTERNATIONAL: Definition = Defin }]), }; -pub(in crate::parser) const SQUARE_INCH_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const SQUARE_INCH_INTERNATIONAL: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -496,7 +496,7 @@ pub(in crate::parser) const SQUARE_INCH_INTERNATIONAL: Definition = Definit }]), }; -pub(in crate::parser) const SQUARE_FOOT_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const SQUARE_FOOT_INTERNATIONAL: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -507,7 +507,7 @@ pub(in crate::parser) const SQUARE_FOOT_INTERNATIONAL: Definition = Definit }]), }; -pub(in crate::parser) const SQUARE_YARD_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const SQUARE_YARD_INTERNATIONAL: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -518,7 +518,7 @@ pub(in crate::parser) const SQUARE_YARD_INTERNATIONAL: Definition = Definit }]), }; -pub(in crate::parser) const CUBIC_INCH_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const CUBIC_INCH_INTERNATIONAL: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -529,7 +529,7 @@ pub(in crate::parser) const CUBIC_INCH_INTERNATIONAL: Definition = Definiti }]), }; -pub(in crate::parser) const CUBIC_FOOT_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const CUBIC_FOOT_INTERNATIONAL: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -540,7 +540,7 @@ pub(in crate::parser) const CUBIC_FOOT_INTERNATIONAL: Definition = Definiti }]), }; -pub(in crate::parser) const CUBIC_YARD_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const CUBIC_YARD_INTERNATIONAL: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -551,7 +551,7 @@ pub(in crate::parser) const CUBIC_YARD_INTERNATIONAL: Definition = Definiti }]), }; -pub(in crate::parser) const BOARD_FOOT_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const BOARD_FOOT_INTERNATIONAL: Definition = Definition::ValueTerms { value: 144.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -562,7 +562,7 @@ pub(in crate::parser) const BOARD_FOOT_INTERNATIONAL: Definition = Definiti }]), }; -pub(in crate::parser) const CORD_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const CORD_INTERNATIONAL: Definition = Definition::ValueTerms { value: 128.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -573,7 +573,7 @@ pub(in crate::parser) const CORD_INTERNATIONAL: Definition = Definition::Va }]), }; -pub(in crate::parser) const MIL_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const MIL_INTERNATIONAL: Definition = Definition::ValueTerms { value: 0.001, terms: Cow::Borrowed(&[Term { factor: None, @@ -584,7 +584,7 @@ pub(in crate::parser) const MIL_INTERNATIONAL: Definition = Definition::Val }]), }; -pub(in crate::parser) const HAND_INTERNATIONAL: Definition = Definition::ValueTerms { +pub(in crate::atom) const HAND_INTERNATIONAL: Definition = Definition::ValueTerms { value: 4.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -595,7 +595,7 @@ pub(in crate::parser) const HAND_INTERNATIONAL: Definition = Definition::Va }]), }; -pub(in crate::parser) const YARD_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const YARD_US: Definition = Definition::ValueTerms { value: 3.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -606,7 +606,7 @@ pub(in crate::parser) const YARD_US: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const ROD_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const ROD_US: Definition = Definition::ValueTerms { value: 16.5, terms: Cow::Borrowed(&[Term { factor: None, @@ -617,7 +617,7 @@ pub(in crate::parser) const ROD_US: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const GUNTERS_CHAIN_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const GUNTERS_CHAIN_US: Definition = Definition::ValueTerms { value: 4.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -628,7 +628,7 @@ pub(in crate::parser) const GUNTERS_CHAIN_US: Definition = Definition::Valu }]), }; -pub(in crate::parser) const RAMDENS_CHAIN_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const RAMDENS_CHAIN_US: Definition = Definition::ValueTerms { value: 100.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -639,7 +639,7 @@ pub(in crate::parser) const RAMDENS_CHAIN_US: Definition = Definition::Valu }]), }; -pub(in crate::parser) const FATHOM_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const FATHOM_US: Definition = Definition::ValueTerms { value: 6.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -650,7 +650,7 @@ pub(in crate::parser) const FATHOM_US: Definition = Definition::ValueTerms }]), }; -pub(in crate::parser) const FURLONG_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const FURLONG_US: Definition = Definition::ValueTerms { value: 40.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -661,7 +661,7 @@ pub(in crate::parser) const FURLONG_US: Definition = Definition::ValueTerms }]), }; -pub(in crate::parser) const MILE_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const MILE_US: Definition = Definition::ValueTerms { value: 8.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -672,7 +672,7 @@ pub(in crate::parser) const MILE_US: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const ACRE_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const ACRE_US: Definition = Definition::ValueTerms { value: 160.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -683,7 +683,7 @@ pub(in crate::parser) const ACRE_US: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const SQUARE_ROD_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const SQUARE_ROD_US: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -694,7 +694,7 @@ pub(in crate::parser) const SQUARE_ROD_US: Definition = Definition::ValueTe }]), }; -pub(in crate::parser) const SQUARE_MILE_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const SQUARE_MILE_US: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -705,9 +705,9 @@ pub(in crate::parser) const SQUARE_MILE_US: Definition = Definition::ValueT }]), }; -pub(in crate::parser) const SECTION: Definition = SQUARE_MILE_US; +pub(in crate::atom) const SECTION: Definition = SQUARE_MILE_US; -pub(in crate::parser) const TOWNSHIP: Definition = Definition::ValueTerms { +pub(in crate::atom) const TOWNSHIP: Definition = Definition::ValueTerms { value: 36.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -718,7 +718,7 @@ pub(in crate::parser) const TOWNSHIP: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const MIL_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const MIL_US: Definition = Definition::ValueTerms { value: 0.001, terms: Cow::Borrowed(&[Term { factor: None, @@ -729,7 +729,7 @@ pub(in crate::parser) const MIL_US: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const INCH_BRITISH: Definition = Definition::ValueTerms { +pub(in crate::atom) const INCH_BRITISH: Definition = Definition::ValueTerms { value: 2.539_998, terms: Cow::Borrowed(&[Term { factor: None, @@ -740,7 +740,7 @@ pub(in crate::parser) const INCH_BRITISH: Definition = Definition::ValueTer }]), }; -pub(in crate::parser) const FOOT_BRITISH: Definition = Definition::ValueTerms { +pub(in crate::atom) const FOOT_BRITISH: Definition = Definition::ValueTerms { value: 12.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -751,7 +751,7 @@ pub(in crate::parser) const FOOT_BRITISH: Definition = Definition::ValueTer }]), }; -pub(in crate::parser) const ROD_BRITISH: Definition = Definition::ValueTerms { +pub(in crate::atom) const ROD_BRITISH: Definition = Definition::ValueTerms { value: 16.5, terms: Cow::Borrowed(&[Term { factor: None, @@ -762,7 +762,7 @@ pub(in crate::parser) const ROD_BRITISH: Definition = Definition::ValueTerm }]), }; -pub(in crate::parser) const GUNTERS_CHAIN_BRITISH: Definition = Definition::ValueTerms { +pub(in crate::atom) const GUNTERS_CHAIN_BRITISH: Definition = Definition::ValueTerms { value: 4.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -773,7 +773,7 @@ pub(in crate::parser) const GUNTERS_CHAIN_BRITISH: Definition = Definition: }]), }; -pub(in crate::parser) const FATHOM_BRITISH: Definition = Definition::ValueTerms { +pub(in crate::atom) const FATHOM_BRITISH: Definition = Definition::ValueTerms { value: 6.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -784,7 +784,7 @@ pub(in crate::parser) const FATHOM_BRITISH: Definition = Definition::ValueT }]), }; -pub(in crate::parser) const PACE_BRITISH: Definition = Definition::ValueTerms { +pub(in crate::atom) const PACE_BRITISH: Definition = Definition::ValueTerms { value: 2.5, terms: Cow::Borrowed(&[Term { factor: None, @@ -795,7 +795,7 @@ pub(in crate::parser) const PACE_BRITISH: Definition = Definition::ValueTer }]), }; -pub(in crate::parser) const YARD_BRITISH: Definition = Definition::ValueTerms { +pub(in crate::atom) const YARD_BRITISH: Definition = Definition::ValueTerms { value: 3.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -806,7 +806,7 @@ pub(in crate::parser) const YARD_BRITISH: Definition = Definition::ValueTer }]), }; -pub(in crate::parser) const MILE_BRITISH: Definition = Definition::ValueTerms { +pub(in crate::atom) const MILE_BRITISH: Definition = Definition::ValueTerms { value: 5280.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -817,7 +817,7 @@ pub(in crate::parser) const MILE_BRITISH: Definition = Definition::ValueTer }]), }; -pub(in crate::parser) const NAUTICLE_MILE_BRITISH: Definition = Definition::ValueTerms { +pub(in crate::atom) const NAUTICLE_MILE_BRITISH: Definition = Definition::ValueTerms { value: 6080.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -828,7 +828,7 @@ pub(in crate::parser) const NAUTICLE_MILE_BRITISH: Definition = Definition: }]), }; -pub(in crate::parser) const ACRE_BRITISH: Definition = Definition::ValueTerms { +pub(in crate::atom) const ACRE_BRITISH: Definition = Definition::ValueTerms { value: 4840.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -839,7 +839,7 @@ pub(in crate::parser) const ACRE_BRITISH: Definition = Definition::ValueTer }]), }; -pub(in crate::parser) const QUEEN_ANNES_WINE_GALLON_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const QUEEN_ANNES_WINE_GALLON_US: Definition = Definition::ValueTerms { value: 231.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -850,7 +850,7 @@ pub(in crate::parser) const QUEEN_ANNES_WINE_GALLON_US: Definition = Defini }]), }; -pub(in crate::parser) const BARREL_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const BARREL_US: Definition = Definition::ValueTerms { value: 42.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -861,7 +861,7 @@ pub(in crate::parser) const BARREL_US: Definition = Definition::ValueTerms }]), }; -pub(in crate::parser) const CORD_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const CORD_US: Definition = Definition::ValueTerms { value: 128.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -872,7 +872,7 @@ pub(in crate::parser) const CORD_US: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const BUSHEL_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const BUSHEL_US: Definition = Definition::ValueTerms { value: 2150.42, terms: Cow::Borrowed(&[Term { factor: None, @@ -883,7 +883,7 @@ pub(in crate::parser) const BUSHEL_US: Definition = Definition::ValueTerms }]), }; -pub(in crate::parser) const CUP_US: Definition = Definition::ValueTerms { +pub(in crate::atom) const CUP_US: Definition = Definition::ValueTerms { value: 16.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -894,7 +894,7 @@ pub(in crate::parser) const CUP_US: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const METRIC_FLUID_OUNCE: Definition = Definition::ValueTerms { +pub(in crate::atom) const METRIC_FLUID_OUNCE: Definition = Definition::ValueTerms { value: 30.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -905,7 +905,7 @@ pub(in crate::parser) const METRIC_FLUID_OUNCE: Definition = Definition::Va }]), }; -pub(in crate::parser) const METRIC_CUP: Definition = Definition::ValueTerms { +pub(in crate::atom) const METRIC_CUP: Definition = Definition::ValueTerms { value: 240.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -916,7 +916,7 @@ pub(in crate::parser) const METRIC_CUP: Definition = Definition::ValueTerms }]), }; -pub(in crate::parser) const METRIC_TEASPOON: Definition = Definition::ValueTerms { +pub(in crate::atom) const METRIC_TEASPOON: Definition = Definition::ValueTerms { value: 5.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -927,7 +927,7 @@ pub(in crate::parser) const METRIC_TEASPOON: Definition = Definition::Value }]), }; -pub(in crate::parser) const METRIC_TABLESPOON: Definition = Definition::ValueTerms { +pub(in crate::atom) const METRIC_TABLESPOON: Definition = Definition::ValueTerms { value: 15.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -938,7 +938,7 @@ pub(in crate::parser) const METRIC_TABLESPOON: Definition = Definition::Val }]), }; -pub(in crate::parser) const GALLON_BRITISH: Definition = Definition::ValueTerms { +pub(in crate::atom) const GALLON_BRITISH: Definition = Definition::ValueTerms { value: 4.54609, terms: Cow::Borrowed(&[Term { factor: None, @@ -949,7 +949,7 @@ pub(in crate::parser) const GALLON_BRITISH: Definition = Definition::ValueT }]), }; -pub(in crate::parser) const PECK_BRITISH: Definition = Definition::ValueTerms { +pub(in crate::atom) const PECK_BRITISH: Definition = Definition::ValueTerms { value: 2.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -960,7 +960,7 @@ pub(in crate::parser) const PECK_BRITISH: Definition = Definition::ValueTer }]), }; -pub(in crate::parser) const BUSHEL_BRITISH: Definition = Definition::ValueTerms { +pub(in crate::atom) const BUSHEL_BRITISH: Definition = Definition::ValueTerms { value: 4.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -971,7 +971,7 @@ pub(in crate::parser) const BUSHEL_BRITISH: Definition = Definition::ValueT }]), }; -pub(in crate::parser) const GRAIN: Definition = Definition::ValueTerms { +pub(in crate::atom) const GRAIN: Definition = Definition::ValueTerms { value: 64.798_91, terms: Cow::Borrowed(&[Term { factor: None, @@ -982,7 +982,7 @@ pub(in crate::parser) const GRAIN: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const POUND_AVOIRDUPOIS: Definition = Definition::ValueTerms { +pub(in crate::atom) const POUND_AVOIRDUPOIS: Definition = Definition::ValueTerms { value: 7000.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -993,7 +993,7 @@ pub(in crate::parser) const POUND_AVOIRDUPOIS: Definition = Definition::Val }]), }; -pub(in crate::parser) const SHORT_HUNDREDWEIGHT_AVOIRDUPOIS: Definition = +pub(in crate::atom) const SHORT_HUNDREDWEIGHT_AVOIRDUPOIS: Definition = Definition::ValueTerms { value: 100.0, terms: Cow::Borrowed(&[Term { @@ -1005,7 +1005,7 @@ pub(in crate::parser) const SHORT_HUNDREDWEIGHT_AVOIRDUPOIS: Definition = }]), }; -pub(in crate::parser) const LONG_HUNDREDWEIGHT_AVOIRDUPOIS: Definition = +pub(in crate::atom) const LONG_HUNDREDWEIGHT_AVOIRDUPOIS: Definition = Definition::ValueTerms { value: 112.0, terms: Cow::Borrowed(&[Term { @@ -1017,7 +1017,7 @@ pub(in crate::parser) const LONG_HUNDREDWEIGHT_AVOIRDUPOIS: Definition = }]), }; -pub(in crate::parser) const SHORT_TON_AVOIRDUPOIS: Definition = Definition::ValueTerms { +pub(in crate::atom) const SHORT_TON_AVOIRDUPOIS: Definition = Definition::ValueTerms { value: 20.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1028,7 +1028,7 @@ pub(in crate::parser) const SHORT_TON_AVOIRDUPOIS: Definition = Definition: }]), }; -pub(in crate::parser) const LONG_TON_AVOIRDUPOIS: Definition = Definition::ValueTerms { +pub(in crate::atom) const LONG_TON_AVOIRDUPOIS: Definition = Definition::ValueTerms { value: 20.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1039,7 +1039,7 @@ pub(in crate::parser) const LONG_TON_AVOIRDUPOIS: Definition = Definition:: }]), }; -pub(in crate::parser) const STONE_AVOIRDUPOIS: Definition = Definition::ValueTerms { +pub(in crate::atom) const STONE_AVOIRDUPOIS: Definition = Definition::ValueTerms { value: 14.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1050,7 +1050,7 @@ pub(in crate::parser) const STONE_AVOIRDUPOIS: Definition = Definition::Val }]), }; -pub(in crate::parser) const PENNYWEIGHT_TROY: Definition = Definition::ValueTerms { +pub(in crate::atom) const PENNYWEIGHT_TROY: Definition = Definition::ValueTerms { value: 24.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1061,7 +1061,7 @@ pub(in crate::parser) const PENNYWEIGHT_TROY: Definition = Definition::Valu }]), }; -pub(in crate::parser) const OUNCE_TROY: Definition = Definition::ValueTerms { +pub(in crate::atom) const OUNCE_TROY: Definition = Definition::ValueTerms { value: 20.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1072,7 +1072,7 @@ pub(in crate::parser) const OUNCE_TROY: Definition = Definition::ValueTerms }]), }; -pub(in crate::parser) const POUND_TROY: Definition = Definition::ValueTerms { +pub(in crate::atom) const POUND_TROY: Definition = Definition::ValueTerms { value: 12.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1083,7 +1083,7 @@ pub(in crate::parser) const POUND_TROY: Definition = Definition::ValueTerms }]), }; -pub(in crate::parser) const SCUPLE_APOTHECARIES: Definition = Definition::ValueTerms { +pub(in crate::atom) const SCUPLE_APOTHECARIES: Definition = Definition::ValueTerms { value: 20.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1094,7 +1094,7 @@ pub(in crate::parser) const SCUPLE_APOTHECARIES: Definition = Definition::V }]), }; -pub(in crate::parser) const DRAM_APOTHECARIES: Definition = Definition::ValueTerms { +pub(in crate::atom) const DRAM_APOTHECARIES: Definition = Definition::ValueTerms { value: 3.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1105,7 +1105,7 @@ pub(in crate::parser) const DRAM_APOTHECARIES: Definition = Definition::Val }]), }; -pub(in crate::parser) const OUNCE_APOTHECARIES: Definition = Definition::ValueTerms { +pub(in crate::atom) const OUNCE_APOTHECARIES: Definition = Definition::ValueTerms { value: 8.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1116,7 +1116,7 @@ pub(in crate::parser) const OUNCE_APOTHECARIES: Definition = Definition::Va }]), }; -pub(in crate::parser) const POUND_APOTHECARIES: Definition = Definition::ValueTerms { +pub(in crate::atom) const POUND_APOTHECARIES: Definition = Definition::ValueTerms { value: 12.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1127,7 +1127,7 @@ pub(in crate::parser) const POUND_APOTHECARIES: Definition = Definition::Va }]), }; -pub(in crate::parser) const METRIC_OUNCE: Definition = Definition::ValueTerms { +pub(in crate::atom) const METRIC_OUNCE: Definition = Definition::ValueTerms { value: 28.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1138,7 +1138,7 @@ pub(in crate::parser) const METRIC_OUNCE: Definition = Definition::ValueTer }]), }; -pub(in crate::parser) const PICA: Definition = Definition::ValueTerms { +pub(in crate::atom) const PICA: Definition = Definition::ValueTerms { value: 12.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1149,7 +1149,7 @@ pub(in crate::parser) const PICA: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const PRINTERS_POINT: Definition = Definition::ValueTerms { +pub(in crate::atom) const PRINTERS_POINT: Definition = Definition::ValueTerms { value: 0.013_837, terms: Cow::Borrowed(&[Term { factor: None, @@ -1160,7 +1160,7 @@ pub(in crate::parser) const PRINTERS_POINT: Definition = Definition::ValueT }]), }; -pub(in crate::parser) const PRINTERS_PICA: Definition = Definition::ValueTerms { +pub(in crate::atom) const PRINTERS_PICA: Definition = Definition::ValueTerms { value: 12.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1171,7 +1171,7 @@ pub(in crate::parser) const PRINTERS_PICA: Definition = Definition::ValueTe }]), }; -pub(in crate::parser) const PIED: Definition = Definition::ValueTerms { +pub(in crate::atom) const PIED: Definition = Definition::ValueTerms { value: 32.48, terms: Cow::Borrowed(&[Term { factor: None, @@ -1182,7 +1182,7 @@ pub(in crate::parser) const PIED: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const CICERO: Definition = Definition::ValueTerms { +pub(in crate::atom) const CICERO: Definition = Definition::ValueTerms { value: 12.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1193,7 +1193,7 @@ pub(in crate::parser) const CICERO: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const CALORIE_AT_15C: Definition = Definition::ValueTerms { +pub(in crate::atom) const CALORIE_AT_15C: Definition = Definition::ValueTerms { value: 4.1858, terms: Cow::Borrowed(&[Term { factor: None, @@ -1204,7 +1204,7 @@ pub(in crate::parser) const CALORIE_AT_15C: Definition = Definition::ValueT }]), }; -pub(in crate::parser) const CALORIE_AT_20C: Definition = Definition::ValueTerms { +pub(in crate::atom) const CALORIE_AT_20C: Definition = Definition::ValueTerms { value: 4.1819, terms: Cow::Borrowed(&[Term { factor: None, @@ -1215,7 +1215,7 @@ pub(in crate::parser) const CALORIE_AT_20C: Definition = Definition::ValueT }]), }; -pub(in crate::parser) const MEAN_CALORIE: Definition = Definition::ValueTerms { +pub(in crate::atom) const MEAN_CALORIE: Definition = Definition::ValueTerms { value: 4.190_02, terms: Cow::Borrowed(&[Term { factor: None, @@ -1226,7 +1226,7 @@ pub(in crate::parser) const MEAN_CALORIE: Definition = Definition::ValueTer }]), }; -pub(in crate::parser) const INTERNATIONAL_TABLE_CALORIE: Definition = Definition::ValueTerms { +pub(in crate::atom) const INTERNATIONAL_TABLE_CALORIE: Definition = Definition::ValueTerms { value: 4.1868, terms: Cow::Borrowed(&[Term { factor: None, @@ -1237,7 +1237,7 @@ pub(in crate::parser) const INTERNATIONAL_TABLE_CALORIE: Definition = Defin }]), }; -pub(in crate::parser) const THERMOCHEMICAL_CALORIE: Definition = Definition::ValueTerms { +pub(in crate::atom) const THERMOCHEMICAL_CALORIE: Definition = Definition::ValueTerms { value: 4.184, terms: Cow::Borrowed(&[Term { factor: None, @@ -1248,7 +1248,7 @@ pub(in crate::parser) const THERMOCHEMICAL_CALORIE: Definition = Definition }]), }; -pub(in crate::parser) const CALORIE: Definition = Definition::ValueTerms { +pub(in crate::atom) const CALORIE: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1259,7 +1259,7 @@ pub(in crate::parser) const CALORIE: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const NUTRITION_LABEL_CALORIES: Definition = Definition::ValueTerms { +pub(in crate::atom) const NUTRITION_LABEL_CALORIES: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1270,7 +1270,7 @@ pub(in crate::parser) const NUTRITION_LABEL_CALORIES: Definition = Definiti }]), }; -pub(in crate::parser) const BRITISH_THERMAL_UNIT_AT_39F: Definition = Definition::ValueTerms { +pub(in crate::atom) const BRITISH_THERMAL_UNIT_AT_39F: Definition = Definition::ValueTerms { value: 1.059_67, terms: Cow::Borrowed(&[Term { factor: None, @@ -1281,7 +1281,7 @@ pub(in crate::parser) const BRITISH_THERMAL_UNIT_AT_39F: Definition = Defin }]), }; -pub(in crate::parser) const BRITISH_THERMAL_UNIT_AT_59F: Definition = Definition::ValueTerms { +pub(in crate::atom) const BRITISH_THERMAL_UNIT_AT_59F: Definition = Definition::ValueTerms { value: 1.0548, terms: Cow::Borrowed(&[Term { factor: None, @@ -1292,7 +1292,7 @@ pub(in crate::parser) const BRITISH_THERMAL_UNIT_AT_59F: Definition = Defin }]), }; -pub(in crate::parser) const BRITISH_THERMAL_UNIT_AT_60F: Definition = Definition::ValueTerms { +pub(in crate::atom) const BRITISH_THERMAL_UNIT_AT_60F: Definition = Definition::ValueTerms { value: 1.05468, terms: Cow::Borrowed(&[Term { factor: None, @@ -1303,7 +1303,7 @@ pub(in crate::parser) const BRITISH_THERMAL_UNIT_AT_60F: Definition = Defin }]), }; -pub(in crate::parser) const MEAN_BRITISH_THERMAL_UNIT: Definition = Definition::ValueTerms { +pub(in crate::atom) const MEAN_BRITISH_THERMAL_UNIT: Definition = Definition::ValueTerms { value: 1.055_87, terms: Cow::Borrowed(&[Term { factor: None, @@ -1314,7 +1314,7 @@ pub(in crate::parser) const MEAN_BRITISH_THERMAL_UNIT: Definition = Definit }]), }; -pub(in crate::parser) const INTERNATIONAL_TABLE_BRITISH_THERMAL_UNIT: Definition = +pub(in crate::atom) const INTERNATIONAL_TABLE_BRITISH_THERMAL_UNIT: Definition = Definition::ValueTerms { value: 1.055_055_852_62, terms: Cow::Borrowed(&[Term { @@ -1326,7 +1326,7 @@ pub(in crate::parser) const INTERNATIONAL_TABLE_BRITISH_THERMAL_UNIT: Definition }]), }; -pub(in crate::parser) const THERMOCHEMICAL_BRITISH_THERMAL_UNIT: Definition = +pub(in crate::atom) const THERMOCHEMICAL_BRITISH_THERMAL_UNIT: Definition = Definition::ValueTerms { value: 1.054_35, terms: Cow::Borrowed(&[Term { @@ -1338,7 +1338,7 @@ pub(in crate::parser) const THERMOCHEMICAL_BRITISH_THERMAL_UNIT: Definition }]), }; -pub(in crate::parser) const BRITISH_THERMAL_UNIT: Definition = Definition::ValueTerms { +pub(in crate::atom) const BRITISH_THERMAL_UNIT: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1349,7 +1349,7 @@ pub(in crate::parser) const BRITISH_THERMAL_UNIT: Definition = Definition:: }]), }; -pub(in crate::parser) const METER_OF_WATER_COLUMN: Definition = Definition::ValueTerms { +pub(in crate::atom) const METER_OF_WATER_COLUMN: Definition = Definition::ValueTerms { value: 9.806_65, terms: Cow::Borrowed(&[Term { factor: None, @@ -1360,7 +1360,7 @@ pub(in crate::parser) const METER_OF_WATER_COLUMN: Definition = Definition: }]), }; -pub(in crate::parser) const METER_OF_MERCURY_COLUMN: Definition = Definition::ValueTerms { +pub(in crate::atom) const METER_OF_MERCURY_COLUMN: Definition = Definition::ValueTerms { value: 133.322, terms: Cow::Borrowed(&[Term { factor: None, @@ -1371,7 +1371,7 @@ pub(in crate::parser) const METER_OF_MERCURY_COLUMN: Definition = Definitio }]), }; -pub(in crate::parser) const PRISM_DIOPTER: Definition = Definition::ValueTermsSpecial { +pub(in crate::atom) const PRISM_DIOPTER: Definition = Definition::ValueTermsSpecial { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1386,7 +1386,7 @@ pub(in crate::parser) const PRISM_DIOPTER: Definition = Definition::ValueTe }, }; -pub(in crate::parser) const PERCENT_OF_SLOPE: Definition = Definition::ValueTermsSpecial { +pub(in crate::atom) const PERCENT_OF_SLOPE: Definition = Definition::ValueTermsSpecial { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1401,7 +1401,7 @@ pub(in crate::parser) const PERCENT_OF_SLOPE: Definition = Definition::Valu }, }; -pub(in crate::parser) const HOMEOPATHIC_POTENCY_OF_DECIMAL_SERIES_RETIRED: Definition = +pub(in crate::atom) const HOMEOPATHIC_POTENCY_OF_DECIMAL_SERIES_RETIRED: Definition = Definition::ValueSpecial { value: 1f64, function_set: FunctionSet { @@ -1410,7 +1410,7 @@ pub(in crate::parser) const HOMEOPATHIC_POTENCY_OF_DECIMAL_SERIES_RETIRED: Defin }, }; -pub(in crate::parser) const HOMEOPATHIC_POTENCY_OF_CENTESIMAL_SERIES_RETIRED: Definition = +pub(in crate::atom) const HOMEOPATHIC_POTENCY_OF_CENTESIMAL_SERIES_RETIRED: Definition = Definition::ValueSpecial { value: 1f64, function_set: FunctionSet { @@ -1419,7 +1419,7 @@ pub(in crate::parser) const HOMEOPATHIC_POTENCY_OF_CENTESIMAL_SERIES_RETIRED: De }, }; -pub(in crate::parser) const HOMEOPATHIC_POTENCY_OF_MILLESIMAL_SERIES_RETIRED: Definition = +pub(in crate::atom) const HOMEOPATHIC_POTENCY_OF_MILLESIMAL_SERIES_RETIRED: Definition = Definition::ValueSpecial { value: 1f64, function_set: FunctionSet { @@ -1428,7 +1428,7 @@ pub(in crate::parser) const HOMEOPATHIC_POTENCY_OF_MILLESIMAL_SERIES_RETIRED: De }, }; -pub(in crate::parser) const HOMEOPATHIC_POTENCY_OF_QUINTMILLESIMAL_SERIES_RETIRED: Definition = +pub(in crate::atom) const HOMEOPATHIC_POTENCY_OF_QUINTMILLESIMAL_SERIES_RETIRED: Definition = Definition::ValueSpecial { value: 1f64, function_set: FunctionSet { @@ -1437,7 +1437,7 @@ pub(in crate::parser) const HOMEOPATHIC_POTENCY_OF_QUINTMILLESIMAL_SERIES_RETIRE }, }; -pub(in crate::parser) const EQUIVALENTS: Definition = Definition::ValueTerms { +pub(in crate::atom) const EQUIVALENTS: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1448,7 +1448,7 @@ pub(in crate::parser) const EQUIVALENTS: Definition = Definition::ValueTerm }]), }; -pub(in crate::parser) const OSMOLE: Definition = Definition::ValueTerms { +pub(in crate::atom) const OSMOLE: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1459,19 +1459,18 @@ pub(in crate::parser) const OSMOLE: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const INTERNATIONAL_UNIT_SECONDARY: Definition = - Definition::ValueTerms { - value: 1.0, - terms: Cow::Borrowed(&[Term { - factor: None, - prefix: None, - atom: Some(Atom::InternationalUnit), - exponent: None, - annotation: None, - }]), - }; +pub(in crate::atom) const INTERNATIONAL_UNIT_SECONDARY: Definition = Definition::ValueTerms { + value: 1.0, + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::InternationalUnit), + exponent: None, + annotation: None, + }]), +}; -pub(in crate::parser) const NEPER: Definition = Definition::ValueSpecial { +pub(in crate::atom) const NEPER: Definition = Definition::ValueSpecial { value: 1.0, function_set: FunctionSet { convert_from: f64::ln, @@ -1479,7 +1478,7 @@ pub(in crate::parser) const NEPER: Definition = Definition::ValueSpecial { }, }; -pub(in crate::parser) const BEL: Definition = Definition::ValueSpecial { +pub(in crate::atom) const BEL: Definition = Definition::ValueSpecial { value: 1.0, function_set: FunctionSet { convert_from: f64::log10, @@ -1487,7 +1486,7 @@ pub(in crate::parser) const BEL: Definition = Definition::ValueSpecial { }, }; -pub(in crate::parser) const BEL_VOLT: Definition = Definition::ValueTermsSpecial { +pub(in crate::atom) const BEL_VOLT: Definition = Definition::ValueTermsSpecial { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1502,7 +1501,7 @@ pub(in crate::parser) const BEL_VOLT: Definition = Definition::ValueTermsSp }, }; -pub(in crate::parser) const BEL_MILLIVOLT: Definition = Definition::ValueTermsSpecial { +pub(in crate::atom) const BEL_MILLIVOLT: Definition = Definition::ValueTermsSpecial { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1517,7 +1516,7 @@ pub(in crate::parser) const BEL_MILLIVOLT: Definition = Definition::ValueTe }, }; -pub(in crate::parser) const BEL_MICROVOLT: Definition = Definition::ValueTermsSpecial { +pub(in crate::atom) const BEL_MICROVOLT: Definition = Definition::ValueTermsSpecial { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1532,7 +1531,7 @@ pub(in crate::parser) const BEL_MICROVOLT: Definition = Definition::ValueTe }, }; -pub(in crate::parser) const BEL_10_NANOVOLT: Definition = Definition::ValueTermsSpecial { +pub(in crate::atom) const BEL_10_NANOVOLT: Definition = Definition::ValueTermsSpecial { value: 10.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1547,7 +1546,7 @@ pub(in crate::parser) const BEL_10_NANOVOLT: Definition = Definition::Value }, }; -pub(in crate::parser) const BEL_WATT: Definition = Definition::ValueTermsSpecial { +pub(in crate::atom) const BEL_WATT: Definition = Definition::ValueTermsSpecial { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1562,7 +1561,7 @@ pub(in crate::parser) const BEL_WATT: Definition = Definition::ValueTermsSp }, }; -pub(in crate::parser) const BEL_KILOWATT: Definition = Definition::ValueTermsSpecial { +pub(in crate::atom) const BEL_KILOWATT: Definition = Definition::ValueTermsSpecial { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1577,7 +1576,7 @@ pub(in crate::parser) const BEL_KILOWATT: Definition = Definition::ValueTer }, }; -pub(in crate::parser) const STERE: Definition = Definition::ValueTerms { +pub(in crate::atom) const STERE: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1588,7 +1587,7 @@ pub(in crate::parser) const STERE: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const ANGSTROM: Definition = Definition::ValueTerms { +pub(in crate::atom) const ANGSTROM: Definition = Definition::ValueTerms { value: 0.1, terms: Cow::Borrowed(&[Term { factor: None, @@ -1599,7 +1598,7 @@ pub(in crate::parser) const ANGSTROM: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const BARN: Definition = Definition::ValueTerms { +pub(in crate::atom) const BARN: Definition = Definition::ValueTerms { value: 100.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1610,7 +1609,7 @@ pub(in crate::parser) const BARN: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const MHO: Definition = Definition::ValueTerms { +pub(in crate::atom) const MHO: Definition = Definition::ValueTerms { value: 1.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1621,7 +1620,7 @@ pub(in crate::parser) const MHO: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const METRIC_CARAT: Definition = Definition::ValueTerms { +pub(in crate::atom) const METRIC_CARAT: Definition = Definition::ValueTerms { value: 0.2, terms: Cow::Borrowed(&[Term { factor: None, @@ -1632,7 +1631,7 @@ pub(in crate::parser) const METRIC_CARAT: Definition = Definition::ValueTer }]), }; -pub(in crate::parser) const SMOOT: Definition = Definition::ValueTerms { +pub(in crate::atom) const SMOOT: Definition = Definition::ValueTerms { value: 67.0, terms: Cow::Borrowed(&[Term { factor: None, @@ -1643,7 +1642,7 @@ pub(in crate::parser) const SMOOT: Definition = Definition::ValueTerms { }]), }; -pub(in crate::parser) const BIT_LOGARITHMUS_DUALIS: Definition = Definition::ValueSpecial { +pub(in crate::atom) const BIT_LOGARITHMUS_DUALIS: Definition = Definition::ValueSpecial { value: 1.0, function_set: FunctionSet { convert_from: f64::log2, @@ -1651,7 +1650,7 @@ pub(in crate::parser) const BIT_LOGARITHMUS_DUALIS: Definition = Definition }, }; -pub(in crate::parser) const BYTE: Definition = Definition::ValueTerms { +pub(in crate::atom) const BYTE: Definition = Definition::ValueTerms { value: 8.0, terms: Cow::Borrowed(&[Term { factor: None, diff --git a/crates/api/src/parser/atom/display.rs b/crates/api/src/atom/display.rs similarity index 100% rename from crates/api/src/parser/atom/display.rs rename to crates/api/src/atom/display.rs diff --git a/crates/api/src/parser/function_set.rs b/crates/api/src/atom/function_set.rs similarity index 100% rename from crates/api/src/parser/function_set.rs rename to crates/api/src/atom/function_set.rs diff --git a/crates/api/src/parser/atom/hash.rs b/crates/api/src/atom/hash.rs similarity index 100% rename from crates/api/src/parser/atom/hash.rs rename to crates/api/src/atom/hash.rs diff --git a/crates/api/src/parser/atom/partial_eq.rs b/crates/api/src/atom/partial_eq.rs similarity index 100% rename from crates/api/src/parser/atom/partial_eq.rs rename to crates/api/src/atom/partial_eq.rs diff --git a/crates/api/src/parser/atom/reducible.rs b/crates/api/src/atom/reducible.rs similarity index 100% rename from crates/api/src/parser/atom/reducible.rs rename to crates/api/src/atom/reducible.rs diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 784e05a5..09c6acc3 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -22,6 +22,7 @@ mod macros; pub mod as_fraction; +pub mod atom; pub mod convertible; pub mod error; pub mod field_eq; @@ -36,14 +37,15 @@ mod reducible; mod ucum_unit; pub use crate::{ + atom::Atom, convertible::Convertible, error::Error, field_eq::FieldEq, is_compatible_with::IsCompatibleWith, measurement::Measurement, parser::{ - composition, Atom, Classification, Composable, Composition, Dimension, Prefix, Property, - Term, UcumSymbol, + composition, Classification, Composable, Composition, Dimension, Prefix, Property, Term, + UcumSymbol, }, ucum_unit::UcumUnit, unit::Unit, diff --git a/crates/api/src/macros.rs b/crates/api/src/macros.rs index 2398a0ca..0db2ae83 100644 --- a/crates/api/src/macros.rs +++ b/crates/api/src/macros.rs @@ -69,7 +69,10 @@ macro_rules! terms { #[cfg(test)] mod tests { - use crate::parser::{Atom, Prefix, Term}; + use crate::{ + parser::{Prefix, Term}, + Atom, + }; #[test] fn validate_term_macro() { diff --git a/crates/api/src/measurement.rs b/crates/api/src/measurement.rs index b2482e56..215e62e7 100644 --- a/crates/api/src/measurement.rs +++ b/crates/api/src/measurement.rs @@ -124,14 +124,14 @@ impl AsRef for Measurement { #[cfg(test)] mod tests { - use super::{ - super::parser::{Atom, Term}, - *, - }; - use crate::unit::Unit; - use approx::{assert_relative_eq, assert_ulps_eq}; use std::{convert::Infallible, str::FromStr}; + use approx::{assert_relative_eq, assert_ulps_eq}; + + use crate::{Atom, Term, Unit}; + + use super::*; + #[test] fn validate_new() { let m = Measurement::try_new(1.0, "m").unwrap(); diff --git a/crates/api/src/parser.rs b/crates/api/src/parser.rs index b8edd2f3..b95eab33 100644 --- a/crates/api/src/parser.rs +++ b/crates/api/src/parser.rs @@ -12,7 +12,6 @@ clippy::non_ascii_literal ) )] -pub mod atom; pub mod classification; pub mod composition; #[allow(clippy::non_ascii_literal)] @@ -21,20 +20,20 @@ pub mod property; mod symbols; mod annotation_composition; -#[cfg(test)] -mod atom_test; mod composable; -mod definition; mod dimension; mod error; -mod function_set; mod prefix; pub(crate) mod term; mod terms; mod ucum_symbol; +use pest::{iterators::Pair, Parser}; + +use crate::Atom; + pub use self::{ - annotation_composition::AnnotationComposition, atom::Atom, classification::Classification, + annotation_composition::AnnotationComposition, classification::Classification, composable::Composable, composition::Composition, dimension::Dimension, error::Error, prefix::Prefix, property::Property, term::Term, ucum_symbol::UcumSymbol, }; @@ -43,7 +42,6 @@ use self::{ symbols::symbol_parser::Rule as SymbolRule, terms::term_parser::{Rule as TermRule, TermParser}, }; -use pest::{iterators::Pair, Parser}; #[inline] pub(crate) fn parse(expression: &str) -> Result, Error> { diff --git a/crates/api/src/unit/term_reducing.rs b/crates/api/src/unit/term_reducing.rs index 2e6f9031..47dad85d 100644 --- a/crates/api/src/unit/term_reducing.rs +++ b/crates/api/src/unit/term_reducing.rs @@ -2,8 +2,8 @@ use std::collections::BTreeMap; use num_traits::Zero; -use crate::parser::{ - term::{self, Exponent, Factor}, +use crate::{ + parser::term::{self, Exponent, Factor}, Atom, Prefix, Term, }; diff --git a/crates/atom_generator/src/generator.rs b/crates/atom_generator/src/generator.rs index b9840ea1..b9b1926f 100644 --- a/crates/atom_generator/src/generator.rs +++ b/crates/atom_generator/src/generator.rs @@ -6,15 +6,15 @@ //! consuming library or application. //! - mod atom; - mod classification; - mod handlebars; - mod property; - mod symbol_grammar; +mod atom; +mod classification; +mod handlebars; +mod property; +mod symbol_grammar; use proc_macro2::TokenStream; - use self::handlebars::HANDLEBARS; +use self::handlebars::HANDLEBARS; use crate::rust_structs::RustAtomList; use std::{ @@ -24,7 +24,7 @@ use std::{ process::Command, }; - const BANNER: &str = +const BANNER: &str = "//----------------------------------------------------------------------------- // DO NOT EDIT THIS FILE! // This is generated by wise_units-atom_generator. @@ -56,7 +56,7 @@ fn generate_property_file(rust_atom_list: &RustAtomList) { fn generate_atom_file(rust_atom_list: &RustAtomList) { let file_body = self::atom::generate_file_body(rust_atom_list); - let file_path = build_file_path("parser/atom.rs"); + let file_path = build_file_path("atom.rs"); write_project_file(&file_path, &file_body, true); } @@ -89,7 +89,7 @@ fn write_project_file(file_path: &Path, file_body: &str, do_format: bool) { } } - fn pretty_format(token_stream: &TokenStream) -> String { +fn pretty_format(token_stream: &TokenStream) -> String { let token_string = token_stream.to_string(); // Run the output through `prettyplease`. This should catch some syntactical mess-ups. diff --git a/crates/atom_generator/src/generator/atom.rs b/crates/atom_generator/src/generator/atom.rs index eaa32bd4..85cf3f76 100644 --- a/crates/atom_generator/src/generator/atom.rs +++ b/crates/atom_generator/src/generator/atom.rs @@ -29,13 +29,17 @@ pub(super) fn generate_file_body(atom_list: &RustAtomList) -> String { use crate::{ is_compatible_with::DefaultCompatibility, - parser::{ - definition::Definition, function_set::FunctionSet, Classification, Property, UcumSymbol, - }, + parser::{Classification, Property, UcumSymbol}, reducible::Reducible, UcumUnit, Unit, }; + #[allow(clippy::wildcard_imports)] + use self::{ + definition::{consts::*, Definition}, + function_set::FunctionSet, + }; + #atom_enum impl Atom { diff --git a/crates/atom_generator/src/generator/property.rs b/crates/atom_generator/src/generator/property.rs index 742078ff..dc85ccd9 100644 --- a/crates/atom_generator/src/generator/property.rs +++ b/crates/atom_generator/src/generator/property.rs @@ -12,7 +12,7 @@ pub(super) fn generate_file_body(atom_list: &RustAtomList) -> String { let display = property_list.display(); let tokens = quote! { - use crate::parser::Atom; + use crate::Atom; use std::fmt; /// Property categorizes the unit by use. Not much mention of it in the UCUM From 7514f1905bb447cbce6538ef8f1c24a14094e871 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 25 Mar 2024 14:09:19 -0700 Subject: [PATCH 47/80] PLCC-299 Move Classification to root --- crates/api/src/atom.rs | 4 ++-- crates/api/src/atom/atom_test.rs | 4 ++-- crates/api/src/{parser => }/classification.rs | 0 crates/api/src/lib.rs | 7 +++---- crates/api/src/parser.rs | 7 +++---- crates/api/src/parser/prefix.rs | 12 ++++++++---- crates/api/src/parser/ucum_symbol.rs | 2 +- crates/atom_generator/src/generator.rs | 2 +- crates/atom_generator/src/generator/atom.rs | 4 ++-- 9 files changed, 22 insertions(+), 20 deletions(-) rename crates/api/src/{parser => }/classification.rs (100%) diff --git a/crates/api/src/atom.rs b/crates/api/src/atom.rs index 2eabf985..e5a618a8 100644 --- a/crates/api/src/atom.rs +++ b/crates/api/src/atom.rs @@ -16,9 +16,9 @@ mod atom_test; use crate::{ is_compatible_with::DefaultCompatibility, - parser::{Classification, Property, UcumSymbol}, + parser::{Property, UcumSymbol}, reducible::Reducible, - UcumUnit, Unit, + Classification, UcumUnit, Unit, }; #[allow(clippy::wildcard_imports)] diff --git a/crates/api/src/atom/atom_test.rs b/crates/api/src/atom/atom_test.rs index 8bb7690a..11e751e3 100644 --- a/crates/api/src/atom/atom_test.rs +++ b/crates/api/src/atom/atom_test.rs @@ -5,9 +5,9 @@ use approx::{assert_relative_eq, assert_ulps_eq}; use crate::{ - parser::{term::UNITY_ARRAY, Classification, Composition, Dimension, Prefix, UcumSymbol}, + parser::{term::UNITY_ARRAY, Composition, Dimension, Prefix, UcumSymbol}, ucum_unit::UcumUnit, - Atom, Composable, + Atom, Classification, Composable, }; macro_rules! validate_definition { diff --git a/crates/api/src/parser/classification.rs b/crates/api/src/classification.rs similarity index 100% rename from crates/api/src/parser/classification.rs rename to crates/api/src/classification.rs diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 09c6acc3..23ce39b8 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -23,6 +23,7 @@ mod macros; pub mod as_fraction; pub mod atom; +pub mod classification; pub mod convertible; pub mod error; pub mod field_eq; @@ -38,15 +39,13 @@ mod ucum_unit; pub use crate::{ atom::Atom, + classification::Classification, convertible::Convertible, error::Error, field_eq::FieldEq, is_compatible_with::IsCompatibleWith, measurement::Measurement, - parser::{ - composition, Classification, Composable, Composition, Dimension, Prefix, Property, Term, - UcumSymbol, - }, + parser::{composition, Composable, Composition, Dimension, Prefix, Property, Term, UcumSymbol}, ucum_unit::UcumUnit, unit::Unit, }; diff --git a/crates/api/src/parser.rs b/crates/api/src/parser.rs index b95eab33..1433c4db 100644 --- a/crates/api/src/parser.rs +++ b/crates/api/src/parser.rs @@ -12,7 +12,6 @@ clippy::non_ascii_literal ) )] -pub mod classification; pub mod composition; #[allow(clippy::non_ascii_literal)] pub mod property; @@ -33,9 +32,9 @@ use pest::{iterators::Pair, Parser}; use crate::Atom; pub use self::{ - annotation_composition::AnnotationComposition, classification::Classification, - composable::Composable, composition::Composition, dimension::Dimension, error::Error, - prefix::Prefix, property::Property, term::Term, ucum_symbol::UcumSymbol, + annotation_composition::AnnotationComposition, composable::Composable, + composition::Composition, dimension::Dimension, error::Error, prefix::Prefix, + property::Property, term::Term, ucum_symbol::UcumSymbol, }; use self::{ diff --git a/crates/api/src/parser/prefix.rs b/crates/api/src/parser/prefix.rs index d9ab6b88..54b22779 100644 --- a/crates/api/src/parser/prefix.rs +++ b/crates/api/src/parser/prefix.rs @@ -1,12 +1,16 @@ mod num_traits; -use super::{Error, Visit}; +use std::fmt; + +use pest::iterators::Pair; + use crate::{ - parser::{symbols::symbol_parser::Rule, ucum_symbol::UcumSymbol, Classification}, + parser::{symbols::symbol_parser::Rule, ucum_symbol::UcumSymbol}, unit::{self, Unit}, + Classification, }; -use pest::iterators::Pair; -use std::fmt; + +use super::{Error, Visit}; const DECI: f64 = 1.0e-1; const CENTI: f64 = 1.0e-2; diff --git a/crates/api/src/parser/ucum_symbol.rs b/crates/api/src/parser/ucum_symbol.rs index c8e524b4..00bce97b 100644 --- a/crates/api/src/parser/ucum_symbol.rs +++ b/crates/api/src/parser/ucum_symbol.rs @@ -1,4 +1,4 @@ -use crate::{parser::Classification, unit::Unit}; +use crate::{Classification, Unit}; pub trait UcumSymbol: Send + Sync + Copy + Clone { fn classification(&self) -> Classification; diff --git a/crates/atom_generator/src/generator.rs b/crates/atom_generator/src/generator.rs index b9b1926f..2311aa1a 100644 --- a/crates/atom_generator/src/generator.rs +++ b/crates/atom_generator/src/generator.rs @@ -44,7 +44,7 @@ pub(crate) fn generate_files(rust_atom_list: &RustAtomList) { fn generate_classification_file(rust_atom_list: &RustAtomList) { let file_body = self::classification::generate_file_body(rust_atom_list); - let file_path = build_file_path("parser/classification.rs"); + let file_path = build_file_path("classification.rs"); write_project_file(&file_path, &file_body, true); } diff --git a/crates/atom_generator/src/generator/atom.rs b/crates/atom_generator/src/generator/atom.rs index 85cf3f76..360c2a83 100644 --- a/crates/atom_generator/src/generator/atom.rs +++ b/crates/atom_generator/src/generator/atom.rs @@ -29,9 +29,9 @@ pub(super) fn generate_file_body(atom_list: &RustAtomList) -> String { use crate::{ is_compatible_with::DefaultCompatibility, - parser::{Classification, Property, UcumSymbol}, + parser::{Property, UcumSymbol}, reducible::Reducible, - UcumUnit, Unit, + Classification, UcumUnit, Unit, }; #[allow(clippy::wildcard_imports)] From 144d680776458ebc3fcc4d3a7a2395b445d3e7d6 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 25 Mar 2024 14:12:55 -0700 Subject: [PATCH 48/80] PLCC-299 Move UcumSymbol to root --- crates/api/src/atom.rs | 6 ++---- crates/api/src/atom/atom_test.rs | 4 ++-- crates/api/src/lib.rs | 4 +++- crates/api/src/parser.rs | 3 +-- crates/api/src/parser/prefix.rs | 10 ++++++---- crates/api/src/parser/term/reducible.rs | 2 +- crates/api/src/{parser => }/ucum_symbol.rs | 0 crates/atom_generator/src/generator/atom.rs | 6 ++---- 8 files changed, 17 insertions(+), 18 deletions(-) rename crates/api/src/{parser => }/ucum_symbol.rs (100%) diff --git a/crates/api/src/atom.rs b/crates/api/src/atom.rs index e5a618a8..1cbf28cb 100644 --- a/crates/api/src/atom.rs +++ b/crates/api/src/atom.rs @@ -15,10 +15,8 @@ mod reducible; mod atom_test; use crate::{ - is_compatible_with::DefaultCompatibility, - parser::{Property, UcumSymbol}, - reducible::Reducible, - Classification, UcumUnit, Unit, + is_compatible_with::DefaultCompatibility, parser::Property, reducible::Reducible, + Classification, UcumSymbol, UcumUnit, Unit, }; #[allow(clippy::wildcard_imports)] diff --git a/crates/api/src/atom/atom_test.rs b/crates/api/src/atom/atom_test.rs index 11e751e3..e2f3ef79 100644 --- a/crates/api/src/atom/atom_test.rs +++ b/crates/api/src/atom/atom_test.rs @@ -5,9 +5,9 @@ use approx::{assert_relative_eq, assert_ulps_eq}; use crate::{ - parser::{term::UNITY_ARRAY, Composition, Dimension, Prefix, UcumSymbol}, + parser::{term::UNITY_ARRAY, Composition, Dimension, Prefix}, ucum_unit::UcumUnit, - Atom, Classification, Composable, + Atom, Classification, Composable, UcumSymbol, }; macro_rules! validate_definition { diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 23ce39b8..4a1cce2a 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -32,6 +32,7 @@ pub mod is_compatible_with; pub mod measurement; pub mod parser; pub mod reduce; +mod ucum_symbol; pub mod unit; mod reducible; @@ -45,7 +46,8 @@ pub use crate::{ field_eq::FieldEq, is_compatible_with::IsCompatibleWith, measurement::Measurement, - parser::{composition, Composable, Composition, Dimension, Prefix, Property, Term, UcumSymbol}, + parser::{composition, Composable, Composition, Dimension, Prefix, Property, Term}, + ucum_symbol::UcumSymbol, ucum_unit::UcumUnit, unit::Unit, }; diff --git a/crates/api/src/parser.rs b/crates/api/src/parser.rs index 1433c4db..f6b5db4b 100644 --- a/crates/api/src/parser.rs +++ b/crates/api/src/parser.rs @@ -25,7 +25,6 @@ mod error; mod prefix; pub(crate) mod term; mod terms; -mod ucum_symbol; use pest::{iterators::Pair, Parser}; @@ -34,7 +33,7 @@ use crate::Atom; pub use self::{ annotation_composition::AnnotationComposition, composable::Composable, composition::Composition, dimension::Dimension, error::Error, prefix::Prefix, - property::Property, term::Term, ucum_symbol::UcumSymbol, + property::Property, term::Term, }; use self::{ diff --git a/crates/api/src/parser/prefix.rs b/crates/api/src/parser/prefix.rs index 54b22779..b9bd6f8a 100644 --- a/crates/api/src/parser/prefix.rs +++ b/crates/api/src/parser/prefix.rs @@ -5,9 +5,9 @@ use std::fmt; use pest::iterators::Pair; use crate::{ - parser::{symbols::symbol_parser::Rule, ucum_symbol::UcumSymbol}, + parser::symbols::symbol_parser::Rule, unit::{self, Unit}, - Classification, + Classification, UcumSymbol, }; use super::{Error, Visit}; @@ -272,10 +272,12 @@ impl fmt::Display for Prefix { #[cfg(test)] mod tests { - use super::Prefix; - use crate::parser::ucum_symbol::UcumSymbol; use approx::{assert_relative_eq, assert_ulps_eq}; + use super::*; + + use crate::UcumSymbol; + macro_rules! validate_value { ($test_name:ident, $variant:ident, $value:expr) => { #[test] diff --git a/crates/api/src/parser/term/reducible.rs b/crates/api/src/parser/term/reducible.rs index f9f77e58..c0fe1122 100644 --- a/crates/api/src/parser/term/reducible.rs +++ b/crates/api/src/parser/term/reducible.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use num_traits::One; -use crate::{parser::ucum_symbol::UcumSymbol, reducible::Reducible}; +use crate::{reducible::Reducible, UcumSymbol}; use super::{Exponent, Factor, Term}; diff --git a/crates/api/src/parser/ucum_symbol.rs b/crates/api/src/ucum_symbol.rs similarity index 100% rename from crates/api/src/parser/ucum_symbol.rs rename to crates/api/src/ucum_symbol.rs diff --git a/crates/atom_generator/src/generator/atom.rs b/crates/atom_generator/src/generator/atom.rs index 360c2a83..0998e977 100644 --- a/crates/atom_generator/src/generator/atom.rs +++ b/crates/atom_generator/src/generator/atom.rs @@ -28,10 +28,8 @@ pub(super) fn generate_file_body(atom_list: &RustAtomList) -> String { mod reducible; use crate::{ - is_compatible_with::DefaultCompatibility, - parser::{Property, UcumSymbol}, - reducible::Reducible, - Classification, UcumUnit, Unit, + is_compatible_with::DefaultCompatibility, parser::Property, reducible::Reducible, + Classification, UcumSymbol, UcumUnit, Unit, }; #[allow(clippy::wildcard_imports)] From 1e2dfbc3ae0494ff262ab4eedcb7ae1a73173006 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 25 Mar 2024 14:22:05 -0700 Subject: [PATCH 49/80] PLCC-299 Move Composable to root --- crates/api/src/atom/atom_test.rs | 2 +- crates/api/src/{parser => }/composable.rs | 0 crates/api/src/is_compatible_with.rs | 4 ++-- crates/api/src/lib.rs | 4 +++- crates/api/src/macros.rs | 2 +- crates/api/src/measurement/composable.rs | 12 ++++-------- crates/api/src/parser.rs | 6 ++---- crates/api/src/parser/term/composable.rs | 6 ++++-- crates/api/src/parser/term/display.rs | 2 +- crates/api/src/parser/term/is_compatible_with.rs | 6 +++--- crates/api/src/parser/term/reducible.rs | 2 +- crates/api/src/parser/terms/mapper.rs | 5 +---- crates/api/src/unit/composable.rs | 13 +++++-------- crates/api/src/unit/to_reduced.rs | 7 +------ 14 files changed, 29 insertions(+), 42 deletions(-) rename crates/api/src/{parser => }/composable.rs (100%) diff --git a/crates/api/src/atom/atom_test.rs b/crates/api/src/atom/atom_test.rs index e2f3ef79..7a3380ff 100644 --- a/crates/api/src/atom/atom_test.rs +++ b/crates/api/src/atom/atom_test.rs @@ -5,7 +5,7 @@ use approx::{assert_relative_eq, assert_ulps_eq}; use crate::{ - parser::{term::UNITY_ARRAY, Composition, Dimension, Prefix}, + parser::{term::UNITY_ARRAY, Composition, Dimension}, ucum_unit::UcumUnit, Atom, Classification, Composable, UcumSymbol, }; diff --git a/crates/api/src/parser/composable.rs b/crates/api/src/composable.rs similarity index 100% rename from crates/api/src/parser/composable.rs rename to crates/api/src/composable.rs diff --git a/crates/api/src/is_compatible_with.rs b/crates/api/src/is_compatible_with.rs index ec69dd75..0744136f 100644 --- a/crates/api/src/is_compatible_with.rs +++ b/crates/api/src/is_compatible_with.rs @@ -1,4 +1,4 @@ -use crate::parser::Composable; +use crate::Composable; /// A simple trait for defining how a type should be compared to another type to see if they're /// compatible. Typically this comparison is made via each type's `Composition`, but the trait @@ -8,7 +8,7 @@ pub trait IsCompatibleWith { fn is_compatible_with(&self, rhs: &RHS) -> bool; } -/// Marker trait to allow for auto-implementing `IsCompatibleWith` using the default implemntation. +/// Marker trait to allow for auto-implementing `IsCompatibleWith` using the default implementation. /// pub trait DefaultCompatibility {} diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 4a1cce2a..aea572a9 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -24,6 +24,7 @@ mod macros; pub mod as_fraction; pub mod atom; pub mod classification; +mod composable; pub mod convertible; pub mod error; pub mod field_eq; @@ -41,12 +42,13 @@ mod ucum_unit; pub use crate::{ atom::Atom, classification::Classification, + composable::Composable, convertible::Convertible, error::Error, field_eq::FieldEq, is_compatible_with::IsCompatibleWith, measurement::Measurement, - parser::{composition, Composable, Composition, Dimension, Prefix, Property, Term}, + parser::{composition, Composition, Dimension, Prefix, Property, Term}, ucum_symbol::UcumSymbol, ucum_unit::UcumUnit, unit::Unit, diff --git a/crates/api/src/macros.rs b/crates/api/src/macros.rs index 0db2ae83..1d38c919 100644 --- a/crates/api/src/macros.rs +++ b/crates/api/src/macros.rs @@ -28,7 +28,7 @@ macro_rules! term { }; ($prefix:ident, $atom:ident) => { - $crate::Term::new(Some(Prefix::$prefix), Some($crate::Atom::$atom)) + $crate::Term::new(Some($crate::Prefix::$prefix), Some($crate::Atom::$atom)) }; ($atom:ident, $($attribute_name:ident: $attribute_value:expr),+) => { diff --git a/crates/api/src/measurement/composable.rs b/crates/api/src/measurement/composable.rs index 63f63014..7f8235f2 100644 --- a/crates/api/src/measurement/composable.rs +++ b/crates/api/src/measurement/composable.rs @@ -1,7 +1,4 @@ -use crate::{ - measurement::Measurement, - parser::{Composable, Composition}, -}; +use crate::{parser::Composition, Composable, Measurement}; //----------------------------------------------------------------------------- // impl Composable @@ -18,10 +15,9 @@ impl Composable for Measurement { // #[cfg(test)] mod tests { - use crate::{ - measurement::Measurement, - parser::{Composable, Composition, Dimension}, - }; + use crate::Dimension; + + use super::*; #[test] fn validate_composition() { diff --git a/crates/api/src/parser.rs b/crates/api/src/parser.rs index f6b5db4b..6e57f1d8 100644 --- a/crates/api/src/parser.rs +++ b/crates/api/src/parser.rs @@ -19,7 +19,6 @@ pub mod property; mod symbols; mod annotation_composition; -mod composable; mod dimension; mod error; mod prefix; @@ -31,9 +30,8 @@ use pest::{iterators::Pair, Parser}; use crate::Atom; pub use self::{ - annotation_composition::AnnotationComposition, composable::Composable, - composition::Composition, dimension::Dimension, error::Error, prefix::Prefix, - property::Property, term::Term, + annotation_composition::AnnotationComposition, composition::Composition, dimension::Dimension, + error::Error, prefix::Prefix, property::Property, term::Term, }; use self::{ diff --git a/crates/api/src/parser/term/composable.rs b/crates/api/src/parser/term/composable.rs index 3a796ff9..9999f028 100644 --- a/crates/api/src/parser/term/composable.rs +++ b/crates/api/src/parser/term/composable.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use crate::parser::{Composable, Composition}; +use crate::{parser::Composition, Composable}; use super::Term; @@ -34,7 +34,9 @@ impl<'a> Composable for Cow<'a, [Term]> { #[cfg(test)] mod tests { - use crate::parser::{Composable, Composition, Dimension, Prefix}; + use crate::Dimension; + + use super::*; macro_rules! validate_composition { ($test_name:ident, $term:expr, $expected_value:expr) => { diff --git a/crates/api/src/parser/term/display.rs b/crates/api/src/parser/term/display.rs index 568ddff2..21429061 100644 --- a/crates/api/src/parser/term/display.rs +++ b/crates/api/src/parser/term/display.rs @@ -53,7 +53,7 @@ fn extract_term_string_atom(term_string: &mut String, term: &Term) { #[cfg(test)] mod tests { - use crate::parser::{term::UNITY, Prefix, Term}; + use crate::parser::{term::UNITY, Term}; macro_rules! validate_display { ($test_name:ident, $term:expr, $output:expr) => { diff --git a/crates/api/src/parser/term/is_compatible_with.rs b/crates/api/src/parser/term/is_compatible_with.rs index b72c4b8f..763dff91 100644 --- a/crates/api/src/parser/term/is_compatible_with.rs +++ b/crates/api/src/parser/term/is_compatible_with.rs @@ -1,8 +1,8 @@ use std::borrow::Cow; use crate::{ - is_compatible_with::IsCompatibleWith, - parser::{annotation_composition::AnnotationComposable, Composable, Term}, + parser::{annotation_composition::AnnotationComposable, Term}, + Composable, IsCompatibleWith, }; /// In order to enforce compatibility on "non-units" (ex. `{each}`, `{total}`, `{heartbeats}`), @@ -52,7 +52,7 @@ impl<'a> IsCompatibleWith for Cow<'a, [Term]> { #[cfg(test)] mod tests { - use crate::{is_compatible_with::IsCompatibleWith, parser::Prefix}; + use crate::is_compatible_with::IsCompatibleWith; mod without_annotations { use super::*; diff --git a/crates/api/src/parser/term/reducible.rs b/crates/api/src/parser/term/reducible.rs index c0fe1122..3cc44fbd 100644 --- a/crates/api/src/parser/term/reducible.rs +++ b/crates/api/src/parser/term/reducible.rs @@ -56,7 +56,7 @@ fn combine_term_values( #[cfg(test)] mod tests { - use crate::{parser::Prefix, reducible::Reducible}; + use crate::reducible::Reducible; use approx::assert_relative_eq; macro_rules! validate_reduce_value { diff --git a/crates/api/src/parser/terms/mapper.rs b/crates/api/src/parser/terms/mapper.rs index 108b0619..65739a4c 100644 --- a/crates/api/src/parser/terms/mapper.rs +++ b/crates/api/src/parser/terms/mapper.rs @@ -50,10 +50,7 @@ pub(crate) fn map(mut pairs: Pairs<'_, Rule>) -> Result, Error> { #[cfg(test)] mod tests { use super::*; - use crate::parser::{ - terms::term_parser::{Rule, TermParser}, - Prefix, - }; + use crate::parser::terms::term_parser::{Rule, TermParser}; use pest::Parser; macro_rules! validate_interpret { diff --git a/crates/api/src/unit/composable.rs b/crates/api/src/unit/composable.rs index d62ba3cb..2e5aeb3b 100644 --- a/crates/api/src/unit/composable.rs +++ b/crates/api/src/unit/composable.rs @@ -1,7 +1,4 @@ -use crate::{ - parser::{Composable, Composition}, - unit::Unit, -}; +use crate::{parser::Composition, Composable, Unit}; //----------------------------------------------------------------------------- // impl Composable @@ -15,12 +12,12 @@ impl Composable for Unit { #[cfg(test)] mod tests { - use crate::{ - parser::{Composable, Composition, Dimension}, - unit::Unit, - }; use std::str::FromStr; + use crate::Dimension; + + use super::*; + macro_rules! build_composition { ( @params diff --git a/crates/api/src/unit/to_reduced.rs b/crates/api/src/unit/to_reduced.rs index a6df2565..ca462bc0 100644 --- a/crates/api/src/unit/to_reduced.rs +++ b/crates/api/src/unit/to_reduced.rs @@ -1,9 +1,4 @@ -use crate::{ - as_fraction::AsFraction, - parser::{Composable, Composition}, - reduce::ToReduced, - Term, -}; +use crate::{as_fraction::AsFraction, parser::Composition, reduce::ToReduced, Composable, Term}; use super::Unit; From ed1ab63019155fa960bdf270f4c43de1969d222c Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 25 Mar 2024 15:48:03 -0700 Subject: [PATCH 50/80] PLCC-299 Move Composition to root --- crates/api/src/atom/atom_test.rs | 4 ++-- crates/api/src/composable.rs | 2 +- crates/api/src/{parser => }/composition.rs | 3 ++- crates/api/src/lib.rs | 4 +++- crates/api/src/measurement/composable.rs | 2 +- crates/api/src/parser.rs | 5 ++--- crates/api/src/parser/term/composable.rs | 2 +- crates/api/src/unit/composable.rs | 2 +- crates/api/src/unit/to_reduced.rs | 2 +- 9 files changed, 14 insertions(+), 12 deletions(-) rename crates/api/src/{parser => }/composition.rs (99%) diff --git a/crates/api/src/atom/atom_test.rs b/crates/api/src/atom/atom_test.rs index 7a3380ff..75456650 100644 --- a/crates/api/src/atom/atom_test.rs +++ b/crates/api/src/atom/atom_test.rs @@ -5,9 +5,9 @@ use approx::{assert_relative_eq, assert_ulps_eq}; use crate::{ - parser::{term::UNITY_ARRAY, Composition, Dimension}, + parser::{term::UNITY_ARRAY, Dimension}, ucum_unit::UcumUnit, - Atom, Classification, Composable, UcumSymbol, + Atom, Classification, Composable, Composition, UcumSymbol, }; macro_rules! validate_definition { diff --git a/crates/api/src/composable.rs b/crates/api/src/composable.rs index 02610f1c..9e43c8d5 100644 --- a/crates/api/src/composable.rs +++ b/crates/api/src/composable.rs @@ -1,4 +1,4 @@ -use crate::parser::Composition; +use crate::Composition; /// A simple trait for getting a type to define how its `Composition` should be built. Typically /// `Composition`s are used to determine the compatibility with another type; so long as each type diff --git a/crates/api/src/parser/composition.rs b/crates/api/src/composition.rs similarity index 99% rename from crates/api/src/parser/composition.rs rename to crates/api/src/composition.rs index fb278ed9..d99307c4 100644 --- a/crates/api/src/parser/composition.rs +++ b/crates/api/src/composition.rs @@ -1,6 +1,7 @@ -use super::{term::Exponent, Dimension}; use std::{fmt, ops::Mul}; +use crate::parser::{term::Exponent, Dimension}; + pub const DIMLESS: Composition = Composition::new_dimless(); pub const ELECTRIC_CHARGE: Composition = Composition::new_electric_charge(1); diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index aea572a9..ab15050e 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -25,6 +25,7 @@ pub mod as_fraction; pub mod atom; pub mod classification; mod composable; +pub mod composition; pub mod convertible; pub mod error; pub mod field_eq; @@ -43,12 +44,13 @@ pub use crate::{ atom::Atom, classification::Classification, composable::Composable, + composition::Composition, convertible::Convertible, error::Error, field_eq::FieldEq, is_compatible_with::IsCompatibleWith, measurement::Measurement, - parser::{composition, Composition, Dimension, Prefix, Property, Term}, + parser::{Dimension, Prefix, Property, Term}, ucum_symbol::UcumSymbol, ucum_unit::UcumUnit, unit::Unit, diff --git a/crates/api/src/measurement/composable.rs b/crates/api/src/measurement/composable.rs index 7f8235f2..1d474e40 100644 --- a/crates/api/src/measurement/composable.rs +++ b/crates/api/src/measurement/composable.rs @@ -1,4 +1,4 @@ -use crate::{parser::Composition, Composable, Measurement}; +use crate::{Composable, Composition, Measurement}; //----------------------------------------------------------------------------- // impl Composable diff --git a/crates/api/src/parser.rs b/crates/api/src/parser.rs index 6e57f1d8..027b5df6 100644 --- a/crates/api/src/parser.rs +++ b/crates/api/src/parser.rs @@ -12,7 +12,6 @@ clippy::non_ascii_literal ) )] -pub mod composition; #[allow(clippy::non_ascii_literal)] pub mod property; @@ -30,8 +29,8 @@ use pest::{iterators::Pair, Parser}; use crate::Atom; pub use self::{ - annotation_composition::AnnotationComposition, composition::Composition, dimension::Dimension, - error::Error, prefix::Prefix, property::Property, term::Term, + annotation_composition::AnnotationComposition, dimension::Dimension, error::Error, + prefix::Prefix, property::Property, term::Term, }; use self::{ diff --git a/crates/api/src/parser/term/composable.rs b/crates/api/src/parser/term/composable.rs index 9999f028..f225a44b 100644 --- a/crates/api/src/parser/term/composable.rs +++ b/crates/api/src/parser/term/composable.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use crate::{parser::Composition, Composable}; +use crate::{Composable, Composition}; use super::Term; diff --git a/crates/api/src/unit/composable.rs b/crates/api/src/unit/composable.rs index 2e5aeb3b..b5c37a6b 100644 --- a/crates/api/src/unit/composable.rs +++ b/crates/api/src/unit/composable.rs @@ -1,4 +1,4 @@ -use crate::{parser::Composition, Composable, Unit}; +use crate::{Composable, Composition, Unit}; //----------------------------------------------------------------------------- // impl Composable diff --git a/crates/api/src/unit/to_reduced.rs b/crates/api/src/unit/to_reduced.rs index ca462bc0..def6ca1a 100644 --- a/crates/api/src/unit/to_reduced.rs +++ b/crates/api/src/unit/to_reduced.rs @@ -1,4 +1,4 @@ -use crate::{as_fraction::AsFraction, parser::Composition, reduce::ToReduced, Composable, Term}; +use crate::{as_fraction::AsFraction, reduce::ToReduced, Composable, Composition, Term}; use super::Unit; From 1e418d3426d45c49dfc8bda723b3df14a5f34008 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 25 Mar 2024 15:49:58 -0700 Subject: [PATCH 51/80] PLCC-299 Move Dimension to root --- crates/api/src/atom/atom_test.rs | 5 ++--- crates/api/src/composition.rs | 2 +- crates/api/src/{parser => }/dimension.rs | 0 crates/api/src/lib.rs | 4 +++- crates/api/src/parser.rs | 5 ++--- 5 files changed, 8 insertions(+), 8 deletions(-) rename crates/api/src/{parser => }/dimension.rs (100%) diff --git a/crates/api/src/atom/atom_test.rs b/crates/api/src/atom/atom_test.rs index 75456650..a189cf97 100644 --- a/crates/api/src/atom/atom_test.rs +++ b/crates/api/src/atom/atom_test.rs @@ -5,9 +5,8 @@ use approx::{assert_relative_eq, assert_ulps_eq}; use crate::{ - parser::{term::UNITY_ARRAY, Dimension}, - ucum_unit::UcumUnit, - Atom, Classification, Composable, Composition, UcumSymbol, + parser::term::UNITY_ARRAY, ucum_unit::UcumUnit, Atom, Classification, Composable, Composition, + Dimension, UcumSymbol, }; macro_rules! validate_definition { diff --git a/crates/api/src/composition.rs b/crates/api/src/composition.rs index d99307c4..cdfa9c37 100644 --- a/crates/api/src/composition.rs +++ b/crates/api/src/composition.rs @@ -1,6 +1,6 @@ use std::{fmt, ops::Mul}; -use crate::parser::{term::Exponent, Dimension}; +use crate::{parser::term::Exponent, Dimension}; pub const DIMLESS: Composition = Composition::new_dimless(); diff --git a/crates/api/src/parser/dimension.rs b/crates/api/src/dimension.rs similarity index 100% rename from crates/api/src/parser/dimension.rs rename to crates/api/src/dimension.rs diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index ab15050e..ea19c015 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -27,6 +27,7 @@ pub mod classification; mod composable; pub mod composition; pub mod convertible; +mod dimension; pub mod error; pub mod field_eq; pub mod invert; @@ -46,11 +47,12 @@ pub use crate::{ composable::Composable, composition::Composition, convertible::Convertible, + dimension::Dimension, error::Error, field_eq::FieldEq, is_compatible_with::IsCompatibleWith, measurement::Measurement, - parser::{Dimension, Prefix, Property, Term}, + parser::{Prefix, Property, Term}, ucum_symbol::UcumSymbol, ucum_unit::UcumUnit, unit::Unit, diff --git a/crates/api/src/parser.rs b/crates/api/src/parser.rs index 027b5df6..7a01285a 100644 --- a/crates/api/src/parser.rs +++ b/crates/api/src/parser.rs @@ -18,7 +18,6 @@ pub mod property; mod symbols; mod annotation_composition; -mod dimension; mod error; mod prefix; pub(crate) mod term; @@ -29,8 +28,8 @@ use pest::{iterators::Pair, Parser}; use crate::Atom; pub use self::{ - annotation_composition::AnnotationComposition, dimension::Dimension, error::Error, - prefix::Prefix, property::Property, term::Term, + annotation_composition::AnnotationComposition, error::Error, prefix::Prefix, + property::Property, term::Term, }; use self::{ From 624756cebbd3b5dda6c078da435dd626c2ad1b9a Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 25 Mar 2024 16:20:36 -0700 Subject: [PATCH 52/80] PLCC-299 Move Prefix to root --- crates/api/src/lib.rs | 4 +- crates/api/src/macros.rs | 5 +- crates/api/src/parser.rs | 48 +++++++++++++++---- crates/api/src/parser/symbols/symbol.rs | 6 ++- crates/api/src/parser/term.rs | 2 +- crates/api/src/parser/terms/mapper.rs | 11 ++++- .../src/parser/terms/mapper/annotatable.rs | 6 ++- .../api/src/parser/terms/mapper/annotation.rs | 4 +- .../api/src/parser/terms/mapper/ast_term.rs | 4 +- .../parser/terms/mapper/basic_component.rs | 4 +- .../api/src/parser/terms/mapper/component.rs | 4 +- crates/api/src/parser/terms/mapper/digits.rs | 4 +- .../api/src/parser/terms/mapper/exponent.rs | 4 +- crates/api/src/parser/terms/mapper/factor.rs | 4 +- .../api/src/parser/terms/mapper/main_term.rs | 4 +- .../src/parser/terms/mapper/simple_unit.rs | 20 ++++---- crates/api/src/{parser => }/prefix.rs | 41 ---------------- .../api/src/{parser => }/prefix/num_traits.rs | 0 .../{parser => }/prefix/num_traits/cast.rs | 2 +- 19 files changed, 90 insertions(+), 87 deletions(-) rename crates/api/src/{parser => }/prefix.rs (82%) rename crates/api/src/{parser => }/prefix/num_traits.rs (100%) rename crates/api/src/{parser => }/prefix/num_traits/cast.rs (99%) diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index ea19c015..a2463a48 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -34,6 +34,7 @@ pub mod invert; pub mod is_compatible_with; pub mod measurement; pub mod parser; +mod prefix; pub mod reduce; mod ucum_symbol; pub mod unit; @@ -52,7 +53,8 @@ pub use crate::{ field_eq::FieldEq, is_compatible_with::IsCompatibleWith, measurement::Measurement, - parser::{Prefix, Property, Term}, + parser::{Property, Term}, + prefix::Prefix, ucum_symbol::UcumSymbol, ucum_unit::UcumUnit, unit::Unit, diff --git a/crates/api/src/macros.rs b/crates/api/src/macros.rs index 1d38c919..f793b543 100644 --- a/crates/api/src/macros.rs +++ b/crates/api/src/macros.rs @@ -69,10 +69,7 @@ macro_rules! terms { #[cfg(test)] mod tests { - use crate::{ - parser::{Prefix, Term}, - Atom, - }; + use crate::{parser::Term, Atom, Prefix}; #[test] fn validate_term_macro() { diff --git a/crates/api/src/parser.rs b/crates/api/src/parser.rs index 7a01285a..4f0ff94b 100644 --- a/crates/api/src/parser.rs +++ b/crates/api/src/parser.rs @@ -19,17 +19,15 @@ mod symbols; mod annotation_composition; mod error; -mod prefix; pub(crate) mod term; mod terms; use pest::{iterators::Pair, Parser}; -use crate::Atom; +use crate::{Atom, Prefix}; pub use self::{ - annotation_composition::AnnotationComposition, error::Error, prefix::Prefix, - property::Property, term::Term, + annotation_composition::AnnotationComposition, error::Error, property::Property, term::Term, }; use self::{ @@ -51,6 +49,41 @@ trait Visit { Self: Sized; } +impl Visit for Prefix { + fn visit(pair: Pair<'_, SymbolRule>) -> Result { + let prefix = match pair.as_rule() { + SymbolRule::pri_atto | SymbolRule::sec_atto => Self::Atto, + SymbolRule::pri_centi | SymbolRule::sec_centi => Self::Centi, + SymbolRule::pri_deci | SymbolRule::sec_deci => Self::Deci, + SymbolRule::pri_deka | SymbolRule::sec_deka => Self::Deka, + SymbolRule::pri_exa | SymbolRule::sec_exa => Self::Exa, + SymbolRule::pri_femto | SymbolRule::sec_femto => Self::Femto, + SymbolRule::pri_gibi | SymbolRule::sec_gibi => Self::Gibi, + SymbolRule::pri_giga | SymbolRule::sec_giga => Self::Giga, + SymbolRule::pri_hecto | SymbolRule::sec_hecto => Self::Hecto, + SymbolRule::pri_kibi | SymbolRule::sec_kibi => Self::Kibi, + SymbolRule::pri_kilo | SymbolRule::sec_kilo => Self::Kilo, + SymbolRule::pri_mebi | SymbolRule::sec_mebi => Self::Mebi, + SymbolRule::pri_mega | SymbolRule::sec_mega => Self::Mega, + SymbolRule::pri_micro | SymbolRule::sec_micro => Self::Micro, + SymbolRule::pri_milli | SymbolRule::sec_milli => Self::Milli, + SymbolRule::pri_nano | SymbolRule::sec_nano => Self::Nano, + SymbolRule::pri_peta | SymbolRule::sec_peta => Self::Peta, + SymbolRule::pri_tebi | SymbolRule::sec_tebi => Self::Tebi, + SymbolRule::pri_tera | SymbolRule::sec_tera => Self::Tera, + SymbolRule::pri_yocto | SymbolRule::sec_yocto => Self::Yocto, + SymbolRule::pri_yotta | SymbolRule::sec_yotta => Self::Yotta, + SymbolRule::pri_zepto | SymbolRule::sec_zepto => Self::Zepto, + SymbolRule::pri_zetta | SymbolRule::sec_zetta => Self::Zetta, + t => { + unreachable!("expected prefix symbol, got {t:?}"); + } + }; + + Ok(prefix) + } +} + // TODO: Move to atom_generator. // #[allow(clippy::too_many_lines)] @@ -621,11 +654,8 @@ impl Visit for Atom { } SymbolRule::pri_yard_us | SymbolRule::sec_yard_us => Self::YardUS, SymbolRule::pri_year | SymbolRule::sec_year => Self::Year, - _ => { - return Err(Error::BadFragment { - fragment: pair.as_span().as_str().to_string(), - position: pair.as_span().start(), - }); + t => { + unreachable!("expected atom symbol, got {t:?}"); } }; diff --git a/crates/api/src/parser/symbols/symbol.rs b/crates/api/src/parser/symbols/symbol.rs index f935b9ed..400c66a7 100644 --- a/crates/api/src/parser/symbols/symbol.rs +++ b/crates/api/src/parser/symbols/symbol.rs @@ -1,6 +1,10 @@ -use crate::parser::{symbols::symbol_parser::Rule, Atom, Error, Prefix, Visit}; use pest::iterators::Pair; +use crate::{ + parser::{symbols::symbol_parser::Rule, Error, Visit}, + Atom, Prefix, +}; + // Technically there should never be a symbol without an atom. #[derive(Debug)] pub(crate) enum Symbol { diff --git a/crates/api/src/parser/term.rs b/crates/api/src/parser/term.rs index 19c66608..097c8f51 100644 --- a/crates/api/src/parser/term.rs +++ b/crates/api/src/parser/term.rs @@ -9,7 +9,7 @@ mod partial_eq; mod reducible; mod ucum_unit; -use crate::parser::{Atom, Prefix}; +use crate::{Atom, Prefix}; pub const UNITY: Term = { Term { diff --git a/crates/api/src/parser/terms/mapper.rs b/crates/api/src/parser/terms/mapper.rs index 65739a4c..8143293a 100644 --- a/crates/api/src/parser/terms/mapper.rs +++ b/crates/api/src/parser/terms/mapper.rs @@ -15,13 +15,20 @@ mod finishable; mod main_term; mod simple_unit; +use pest::iterators::{Pair, Pairs}; + +use crate::{ + parser::{Error, Visit}, + Atom, Prefix, Term, +}; + use self::{ annotatable::Annotatable, annotation::Annotation, ast_term::AstTerm, basic_component::BasicComponent, component::Component, digits::Digits, exponent::Exponent, finishable::Finishable, main_term::MainTerm, simple_unit::SimpleUnit, }; -use crate::parser::{terms::term_parser::Rule, Atom, Error, Prefix, Term, Visit}; -use pest::iterators::{Pair, Pairs}; + +use super::term_parser::Rule; #[allow(clippy::large_enum_variant)] #[allow(clippy::result_large_err)] diff --git a/crates/api/src/parser/terms/mapper/annotatable.rs b/crates/api/src/parser/terms/mapper/annotatable.rs index bd26f724..12b63b36 100644 --- a/crates/api/src/parser/terms/mapper/annotatable.rs +++ b/crates/api/src/parser/terms/mapper/annotatable.rs @@ -1,8 +1,10 @@ use pest::iterators::Pair; -use crate::parser::{term::Exponent as IExponent, terms::term_parser::Rule as TermRule}; +use crate::parser::{ + term::Exponent as IExponent, terms::term_parser::Rule as TermRule, Error, Visit, +}; -use super::{Atom, Error, Exponent, Prefix, SimpleUnit, Visit}; +use super::{Atom, Exponent, Prefix, SimpleUnit}; pub(super) enum Annotatable { PrefixedWithExponent { diff --git a/crates/api/src/parser/terms/mapper/annotation.rs b/crates/api/src/parser/terms/mapper/annotation.rs index cbb92763..f54230e4 100644 --- a/crates/api/src/parser/terms/mapper/annotation.rs +++ b/crates/api/src/parser/terms/mapper/annotation.rs @@ -1,7 +1,7 @@ -use super::{Error, Visit}; -use crate::parser::terms::term_parser::Rule as TermRule; use pest::iterators::Pair; +use crate::parser::{terms::term_parser::Rule as TermRule, Error, Visit}; + pub(super) type Annotation = String; impl Visit for Annotation { diff --git a/crates/api/src/parser/terms/mapper/ast_term.rs b/crates/api/src/parser/terms/mapper/ast_term.rs index c81eed50..3ce8d8d5 100644 --- a/crates/api/src/parser/terms/mapper/ast_term.rs +++ b/crates/api/src/parser/terms/mapper/ast_term.rs @@ -1,8 +1,8 @@ use pest::iterators::Pair; -use crate::parser::terms::term_parser::Rule; +use crate::parser::{terms::term_parser::Rule, Error, Visit}; -use super::{Component, Error, Finishable, Term, Visit}; +use super::{Component, Finishable, Term}; pub(super) struct AstTerm { pub(super) component: Component, diff --git a/crates/api/src/parser/terms/mapper/basic_component.rs b/crates/api/src/parser/terms/mapper/basic_component.rs index 1dfcde79..521c94e0 100644 --- a/crates/api/src/parser/terms/mapper/basic_component.rs +++ b/crates/api/src/parser/terms/mapper/basic_component.rs @@ -1,8 +1,8 @@ use pest::iterators::Pair; -use crate::parser::{term::Factor, terms::term_parser::Rule}; +use crate::parser::{term::Factor, terms::term_parser::Rule, Error, Visit}; -use super::{Annotatable, Annotation, AstTerm, Error, Finishable, Term, Visit}; +use super::{Annotatable, Annotation, AstTerm, Finishable, Term}; pub(super) struct BasicComponent { pub(super) factor: Option, diff --git a/crates/api/src/parser/terms/mapper/component.rs b/crates/api/src/parser/terms/mapper/component.rs index d54de3d7..44249e04 100644 --- a/crates/api/src/parser/terms/mapper/component.rs +++ b/crates/api/src/parser/terms/mapper/component.rs @@ -1,8 +1,8 @@ use pest::iterators::Pair; -use crate::parser::{term::Factor, terms::term_parser::Rule}; +use crate::parser::{term::Factor, terms::term_parser::Rule, Error, Visit}; -use super::{BasicComponent, Error, Finishable, Term, Visit}; +use super::{BasicComponent, Finishable, Term}; pub(super) struct Component { pub(super) factor: Option, diff --git a/crates/api/src/parser/terms/mapper/digits.rs b/crates/api/src/parser/terms/mapper/digits.rs index 99a99529..9ec732b0 100644 --- a/crates/api/src/parser/terms/mapper/digits.rs +++ b/crates/api/src/parser/terms/mapper/digits.rs @@ -1,7 +1,7 @@ -use super::{Error, Visit}; -use crate::parser::terms::term_parser::Rule as TermRule; use pest::iterators::Pair; +use crate::parser::{terms::term_parser::Rule as TermRule, Error, Visit}; + pub(super) type Digits = i32; impl Visit for Digits { diff --git a/crates/api/src/parser/terms/mapper/exponent.rs b/crates/api/src/parser/terms/mapper/exponent.rs index 0bf47f78..b74de672 100644 --- a/crates/api/src/parser/terms/mapper/exponent.rs +++ b/crates/api/src/parser/terms/mapper/exponent.rs @@ -1,8 +1,8 @@ use pest::iterators::Pair; -use crate::parser::{term, terms::term_parser::Rule as TermRule}; +use crate::parser::{term, terms::term_parser::Rule as TermRule, Error, Visit}; -use super::{Digits, Error, Visit}; +use super::Digits; pub(super) struct Exponent(pub(super) term::Exponent); diff --git a/crates/api/src/parser/terms/mapper/factor.rs b/crates/api/src/parser/terms/mapper/factor.rs index d32fe75e..770a0ec7 100644 --- a/crates/api/src/parser/terms/mapper/factor.rs +++ b/crates/api/src/parser/terms/mapper/factor.rs @@ -1,8 +1,6 @@ use pest::iterators::Pair; -use crate::parser::{term, terms::term_parser::Rule as TermRule}; - -use super::{Error, Visit}; +use crate::parser::{term, terms::term_parser::Rule as TermRule, Error, Visit}; impl Visit for term::Factor { fn visit(pair: Pair<'_, TermRule>) -> Result { diff --git a/crates/api/src/parser/terms/mapper/main_term.rs b/crates/api/src/parser/terms/mapper/main_term.rs index 24c39107..23efdfd4 100644 --- a/crates/api/src/parser/terms/mapper/main_term.rs +++ b/crates/api/src/parser/terms/mapper/main_term.rs @@ -1,9 +1,9 @@ use num_traits::Inv; use pest::iterators::Pair; -use crate::parser::{terms::term_parser::Rule, Error, Term}; +use crate::parser::{terms::term_parser::Rule, Error, Term, Visit}; -use super::{AstTerm, Finishable, Visit}; +use super::{AstTerm, Finishable}; pub(super) struct MainTerm { pub(super) terms: Vec, diff --git a/crates/api/src/parser/terms/mapper/simple_unit.rs b/crates/api/src/parser/terms/mapper/simple_unit.rs index e68c5741..40072244 100644 --- a/crates/api/src/parser/terms/mapper/simple_unit.rs +++ b/crates/api/src/parser/terms/mapper/simple_unit.rs @@ -1,13 +1,17 @@ -use super::{Atom, Error, Prefix, Visit}; -use crate::parser::{ - symbols::{ - mapper as symbol_mapper, - symbol_parser::{Rule as SymbolRule, SymbolParser}, - Symbol, +use pest::{iterators::Pair, Parser}; + +use crate::{ + parser::{ + symbols::{ + mapper as symbol_mapper, + symbol_parser::{Rule as SymbolRule, SymbolParser}, + Symbol, + }, + terms::term_parser::Rule as TermRule, + Error, Visit, }, - terms::term_parser::Rule as TermRule, + Atom, Prefix, }; -use pest::{iterators::Pair, Parser}; pub(super) enum SimpleUnit { Prefixed { prefix: Prefix, atom: Atom }, diff --git a/crates/api/src/parser/prefix.rs b/crates/api/src/prefix.rs similarity index 82% rename from crates/api/src/parser/prefix.rs rename to crates/api/src/prefix.rs index b9bd6f8a..ebda3944 100644 --- a/crates/api/src/parser/prefix.rs +++ b/crates/api/src/prefix.rs @@ -2,16 +2,11 @@ mod num_traits; use std::fmt; -use pest::iterators::Pair; - use crate::{ - parser::symbols::symbol_parser::Rule, unit::{self, Unit}, Classification, UcumSymbol, }; -use super::{Error, Visit}; - const DECI: f64 = 1.0e-1; const CENTI: f64 = 1.0e-2; const MILLI: f64 = 1.0e-3; @@ -228,42 +223,6 @@ impl UcumSymbol for Prefix { } } -impl Visit for Prefix { - fn visit(pair: Pair<'_, Rule>) -> Result { - let prefix = match pair.as_rule() { - Rule::pri_atto | Rule::sec_atto => Self::Atto, - Rule::pri_centi | Rule::sec_centi => Self::Centi, - Rule::pri_deci | Rule::sec_deci => Self::Deci, - Rule::pri_deka | Rule::sec_deka => Self::Deka, - Rule::pri_exa | Rule::sec_exa => Self::Exa, - Rule::pri_femto | Rule::sec_femto => Self::Femto, - Rule::pri_gibi | Rule::sec_gibi => Self::Gibi, - Rule::pri_giga | Rule::sec_giga => Self::Giga, - Rule::pri_hecto | Rule::sec_hecto => Self::Hecto, - Rule::pri_kibi | Rule::sec_kibi => Self::Kibi, - Rule::pri_kilo | Rule::sec_kilo => Self::Kilo, - Rule::pri_mebi | Rule::sec_mebi => Self::Mebi, - Rule::pri_mega | Rule::sec_mega => Self::Mega, - Rule::pri_micro | Rule::sec_micro => Self::Micro, - Rule::pri_milli | Rule::sec_milli => Self::Milli, - Rule::pri_nano | Rule::sec_nano => Self::Nano, - Rule::pri_peta | Rule::sec_peta => Self::Peta, - Rule::pri_tebi | Rule::sec_tebi => Self::Tebi, - Rule::pri_tera | Rule::sec_tera => Self::Tera, - Rule::pri_yocto | Rule::sec_yocto => Self::Yocto, - Rule::pri_yotta | Rule::sec_yotta => Self::Yotta, - Rule::pri_zepto | Rule::sec_zepto => Self::Zepto, - Rule::pri_zetta | Rule::sec_zetta => Self::Zetta, - _ => { - eprintln!("prefix wat"); - return Err(Error::UnknownUnitString(pair.as_str().to_string())); - } - }; - - Ok(prefix) - } -} - impl fmt::Display for Prefix { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{}", self.primary_code()) diff --git a/crates/api/src/parser/prefix/num_traits.rs b/crates/api/src/prefix/num_traits.rs similarity index 100% rename from crates/api/src/parser/prefix/num_traits.rs rename to crates/api/src/prefix/num_traits.rs diff --git a/crates/api/src/parser/prefix/num_traits/cast.rs b/crates/api/src/prefix/num_traits/cast.rs similarity index 99% rename from crates/api/src/parser/prefix/num_traits/cast.rs rename to crates/api/src/prefix/num_traits/cast.rs index 8adbb4be..c396a776 100644 --- a/crates/api/src/parser/prefix/num_traits/cast.rs +++ b/crates/api/src/prefix/num_traits/cast.rs @@ -1,6 +1,6 @@ use num_traits::{FromPrimitive, ToPrimitive, Zero}; -use crate::{parser::prefix, Prefix, UcumSymbol}; +use crate::{prefix, Prefix, UcumSymbol}; impl ToPrimitive for Prefix { fn to_u64(&self) -> Option { From 5aa267034e4a35b6e7a05495a2973421e5f8c26c Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 25 Mar 2024 16:23:13 -0700 Subject: [PATCH 53/80] PLCC-299 Move Property to root --- crates/api/src/atom.rs | 4 ++-- crates/api/src/lib.rs | 20 +++++--------------- crates/api/src/parser.rs | 21 ++------------------- crates/api/src/{parser => }/property.rs | 2 +- crates/atom_generator/src/generator.rs | 2 +- crates/atom_generator/src/generator/atom.rs | 4 ++-- 6 files changed, 13 insertions(+), 40 deletions(-) rename crates/api/src/{parser => }/property.rs (99%) diff --git a/crates/api/src/atom.rs b/crates/api/src/atom.rs index 1cbf28cb..dbe9ab21 100644 --- a/crates/api/src/atom.rs +++ b/crates/api/src/atom.rs @@ -15,8 +15,8 @@ mod reducible; mod atom_test; use crate::{ - is_compatible_with::DefaultCompatibility, parser::Property, reducible::Reducible, - Classification, UcumSymbol, UcumUnit, Unit, + is_compatible_with::DefaultCompatibility, reducible::Reducible, Classification, Property, + UcumSymbol, UcumUnit, Unit, }; #[allow(clippy::wildcard_imports)] diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index a2463a48..67286ac0 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -35,6 +35,7 @@ pub mod is_compatible_with; pub mod measurement; pub mod parser; mod prefix; +pub mod property; pub mod reduce; mod ucum_symbol; pub mod unit; @@ -43,19 +44,8 @@ mod reducible; mod ucum_unit; pub use crate::{ - atom::Atom, - classification::Classification, - composable::Composable, - composition::Composition, - convertible::Convertible, - dimension::Dimension, - error::Error, - field_eq::FieldEq, - is_compatible_with::IsCompatibleWith, - measurement::Measurement, - parser::{Property, Term}, - prefix::Prefix, - ucum_symbol::UcumSymbol, - ucum_unit::UcumUnit, - unit::Unit, + atom::Atom, classification::Classification, composable::Composable, composition::Composition, + convertible::Convertible, dimension::Dimension, error::Error, field_eq::FieldEq, + is_compatible_with::IsCompatibleWith, measurement::Measurement, parser::Term, prefix::Prefix, + property::Property, ucum_symbol::UcumSymbol, ucum_unit::UcumUnit, unit::Unit, }; diff --git a/crates/api/src/parser.rs b/crates/api/src/parser.rs index 4f0ff94b..0d63864d 100644 --- a/crates/api/src/parser.rs +++ b/crates/api/src/parser.rs @@ -1,24 +1,9 @@ #![allow(clippy::large_enum_variant)] #![allow(clippy::result_large_err)] -// Because long numbers are generated, there's no way (that I know of) to -// generate them using underscores (to make them pass the clippy lint). -#[cfg_attr( - feature = "cargo-clippy", - allow( - clippy::unreadable_literal, - clippy::match_same_arms, - clippy::too_many_lines, - clippy::non_ascii_literal - ) -)] -#[allow(clippy::non_ascii_literal)] -pub mod property; - -mod symbols; - mod annotation_composition; mod error; +mod symbols; pub(crate) mod term; mod terms; @@ -26,9 +11,7 @@ use pest::{iterators::Pair, Parser}; use crate::{Atom, Prefix}; -pub use self::{ - annotation_composition::AnnotationComposition, error::Error, property::Property, term::Term, -}; +pub use self::{annotation_composition::AnnotationComposition, error::Error, term::Term}; use self::{ symbols::symbol_parser::Rule as SymbolRule, diff --git a/crates/api/src/parser/property.rs b/crates/api/src/property.rs similarity index 99% rename from crates/api/src/parser/property.rs rename to crates/api/src/property.rs index cbf4ecd3..2e8c6f88 100644 --- a/crates/api/src/parser/property.rs +++ b/crates/api/src/property.rs @@ -3,7 +3,7 @@ // This is generated by wise_units-atom_generator. //----------------------------------------------------------------------------- -use crate::parser::Atom; +use crate::Atom; use std::fmt; /// Property categorizes the unit by use. Not much mention of it in the UCUM /// HTML spec, but is used throughout the diff --git a/crates/atom_generator/src/generator.rs b/crates/atom_generator/src/generator.rs index 2311aa1a..acb7bd04 100644 --- a/crates/atom_generator/src/generator.rs +++ b/crates/atom_generator/src/generator.rs @@ -50,7 +50,7 @@ fn generate_classification_file(rust_atom_list: &RustAtomList) { fn generate_property_file(rust_atom_list: &RustAtomList) { let file_body = self::property::generate_file_body(rust_atom_list); - let file_path = build_file_path("parser/property.rs"); + let file_path = build_file_path("property.rs"); write_project_file(&file_path, &file_body, true); } diff --git a/crates/atom_generator/src/generator/atom.rs b/crates/atom_generator/src/generator/atom.rs index 0998e977..08048d74 100644 --- a/crates/atom_generator/src/generator/atom.rs +++ b/crates/atom_generator/src/generator/atom.rs @@ -28,8 +28,8 @@ pub(super) fn generate_file_body(atom_list: &RustAtomList) -> String { mod reducible; use crate::{ - is_compatible_with::DefaultCompatibility, parser::Property, reducible::Reducible, - Classification, UcumSymbol, UcumUnit, Unit, + is_compatible_with::DefaultCompatibility, reducible::Reducible, Classification, Property, + UcumSymbol, UcumUnit, Unit, }; #[allow(clippy::wildcard_imports)] From 8ac63470a4af7db77adb7c8c418522df2a424f74 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 25 Mar 2024 16:33:54 -0700 Subject: [PATCH 54/80] PLCC-299 Move Term to root --- crates/api/src/atom/atom_test.rs | 2 +- crates/api/src/atom/definition.rs | 5 +---- crates/api/src/composition.rs | 2 +- crates/api/src/lib.rs | 5 +++-- crates/api/src/macros.rs | 2 +- crates/api/src/measurement/num_traits/pow.rs | 2 +- crates/api/src/parser.rs | 7 +++---- crates/api/src/parser/annotation_composition.rs | 2 +- crates/api/src/parser/terms/mapper.rs | 6 ++++-- crates/api/src/parser/terms/mapper/annotatable.rs | 5 +++-- crates/api/src/parser/terms/mapper/ast_term.rs | 2 +- crates/api/src/parser/terms/mapper/basic_component.rs | 5 ++++- crates/api/src/parser/terms/mapper/component.rs | 5 ++++- crates/api/src/parser/terms/mapper/exponent.rs | 5 ++++- crates/api/src/parser/terms/mapper/factor.rs | 5 ++++- crates/api/src/parser/terms/mapper/finishable.rs | 2 +- crates/api/src/parser/terms/mapper/main_term.rs | 5 ++++- crates/api/src/{parser => }/term.rs | 0 crates/api/src/{parser => }/term/annotation_composable.rs | 4 ++-- crates/api/src/{parser => }/term/composable.rs | 0 crates/api/src/{parser => }/term/display.rs | 2 +- crates/api/src/{parser => }/term/field_eq.rs | 0 crates/api/src/{parser => }/term/invert.rs | 0 crates/api/src/{parser => }/term/is_compatible_with.rs | 3 +-- crates/api/src/{parser => }/term/num_traits.rs | 0 crates/api/src/{parser => }/term/num_traits/inv.rs | 0 crates/api/src/{parser => }/term/num_traits/pow.rs | 2 +- crates/api/src/{parser => }/term/partial_eq.rs | 0 crates/api/src/{parser => }/term/reducible.rs | 0 crates/api/src/{parser => }/term/ucum_unit.rs | 0 crates/api/src/unit.rs | 5 +---- crates/api/src/unit/as_fraction.rs | 2 +- crates/api/src/unit/deref.rs | 4 ++-- crates/api/src/unit/is_compatible_with.rs | 4 +--- crates/api/src/unit/num_traits/inv.rs | 2 +- crates/api/src/unit/num_traits/pow.rs | 2 +- crates/api/src/unit/term_reducing.rs | 2 +- crates/api/src/unit/to_reduced.rs | 2 +- 38 files changed, 55 insertions(+), 46 deletions(-) rename crates/api/src/{parser => }/term.rs (100%) rename crates/api/src/{parser => }/term/annotation_composable.rs (97%) rename crates/api/src/{parser => }/term/composable.rs (100%) rename crates/api/src/{parser => }/term/display.rs (98%) rename crates/api/src/{parser => }/term/field_eq.rs (100%) rename crates/api/src/{parser => }/term/invert.rs (100%) rename crates/api/src/{parser => }/term/is_compatible_with.rs (98%) rename crates/api/src/{parser => }/term/num_traits.rs (100%) rename crates/api/src/{parser => }/term/num_traits/inv.rs (100%) rename crates/api/src/{parser => }/term/num_traits/pow.rs (98%) rename crates/api/src/{parser => }/term/partial_eq.rs (100%) rename crates/api/src/{parser => }/term/reducible.rs (100%) rename crates/api/src/{parser => }/term/ucum_unit.rs (100%) diff --git a/crates/api/src/atom/atom_test.rs b/crates/api/src/atom/atom_test.rs index a189cf97..b609319f 100644 --- a/crates/api/src/atom/atom_test.rs +++ b/crates/api/src/atom/atom_test.rs @@ -5,7 +5,7 @@ use approx::{assert_relative_eq, assert_ulps_eq}; use crate::{ - parser::term::UNITY_ARRAY, ucum_unit::UcumUnit, Atom, Classification, Composable, Composition, + term::UNITY_ARRAY, ucum_unit::UcumUnit, Atom, Classification, Composable, Composition, Dimension, UcumSymbol, }; diff --git a/crates/api/src/atom/definition.rs b/crates/api/src/atom/definition.rs index 135d9506..a8b00b42 100644 --- a/crates/api/src/atom/definition.rs +++ b/crates/api/src/atom/definition.rs @@ -7,10 +7,7 @@ use std::{borrow::Cow, str::FromStr}; use num_traits::One; -use crate::{ - parser::{term, Term}, - reducible::Reducible, -}; +use crate::{reducible::Reducible, term, Term}; use super::function_set::FunctionSet; diff --git a/crates/api/src/composition.rs b/crates/api/src/composition.rs index cdfa9c37..2e42e900 100644 --- a/crates/api/src/composition.rs +++ b/crates/api/src/composition.rs @@ -1,6 +1,6 @@ use std::{fmt, ops::Mul}; -use crate::{parser::term::Exponent, Dimension}; +use crate::{term::Exponent, Dimension}; pub const DIMLESS: Composition = Composition::new_dimless(); diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 67286ac0..05e559fe 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -37,6 +37,7 @@ pub mod parser; mod prefix; pub mod property; pub mod reduce; +pub(crate) mod term; mod ucum_symbol; pub mod unit; @@ -46,6 +47,6 @@ mod ucum_unit; pub use crate::{ atom::Atom, classification::Classification, composable::Composable, composition::Composition, convertible::Convertible, dimension::Dimension, error::Error, field_eq::FieldEq, - is_compatible_with::IsCompatibleWith, measurement::Measurement, parser::Term, prefix::Prefix, - property::Property, ucum_symbol::UcumSymbol, ucum_unit::UcumUnit, unit::Unit, + is_compatible_with::IsCompatibleWith, measurement::Measurement, prefix::Prefix, + property::Property, term::Term, ucum_symbol::UcumSymbol, ucum_unit::UcumUnit, unit::Unit, }; diff --git a/crates/api/src/macros.rs b/crates/api/src/macros.rs index f793b543..29d870ae 100644 --- a/crates/api/src/macros.rs +++ b/crates/api/src/macros.rs @@ -69,7 +69,7 @@ macro_rules! terms { #[cfg(test)] mod tests { - use crate::{parser::Term, Atom, Prefix}; + use crate::{Term, Atom, Prefix}; #[test] fn validate_term_macro() { diff --git a/crates/api/src/measurement/num_traits/pow.rs b/crates/api/src/measurement/num_traits/pow.rs index 3c2dbd6d..50337909 100644 --- a/crates/api/src/measurement/num_traits/pow.rs +++ b/crates/api/src/measurement/num_traits/pow.rs @@ -1,6 +1,6 @@ use num_traits::Pow; -use crate::{parser::term::Exponent, Measurement}; +use crate::{term::Exponent, Measurement}; impl Pow for Measurement { type Output = Self; diff --git a/crates/api/src/parser.rs b/crates/api/src/parser.rs index 0d63864d..dde22fe6 100644 --- a/crates/api/src/parser.rs +++ b/crates/api/src/parser.rs @@ -1,17 +1,16 @@ #![allow(clippy::large_enum_variant)] #![allow(clippy::result_large_err)] -mod annotation_composition; +pub(crate) mod annotation_composition; mod error; mod symbols; -pub(crate) mod term; mod terms; use pest::{iterators::Pair, Parser}; -use crate::{Atom, Prefix}; +use crate::{Atom, Prefix, Term}; -pub use self::{annotation_composition::AnnotationComposition, error::Error, term::Term}; +pub use self::{annotation_composition::AnnotationComposition, error::Error}; use self::{ symbols::symbol_parser::Rule as SymbolRule, diff --git a/crates/api/src/parser/annotation_composition.rs b/crates/api/src/parser/annotation_composition.rs index adfeb887..119b73d9 100644 --- a/crates/api/src/parser/annotation_composition.rs +++ b/crates/api/src/parser/annotation_composition.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use super::term::Exponent; +use crate::term::Exponent; pub type AnnotationComposition = HashMap; diff --git a/crates/api/src/parser/terms/mapper.rs b/crates/api/src/parser/terms/mapper.rs index 8143293a..3f6153da 100644 --- a/crates/api/src/parser/terms/mapper.rs +++ b/crates/api/src/parser/terms/mapper.rs @@ -56,10 +56,12 @@ pub(crate) fn map(mut pairs: Pairs<'_, Rule>) -> Result, Error> { #[cfg(test)] mod tests { - use super::*; - use crate::parser::terms::term_parser::{Rule, TermParser}; use pest::Parser; + use crate::parser::terms::term_parser::{Rule, TermParser}; + + use super::*; + macro_rules! validate_interpret { ($test_name:ident, $input:expr, $($terms:expr),+) => { #[test] diff --git a/crates/api/src/parser/terms/mapper/annotatable.rs b/crates/api/src/parser/terms/mapper/annotatable.rs index 12b63b36..cd3bdf33 100644 --- a/crates/api/src/parser/terms/mapper/annotatable.rs +++ b/crates/api/src/parser/terms/mapper/annotatable.rs @@ -1,7 +1,8 @@ use pest::iterators::Pair; -use crate::parser::{ - term::Exponent as IExponent, terms::term_parser::Rule as TermRule, Error, Visit, +use crate::{ + parser::{terms::term_parser::Rule as TermRule, Error, Visit}, + term::Exponent as IExponent, }; use super::{Atom, Exponent, Prefix, SimpleUnit}; diff --git a/crates/api/src/parser/terms/mapper/ast_term.rs b/crates/api/src/parser/terms/mapper/ast_term.rs index 3ce8d8d5..10bf2691 100644 --- a/crates/api/src/parser/terms/mapper/ast_term.rs +++ b/crates/api/src/parser/terms/mapper/ast_term.rs @@ -43,7 +43,7 @@ impl AstTerm { match op { SecondToken::Dot => (), SecondToken::Slash => { - crate::parser::term::num_traits::inv::inv_terms(&mut new_terms); + crate::term::num_traits::inv::inv_terms(&mut new_terms); } } diff --git a/crates/api/src/parser/terms/mapper/basic_component.rs b/crates/api/src/parser/terms/mapper/basic_component.rs index 521c94e0..271f9f5b 100644 --- a/crates/api/src/parser/terms/mapper/basic_component.rs +++ b/crates/api/src/parser/terms/mapper/basic_component.rs @@ -1,6 +1,9 @@ use pest::iterators::Pair; -use crate::parser::{term::Factor, terms::term_parser::Rule, Error, Visit}; +use crate::{ + parser::{terms::term_parser::Rule, Error, Visit}, + term::Factor, +}; use super::{Annotatable, Annotation, AstTerm, Finishable, Term}; diff --git a/crates/api/src/parser/terms/mapper/component.rs b/crates/api/src/parser/terms/mapper/component.rs index 44249e04..bc041338 100644 --- a/crates/api/src/parser/terms/mapper/component.rs +++ b/crates/api/src/parser/terms/mapper/component.rs @@ -1,6 +1,9 @@ use pest::iterators::Pair; -use crate::parser::{term::Factor, terms::term_parser::Rule, Error, Visit}; +use crate::{ + parser::{terms::term_parser::Rule, Error, Visit}, + term::Factor, +}; use super::{BasicComponent, Finishable, Term}; diff --git a/crates/api/src/parser/terms/mapper/exponent.rs b/crates/api/src/parser/terms/mapper/exponent.rs index b74de672..32d8afe7 100644 --- a/crates/api/src/parser/terms/mapper/exponent.rs +++ b/crates/api/src/parser/terms/mapper/exponent.rs @@ -1,6 +1,9 @@ use pest::iterators::Pair; -use crate::parser::{term, terms::term_parser::Rule as TermRule, Error, Visit}; +use crate::{ + parser::{terms::term_parser::Rule as TermRule, Error, Visit}, + term, +}; use super::Digits; diff --git a/crates/api/src/parser/terms/mapper/factor.rs b/crates/api/src/parser/terms/mapper/factor.rs index 770a0ec7..09eb97e4 100644 --- a/crates/api/src/parser/terms/mapper/factor.rs +++ b/crates/api/src/parser/terms/mapper/factor.rs @@ -1,6 +1,9 @@ use pest::iterators::Pair; -use crate::parser::{term, terms::term_parser::Rule as TermRule, Error, Visit}; +use crate::{ + parser::{terms::term_parser::Rule as TermRule, Error, Visit}, + term, +}; impl Visit for term::Factor { fn visit(pair: Pair<'_, TermRule>) -> Result { diff --git a/crates/api/src/parser/terms/mapper/finishable.rs b/crates/api/src/parser/terms/mapper/finishable.rs index bd7fb800..639bed85 100644 --- a/crates/api/src/parser/terms/mapper/finishable.rs +++ b/crates/api/src/parser/terms/mapper/finishable.rs @@ -1,4 +1,4 @@ -use crate::parser::Term; +use crate::Term; pub(super) trait Finishable { fn finish(self) -> Vec; diff --git a/crates/api/src/parser/terms/mapper/main_term.rs b/crates/api/src/parser/terms/mapper/main_term.rs index 23efdfd4..2b0973fb 100644 --- a/crates/api/src/parser/terms/mapper/main_term.rs +++ b/crates/api/src/parser/terms/mapper/main_term.rs @@ -1,7 +1,10 @@ use num_traits::Inv; use pest::iterators::Pair; -use crate::parser::{terms::term_parser::Rule, Error, Term, Visit}; +use crate::{ + parser::{terms::term_parser::Rule, Error, Visit}, + Term, +}; use super::{AstTerm, Finishable}; diff --git a/crates/api/src/parser/term.rs b/crates/api/src/term.rs similarity index 100% rename from crates/api/src/parser/term.rs rename to crates/api/src/term.rs diff --git a/crates/api/src/parser/term/annotation_composable.rs b/crates/api/src/term/annotation_composable.rs similarity index 97% rename from crates/api/src/parser/term/annotation_composable.rs rename to crates/api/src/term/annotation_composable.rs index dc876e20..a3c3959b 100644 --- a/crates/api/src/parser/term/annotation_composable.rs +++ b/crates/api/src/term/annotation_composable.rs @@ -1,5 +1,5 @@ -use crate::parser::{ - annotation_composition::{AnnotationComposable, AnnotationComposition}, +use crate::{ + parser::annotation_composition::{AnnotationComposable, AnnotationComposition}, Term, }; diff --git a/crates/api/src/parser/term/composable.rs b/crates/api/src/term/composable.rs similarity index 100% rename from crates/api/src/parser/term/composable.rs rename to crates/api/src/term/composable.rs diff --git a/crates/api/src/parser/term/display.rs b/crates/api/src/term/display.rs similarity index 98% rename from crates/api/src/parser/term/display.rs rename to crates/api/src/term/display.rs index 21429061..5b48cc5e 100644 --- a/crates/api/src/parser/term/display.rs +++ b/crates/api/src/term/display.rs @@ -53,7 +53,7 @@ fn extract_term_string_atom(term_string: &mut String, term: &Term) { #[cfg(test)] mod tests { - use crate::parser::{term::UNITY, Term}; + use crate::{term::UNITY, Term}; macro_rules! validate_display { ($test_name:ident, $term:expr, $output:expr) => { diff --git a/crates/api/src/parser/term/field_eq.rs b/crates/api/src/term/field_eq.rs similarity index 100% rename from crates/api/src/parser/term/field_eq.rs rename to crates/api/src/term/field_eq.rs diff --git a/crates/api/src/parser/term/invert.rs b/crates/api/src/term/invert.rs similarity index 100% rename from crates/api/src/parser/term/invert.rs rename to crates/api/src/term/invert.rs diff --git a/crates/api/src/parser/term/is_compatible_with.rs b/crates/api/src/term/is_compatible_with.rs similarity index 98% rename from crates/api/src/parser/term/is_compatible_with.rs rename to crates/api/src/term/is_compatible_with.rs index 763dff91..0d9a5a1b 100644 --- a/crates/api/src/parser/term/is_compatible_with.rs +++ b/crates/api/src/term/is_compatible_with.rs @@ -1,8 +1,7 @@ use std::borrow::Cow; use crate::{ - parser::{annotation_composition::AnnotationComposable, Term}, - Composable, IsCompatibleWith, + parser::annotation_composition::AnnotationComposable, Composable, IsCompatibleWith, Term, }; /// In order to enforce compatibility on "non-units" (ex. `{each}`, `{total}`, `{heartbeats}`), diff --git a/crates/api/src/parser/term/num_traits.rs b/crates/api/src/term/num_traits.rs similarity index 100% rename from crates/api/src/parser/term/num_traits.rs rename to crates/api/src/term/num_traits.rs diff --git a/crates/api/src/parser/term/num_traits/inv.rs b/crates/api/src/term/num_traits/inv.rs similarity index 100% rename from crates/api/src/parser/term/num_traits/inv.rs rename to crates/api/src/term/num_traits/inv.rs diff --git a/crates/api/src/parser/term/num_traits/pow.rs b/crates/api/src/term/num_traits/pow.rs similarity index 98% rename from crates/api/src/parser/term/num_traits/pow.rs rename to crates/api/src/term/num_traits/pow.rs index 5338a0f1..792f4dd7 100644 --- a/crates/api/src/parser/term/num_traits/pow.rs +++ b/crates/api/src/term/num_traits/pow.rs @@ -1,6 +1,6 @@ use num_traits::Pow; -use crate::{parser::term::Exponent, Term}; +use crate::{term::Exponent, Term}; impl Pow for Term { type Output = Self; diff --git a/crates/api/src/parser/term/partial_eq.rs b/crates/api/src/term/partial_eq.rs similarity index 100% rename from crates/api/src/parser/term/partial_eq.rs rename to crates/api/src/term/partial_eq.rs diff --git a/crates/api/src/parser/term/reducible.rs b/crates/api/src/term/reducible.rs similarity index 100% rename from crates/api/src/parser/term/reducible.rs rename to crates/api/src/term/reducible.rs diff --git a/crates/api/src/parser/term/ucum_unit.rs b/crates/api/src/term/ucum_unit.rs similarity index 100% rename from crates/api/src/parser/term/ucum_unit.rs rename to crates/api/src/term/ucum_unit.rs diff --git a/crates/api/src/unit.rs b/crates/api/src/unit.rs index 63fe6a27..499a78b4 100644 --- a/crates/api/src/unit.rs +++ b/crates/api/src/unit.rs @@ -28,10 +28,7 @@ use std::{borrow::Cow, str::FromStr}; #[cfg(feature = "cffi")] use ffi_common::derive::FFI; -use crate::{ - parser::{term, Term}, - Error, -}; +use crate::{term, Error, Term}; pub const UNITY: Unit = Unit { terms: Cow::Borrowed(term::UNITY_ARRAY_REF), diff --git a/crates/api/src/unit/as_fraction.rs b/crates/api/src/unit/as_fraction.rs index d913e58a..b97353af 100644 --- a/crates/api/src/unit/as_fraction.rs +++ b/crates/api/src/unit/as_fraction.rs @@ -1,6 +1,6 @@ use num_traits::Inv; -use crate::{as_fraction::AsFraction, parser::Term, unit::Unit}; +use crate::{as_fraction::AsFraction, Term, Unit}; impl AsFraction for Unit { type Numerator = Option; diff --git a/crates/api/src/unit/deref.rs b/crates/api/src/unit/deref.rs index e96e6bd3..888365dc 100644 --- a/crates/api/src/unit/deref.rs +++ b/crates/api/src/unit/deref.rs @@ -1,10 +1,10 @@ -use crate::{parser::Term, unit::Unit}; +use crate::Term; //----------------------------------------------------------------------------- // impl Deref //----------------------------------------------------------------------------- // TODO: Get rid of this in 1.0. -impl ::std::ops::Deref for Unit { +impl ::std::ops::Deref for crate::Unit { type Target = [Term]; fn deref(&self) -> &[Term] { diff --git a/crates/api/src/unit/is_compatible_with.rs b/crates/api/src/unit/is_compatible_with.rs index f3eb5a85..06097758 100644 --- a/crates/api/src/unit/is_compatible_with.rs +++ b/crates/api/src/unit/is_compatible_with.rs @@ -1,8 +1,6 @@ use std::borrow::Cow; -use crate::{ - is_compatible_with::IsCompatibleWith, measurement::Measurement, parser::Term, unit::Unit, -}; +use crate::{IsCompatibleWith, Measurement, Term, Unit}; #[cfg_attr(feature = "cffi", ffi_common::derive::expose_impl)] impl IsCompatibleWith for Unit { diff --git a/crates/api/src/unit/num_traits/inv.rs b/crates/api/src/unit/num_traits/inv.rs index 863f01ae..4c05ceb8 100644 --- a/crates/api/src/unit/num_traits/inv.rs +++ b/crates/api/src/unit/num_traits/inv.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use num_traits::Inv; -use crate::{parser::term, Unit}; +use crate::{term, Unit}; impl Inv for Unit { type Output = Self; diff --git a/crates/api/src/unit/num_traits/pow.rs b/crates/api/src/unit/num_traits/pow.rs index 7d6910a0..a7649cae 100644 --- a/crates/api/src/unit/num_traits/pow.rs +++ b/crates/api/src/unit/num_traits/pow.rs @@ -1,6 +1,6 @@ use num_traits::Pow; -use crate::{parser::term::Exponent, Unit}; +use crate::{term::Exponent, Unit}; impl Pow for Unit { type Output = Self; diff --git a/crates/api/src/unit/term_reducing.rs b/crates/api/src/unit/term_reducing.rs index 47dad85d..83d7c37f 100644 --- a/crates/api/src/unit/term_reducing.rs +++ b/crates/api/src/unit/term_reducing.rs @@ -3,7 +3,7 @@ use std::collections::BTreeMap; use num_traits::Zero; use crate::{ - parser::term::{self, Exponent, Factor}, + term::{self, Exponent, Factor}, Atom, Prefix, Term, }; diff --git a/crates/api/src/unit/to_reduced.rs b/crates/api/src/unit/to_reduced.rs index def6ca1a..4e46e18c 100644 --- a/crates/api/src/unit/to_reduced.rs +++ b/crates/api/src/unit/to_reduced.rs @@ -57,7 +57,7 @@ impl ToReduced for Unit { new_terms.extend_from_slice(&new_numerators); let new_denominators = - crate::parser::term::num_traits::inv::inv_terms_into(new_denominators); + crate::term::num_traits::inv::inv_terms_into(new_denominators); new_terms.extend_from_slice(&new_denominators); Self::new(super::term_reducing::reduce_terms(&new_terms)) From abaab2cb691b249254c1efa6a7000477f73beda3 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 25 Mar 2024 16:47:38 -0700 Subject: [PATCH 55/80] Allow clippies for generated Atom --- crates/api/src/atom.rs | 5 +++++ crates/atom_generator/src/generator/atom.rs | 2 ++ 2 files changed, 7 insertions(+) diff --git a/crates/api/src/atom.rs b/crates/api/src/atom.rs index dbe9ab21..3e85ba9f 100644 --- a/crates/api/src/atom.rs +++ b/crates/api/src/atom.rs @@ -2,6 +2,11 @@ // DO NOT EDIT THIS FILE! // This is generated by wise_units-atom_generator. //----------------------------------------------------------------------------- +#![allow( + clippy::unreadable_literal, + clippy::too_many_lines, + clippy::match_same_arms +)] mod composable; mod definition; diff --git a/crates/atom_generator/src/generator/atom.rs b/crates/atom_generator/src/generator/atom.rs index 08048d74..1bc7eae9 100644 --- a/crates/atom_generator/src/generator/atom.rs +++ b/crates/atom_generator/src/generator/atom.rs @@ -21,6 +21,8 @@ pub(super) fn generate_file_body(atom_list: &RustAtomList) -> String { let is_metric_method = atom_list.is_metric_method(); let tokens = quote! { + #![allow(clippy::unreadable_literal, clippy::too_many_lines, clippy::match_same_arms)] + mod composable; mod display; mod hash; From 116a25f0904a901a4cf47607a9b3f5621f668346 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Tue, 26 Mar 2024 11:08:20 -0700 Subject: [PATCH 56/80] PLCC-299 Move parser to live under unit module --- crates/api/CHANGELOG.md | 16 ++++++++++++++-- .../src/{parser => }/annotation_composition.rs | 0 crates/api/src/error.rs | 2 +- crates/api/src/lib.rs | 2 +- crates/api/src/term/annotation_composable.rs | 4 ++-- crates/api/src/term/is_compatible_with.rs | 4 +--- crates/api/src/unit.rs | 3 +++ crates/api/src/unit/from_str.rs | 5 +++-- crates/api/src/{ => unit}/parser.rs | 3 +-- crates/api/src/{ => unit}/parser/error.rs | 5 +++-- crates/api/src/{ => unit}/parser/symbols.rs | 0 .../api/src/{ => unit}/parser/symbols/mapper.rs | 5 +++-- .../src/{ => unit}/parser/symbols/symbol.pest | 0 .../api/src/{ => unit}/parser/symbols/symbol.rs | 2 +- .../{ => unit}/parser/symbols/symbol_parser.rs | 2 +- .../parser/symbols/symbol_parser_test.rs | 3 ++- crates/api/src/{ => unit}/parser/terms.rs | 0 crates/api/src/{ => unit}/parser/terms/mapper.rs | 4 ++-- .../parser/terms/mapper/annotatable.rs | 2 +- .../{ => unit}/parser/terms/mapper/annotation.rs | 2 +- .../{ => unit}/parser/terms/mapper/ast_term.rs | 2 +- .../parser/terms/mapper/basic_component.rs | 2 +- .../{ => unit}/parser/terms/mapper/component.rs | 2 +- .../src/{ => unit}/parser/terms/mapper/digits.rs | 2 +- .../{ => unit}/parser/terms/mapper/exponent.rs | 2 +- .../src/{ => unit}/parser/terms/mapper/factor.rs | 2 +- .../{ => unit}/parser/terms/mapper/finishable.rs | 0 .../{ => unit}/parser/terms/mapper/main_term.rs | 2 +- .../parser/terms/mapper/simple_unit.rs | 2 +- crates/api/src/{ => unit}/parser/terms/term.pest | 0 .../src/{ => unit}/parser/terms/term_parser.rs | 2 +- 31 files changed, 49 insertions(+), 33 deletions(-) rename crates/api/src/{parser => }/annotation_composition.rs (100%) rename crates/api/src/{ => unit}/parser.rs (99%) rename crates/api/src/{ => unit}/parser/error.rs (97%) rename crates/api/src/{ => unit}/parser/symbols.rs (100%) rename crates/api/src/{ => unit}/parser/symbols/mapper.rs (93%) rename crates/api/src/{ => unit}/parser/symbols/symbol.pest (100%) rename crates/api/src/{ => unit}/parser/symbols/symbol.rs (97%) rename crates/api/src/{ => unit}/parser/symbols/symbol_parser.rs (71%) rename crates/api/src/{ => unit}/parser/symbols/symbol_parser_test.rs (98%) rename crates/api/src/{ => unit}/parser/terms.rs (100%) rename crates/api/src/{ => unit}/parser/terms/mapper.rs (98%) rename crates/api/src/{ => unit}/parser/terms/mapper/annotatable.rs (96%) rename crates/api/src/{ => unit}/parser/terms/mapper/annotation.rs (74%) rename crates/api/src/{ => unit}/parser/terms/mapper/ast_term.rs (96%) rename crates/api/src/{ => unit}/parser/terms/mapper/basic_component.rs (98%) rename crates/api/src/{ => unit}/parser/terms/mapper/component.rs (96%) rename crates/api/src/{ => unit}/parser/terms/mapper/digits.rs (74%) rename crates/api/src/{ => unit}/parser/terms/mapper/exponent.rs (95%) rename crates/api/src/{ => unit}/parser/terms/mapper/factor.rs (76%) rename crates/api/src/{ => unit}/parser/terms/mapper/finishable.rs (100%) rename crates/api/src/{ => unit}/parser/terms/mapper/main_term.rs (96%) rename crates/api/src/{ => unit}/parser/terms/mapper/simple_unit.rs (98%) rename crates/api/src/{ => unit}/parser/terms/term.pest (100%) rename crates/api/src/{ => unit}/parser/terms/term_parser.rs (99%) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index f949dd14..1b1ecb77 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -22,8 +22,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Added `unit` constant: `UNITY` - Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. - Added `measurement!()` macro for wrapping `Measurement::try_new().unwrap()`. -- Added `crate::parser::term::Factor` type alias for `u32`. -- Added `crate::parser::term::Exponent` type alias for `i32`. +- Added `crate::term::Factor` type alias for `u32`. +- Added `crate::term::Exponent` type alias for `i32`. - (Internal) Added constants for many but not all internal `Definition`s. ### Changed @@ -33,6 +33,18 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). still generated using `handlebars`). - (Internal) `Definition` is now an enum and is generic over value type `V`. - (Internal) `Definition` resolution uses `uncreachable!()` for all `Definition` unit strings. +- (Internal) Moved the following modules from `crate::parser::` to `crate::`: + - `annotation_composition` + - `atom` + - `classification` + - `composable` + - `composition` + - `dimension` + - `prefix` + - `property` + - `term` + - `ucum_symbol` +- (Internal) Moved `crate::parser` to `crate::unit::parser`. ### Deprecated diff --git a/crates/api/src/parser/annotation_composition.rs b/crates/api/src/annotation_composition.rs similarity index 100% rename from crates/api/src/parser/annotation_composition.rs rename to crates/api/src/annotation_composition.rs diff --git a/crates/api/src/error.rs b/crates/api/src/error.rs index 6530c105..78178543 100644 --- a/crates/api/src/error.rs +++ b/crates/api/src/error.rs @@ -1,4 +1,4 @@ -use crate::parser::Error as ParserError; +use crate::unit::ParserError; #[derive(Clone, Debug, thiserror::Error, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize))] diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 05e559fe..24df737b 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -21,6 +21,7 @@ #[macro_use] mod macros; +pub(crate) mod annotation_composition; pub mod as_fraction; pub mod atom; pub mod classification; @@ -33,7 +34,6 @@ pub mod field_eq; pub mod invert; pub mod is_compatible_with; pub mod measurement; -pub mod parser; mod prefix; pub mod property; pub mod reduce; diff --git a/crates/api/src/term/annotation_composable.rs b/crates/api/src/term/annotation_composable.rs index a3c3959b..0372bc40 100644 --- a/crates/api/src/term/annotation_composable.rs +++ b/crates/api/src/term/annotation_composable.rs @@ -1,5 +1,5 @@ use crate::{ - parser::annotation_composition::{AnnotationComposable, AnnotationComposition}, + annotation_composition::{AnnotationComposable, AnnotationComposition}, Term, }; @@ -40,7 +40,7 @@ impl<'a> AnnotationComposable for &'a [Term] { #[cfg(test)] mod tests { - use crate::parser::annotation_composition::{AnnotationComposable, AnnotationComposition}; + use super::*; mod without_annotations { use super::*; diff --git a/crates/api/src/term/is_compatible_with.rs b/crates/api/src/term/is_compatible_with.rs index 0d9a5a1b..d2c22afc 100644 --- a/crates/api/src/term/is_compatible_with.rs +++ b/crates/api/src/term/is_compatible_with.rs @@ -1,8 +1,6 @@ use std::borrow::Cow; -use crate::{ - parser::annotation_composition::AnnotationComposable, Composable, IsCompatibleWith, Term, -}; +use crate::{annotation_composition::AnnotationComposable, Composable, IsCompatibleWith, Term}; /// In order to enforce compatibility on "non-units" (ex. `{each}`, `{total}`, `{heartbeats}`), /// `Term`s need to compare their annotations along with their `Composition`s. In practice, and diff --git a/crates/api/src/unit.rs b/crates/api/src/unit.rs index 499a78b4..6230d695 100644 --- a/crates/api/src/unit.rs +++ b/crates/api/src/unit.rs @@ -8,6 +8,7 @@ mod invert; mod is_compatible_with; mod num_traits; mod ops; +mod parser; mod partial_eq; mod partial_ord; mod reducible; @@ -28,6 +29,8 @@ use std::{borrow::Cow, str::FromStr}; #[cfg(feature = "cffi")] use ffi_common::derive::FFI; +pub(crate) use self::parser::Error as ParserError; + use crate::{term, Error, Term}; pub const UNITY: Unit = Unit { diff --git a/crates/api/src/unit/from_str.rs b/crates/api/src/unit/from_str.rs index 11588145..dcc1380b 100644 --- a/crates/api/src/unit/from_str.rs +++ b/crates/api/src/unit/from_str.rs @@ -1,6 +1,7 @@ -use crate::{Error, Unit}; use std::str::FromStr; +use crate::{Error, Unit}; + //----------------------------------------------------------------------------- // impl FromStr //----------------------------------------------------------------------------- @@ -9,7 +10,7 @@ impl FromStr for Unit { #[inline] fn from_str(expression: &str) -> Result { - Ok(Self::new(crate::parser::parse(expression)?)) + Ok(Self::new(super::parser::parse(expression)?)) } } diff --git a/crates/api/src/parser.rs b/crates/api/src/unit/parser.rs similarity index 99% rename from crates/api/src/parser.rs rename to crates/api/src/unit/parser.rs index dde22fe6..8766e0b3 100644 --- a/crates/api/src/parser.rs +++ b/crates/api/src/unit/parser.rs @@ -1,7 +1,6 @@ #![allow(clippy::large_enum_variant)] #![allow(clippy::result_large_err)] -pub(crate) mod annotation_composition; mod error; mod symbols; mod terms; @@ -10,7 +9,7 @@ use pest::{iterators::Pair, Parser}; use crate::{Atom, Prefix, Term}; -pub use self::{annotation_composition::AnnotationComposition, error::Error}; +pub use self::error::Error; use self::{ symbols::symbol_parser::Rule as SymbolRule, diff --git a/crates/api/src/parser/error.rs b/crates/api/src/unit/parser/error.rs similarity index 97% rename from crates/api/src/parser/error.rs rename to crates/api/src/unit/parser/error.rs index 180dd326..9e23fd43 100644 --- a/crates/api/src/parser/error.rs +++ b/crates/api/src/unit/parser/error.rs @@ -1,7 +1,8 @@ -use crate::parser::{ +use pest::error::Error as PestError; + +use crate::unit::parser::{ symbols::symbol_parser::Rule as SymbolRule, terms::term_parser::Rule as TermRule, }; -use pest::error::Error as PestError; /// Errors when trying to convert between types that aren't commensurable. /// diff --git a/crates/api/src/parser/symbols.rs b/crates/api/src/unit/parser/symbols.rs similarity index 100% rename from crates/api/src/parser/symbols.rs rename to crates/api/src/unit/parser/symbols.rs diff --git a/crates/api/src/parser/symbols/mapper.rs b/crates/api/src/unit/parser/symbols/mapper.rs similarity index 93% rename from crates/api/src/parser/symbols/mapper.rs rename to crates/api/src/unit/parser/symbols/mapper.rs index f7adb7cb..61f5924b 100644 --- a/crates/api/src/parser/symbols/mapper.rs +++ b/crates/api/src/unit/parser/symbols/mapper.rs @@ -1,8 +1,9 @@ -use crate::parser::{ +use pest::iterators::Pair; + +use crate::unit::parser::{ symbols::{symbol_parser::Rule, Symbol}, Error, Visit, }; -use pest::iterators::Pair; pub(in super::super) fn map(pair: Pair<'_, Rule>) -> Result { if pair.as_rule() == Rule::symbol { diff --git a/crates/api/src/parser/symbols/symbol.pest b/crates/api/src/unit/parser/symbols/symbol.pest similarity index 100% rename from crates/api/src/parser/symbols/symbol.pest rename to crates/api/src/unit/parser/symbols/symbol.pest diff --git a/crates/api/src/parser/symbols/symbol.rs b/crates/api/src/unit/parser/symbols/symbol.rs similarity index 97% rename from crates/api/src/parser/symbols/symbol.rs rename to crates/api/src/unit/parser/symbols/symbol.rs index 400c66a7..45e06d86 100644 --- a/crates/api/src/parser/symbols/symbol.rs +++ b/crates/api/src/unit/parser/symbols/symbol.rs @@ -1,7 +1,7 @@ use pest::iterators::Pair; use crate::{ - parser::{symbols::symbol_parser::Rule, Error, Visit}, + unit::parser::{symbols::symbol_parser::Rule, Error, Visit}, Atom, Prefix, }; diff --git a/crates/api/src/parser/symbols/symbol_parser.rs b/crates/api/src/unit/parser/symbols/symbol_parser.rs similarity index 71% rename from crates/api/src/parser/symbols/symbol_parser.rs rename to crates/api/src/unit/parser/symbols/symbol_parser.rs index 6a28122c..8dbe5cba 100644 --- a/crates/api/src/parser/symbols/symbol_parser.rs +++ b/crates/api/src/unit/parser/symbols/symbol_parser.rs @@ -3,5 +3,5 @@ use pest_derive::Parser; #[derive(Parser)] -#[grammar = "parser/symbols/symbol.pest"] +#[grammar = "unit/parser/symbols/symbol.pest"] pub(crate) struct SymbolParser; diff --git a/crates/api/src/parser/symbols/symbol_parser_test.rs b/crates/api/src/unit/parser/symbols/symbol_parser_test.rs similarity index 98% rename from crates/api/src/parser/symbols/symbol_parser_test.rs rename to crates/api/src/unit/parser/symbols/symbol_parser_test.rs index 3ebdc1f3..2b89db93 100644 --- a/crates/api/src/parser/symbols/symbol_parser_test.rs +++ b/crates/api/src/unit/parser/symbols/symbol_parser_test.rs @@ -3,9 +3,10 @@ #![cfg(test)] #![allow(clippy::cognitive_complexity, non_fmt_panics)] -use crate::parser::symbols::symbol_parser::{Rule, SymbolParser}; use pest::{consumes_to, fails_with, parses_to, Parser}; +use crate::unit::parser::symbols::symbol_parser::{Rule, SymbolParser}; + #[test] fn validate_prefixes() { parses_to! { diff --git a/crates/api/src/parser/terms.rs b/crates/api/src/unit/parser/terms.rs similarity index 100% rename from crates/api/src/parser/terms.rs rename to crates/api/src/unit/parser/terms.rs diff --git a/crates/api/src/parser/terms/mapper.rs b/crates/api/src/unit/parser/terms/mapper.rs similarity index 98% rename from crates/api/src/parser/terms/mapper.rs rename to crates/api/src/unit/parser/terms/mapper.rs index 3f6153da..d7ace3dc 100644 --- a/crates/api/src/parser/terms/mapper.rs +++ b/crates/api/src/unit/parser/terms/mapper.rs @@ -18,7 +18,7 @@ mod simple_unit; use pest::iterators::{Pair, Pairs}; use crate::{ - parser::{Error, Visit}, + unit::parser::{Error, Visit}, Atom, Prefix, Term, }; @@ -58,7 +58,7 @@ pub(crate) fn map(mut pairs: Pairs<'_, Rule>) -> Result, Error> { mod tests { use pest::Parser; - use crate::parser::terms::term_parser::{Rule, TermParser}; + use crate::unit::parser::terms::term_parser::TermParser; use super::*; diff --git a/crates/api/src/parser/terms/mapper/annotatable.rs b/crates/api/src/unit/parser/terms/mapper/annotatable.rs similarity index 96% rename from crates/api/src/parser/terms/mapper/annotatable.rs rename to crates/api/src/unit/parser/terms/mapper/annotatable.rs index cd3bdf33..e22979f5 100644 --- a/crates/api/src/parser/terms/mapper/annotatable.rs +++ b/crates/api/src/unit/parser/terms/mapper/annotatable.rs @@ -1,8 +1,8 @@ use pest::iterators::Pair; use crate::{ - parser::{terms::term_parser::Rule as TermRule, Error, Visit}, term::Exponent as IExponent, + unit::parser::{terms::term_parser::Rule as TermRule, Error, Visit}, }; use super::{Atom, Exponent, Prefix, SimpleUnit}; diff --git a/crates/api/src/parser/terms/mapper/annotation.rs b/crates/api/src/unit/parser/terms/mapper/annotation.rs similarity index 74% rename from crates/api/src/parser/terms/mapper/annotation.rs rename to crates/api/src/unit/parser/terms/mapper/annotation.rs index f54230e4..6f22675b 100644 --- a/crates/api/src/parser/terms/mapper/annotation.rs +++ b/crates/api/src/unit/parser/terms/mapper/annotation.rs @@ -1,6 +1,6 @@ use pest::iterators::Pair; -use crate::parser::{terms::term_parser::Rule as TermRule, Error, Visit}; +use crate::unit::parser::{terms::term_parser::Rule as TermRule, Error, Visit}; pub(super) type Annotation = String; diff --git a/crates/api/src/parser/terms/mapper/ast_term.rs b/crates/api/src/unit/parser/terms/mapper/ast_term.rs similarity index 96% rename from crates/api/src/parser/terms/mapper/ast_term.rs rename to crates/api/src/unit/parser/terms/mapper/ast_term.rs index 10bf2691..c831a9a4 100644 --- a/crates/api/src/parser/terms/mapper/ast_term.rs +++ b/crates/api/src/unit/parser/terms/mapper/ast_term.rs @@ -1,6 +1,6 @@ use pest::iterators::Pair; -use crate::parser::{terms::term_parser::Rule, Error, Visit}; +use crate::unit::parser::{terms::term_parser::Rule, Error, Visit}; use super::{Component, Finishable, Term}; diff --git a/crates/api/src/parser/terms/mapper/basic_component.rs b/crates/api/src/unit/parser/terms/mapper/basic_component.rs similarity index 98% rename from crates/api/src/parser/terms/mapper/basic_component.rs rename to crates/api/src/unit/parser/terms/mapper/basic_component.rs index 271f9f5b..5932bcf3 100644 --- a/crates/api/src/parser/terms/mapper/basic_component.rs +++ b/crates/api/src/unit/parser/terms/mapper/basic_component.rs @@ -1,8 +1,8 @@ use pest::iterators::Pair; use crate::{ - parser::{terms::term_parser::Rule, Error, Visit}, term::Factor, + unit::parser::{terms::term_parser::Rule, Error, Visit}, }; use super::{Annotatable, Annotation, AstTerm, Finishable, Term}; diff --git a/crates/api/src/parser/terms/mapper/component.rs b/crates/api/src/unit/parser/terms/mapper/component.rs similarity index 96% rename from crates/api/src/parser/terms/mapper/component.rs rename to crates/api/src/unit/parser/terms/mapper/component.rs index bc041338..f88261ee 100644 --- a/crates/api/src/parser/terms/mapper/component.rs +++ b/crates/api/src/unit/parser/terms/mapper/component.rs @@ -1,8 +1,8 @@ use pest::iterators::Pair; use crate::{ - parser::{terms::term_parser::Rule, Error, Visit}, term::Factor, + unit::parser::{terms::term_parser::Rule, Error, Visit}, }; use super::{BasicComponent, Finishable, Term}; diff --git a/crates/api/src/parser/terms/mapper/digits.rs b/crates/api/src/unit/parser/terms/mapper/digits.rs similarity index 74% rename from crates/api/src/parser/terms/mapper/digits.rs rename to crates/api/src/unit/parser/terms/mapper/digits.rs index 9ec732b0..3a5d0312 100644 --- a/crates/api/src/parser/terms/mapper/digits.rs +++ b/crates/api/src/unit/parser/terms/mapper/digits.rs @@ -1,6 +1,6 @@ use pest::iterators::Pair; -use crate::parser::{terms::term_parser::Rule as TermRule, Error, Visit}; +use crate::unit::parser::{terms::term_parser::Rule as TermRule, Error, Visit}; pub(super) type Digits = i32; diff --git a/crates/api/src/parser/terms/mapper/exponent.rs b/crates/api/src/unit/parser/terms/mapper/exponent.rs similarity index 95% rename from crates/api/src/parser/terms/mapper/exponent.rs rename to crates/api/src/unit/parser/terms/mapper/exponent.rs index 32d8afe7..544a8d4a 100644 --- a/crates/api/src/parser/terms/mapper/exponent.rs +++ b/crates/api/src/unit/parser/terms/mapper/exponent.rs @@ -1,8 +1,8 @@ use pest::iterators::Pair; use crate::{ - parser::{terms::term_parser::Rule as TermRule, Error, Visit}, term, + unit::parser::{terms::term_parser::Rule as TermRule, Error, Visit}, }; use super::Digits; diff --git a/crates/api/src/parser/terms/mapper/factor.rs b/crates/api/src/unit/parser/terms/mapper/factor.rs similarity index 76% rename from crates/api/src/parser/terms/mapper/factor.rs rename to crates/api/src/unit/parser/terms/mapper/factor.rs index 09eb97e4..b72e6ce2 100644 --- a/crates/api/src/parser/terms/mapper/factor.rs +++ b/crates/api/src/unit/parser/terms/mapper/factor.rs @@ -1,8 +1,8 @@ use pest::iterators::Pair; use crate::{ - parser::{terms::term_parser::Rule as TermRule, Error, Visit}, term, + unit::parser::{terms::term_parser::Rule as TermRule, Error, Visit}, }; impl Visit for term::Factor { diff --git a/crates/api/src/parser/terms/mapper/finishable.rs b/crates/api/src/unit/parser/terms/mapper/finishable.rs similarity index 100% rename from crates/api/src/parser/terms/mapper/finishable.rs rename to crates/api/src/unit/parser/terms/mapper/finishable.rs diff --git a/crates/api/src/parser/terms/mapper/main_term.rs b/crates/api/src/unit/parser/terms/mapper/main_term.rs similarity index 96% rename from crates/api/src/parser/terms/mapper/main_term.rs rename to crates/api/src/unit/parser/terms/mapper/main_term.rs index 2b0973fb..2d1e45e6 100644 --- a/crates/api/src/parser/terms/mapper/main_term.rs +++ b/crates/api/src/unit/parser/terms/mapper/main_term.rs @@ -2,7 +2,7 @@ use num_traits::Inv; use pest::iterators::Pair; use crate::{ - parser::{terms::term_parser::Rule, Error, Visit}, + unit::parser::{terms::term_parser::Rule, Error, Visit}, Term, }; diff --git a/crates/api/src/parser/terms/mapper/simple_unit.rs b/crates/api/src/unit/parser/terms/mapper/simple_unit.rs similarity index 98% rename from crates/api/src/parser/terms/mapper/simple_unit.rs rename to crates/api/src/unit/parser/terms/mapper/simple_unit.rs index 40072244..8b3b3f43 100644 --- a/crates/api/src/parser/terms/mapper/simple_unit.rs +++ b/crates/api/src/unit/parser/terms/mapper/simple_unit.rs @@ -1,7 +1,7 @@ use pest::{iterators::Pair, Parser}; use crate::{ - parser::{ + unit::parser::{ symbols::{ mapper as symbol_mapper, symbol_parser::{Rule as SymbolRule, SymbolParser}, diff --git a/crates/api/src/parser/terms/term.pest b/crates/api/src/unit/parser/terms/term.pest similarity index 100% rename from crates/api/src/parser/terms/term.pest rename to crates/api/src/unit/parser/terms/term.pest diff --git a/crates/api/src/parser/terms/term_parser.rs b/crates/api/src/unit/parser/terms/term_parser.rs similarity index 99% rename from crates/api/src/parser/terms/term_parser.rs rename to crates/api/src/unit/parser/terms/term_parser.rs index 55cfba8d..cecc7ee5 100644 --- a/crates/api/src/parser/terms/term_parser.rs +++ b/crates/api/src/unit/parser/terms/term_parser.rs @@ -3,7 +3,7 @@ use pest_derive::Parser; #[derive(Parser)] -#[grammar = "parser/terms/term.pest"] +#[grammar = "unit/parser/terms/term.pest"] pub(crate) struct TermParser; #[cfg(test)] From 4e42205b62ad62246ac6084a15ac811b18b9d77e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 20:39:21 +0000 Subject: [PATCH 57/80] Bump webfactory/ssh-agent from 0.8.0 to 0.9.0 Bumps [webfactory/ssh-agent](https://github.com/webfactory/ssh-agent) from 0.8.0 to 0.9.0. - [Release notes](https://github.com/webfactory/ssh-agent/releases) - [Changelog](https://github.com/webfactory/ssh-agent/blob/master/CHANGELOG.md) - [Commits](https://github.com/webfactory/ssh-agent/compare/v0.8.0...v0.9.0) --- updated-dependencies: - dependency-name: webfactory/ssh-agent dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/rust-ci.yml | 4 ++-- .github/workflows/security-audit.yml | 2 +- .github/workflows/upload-release.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index 94a6f376..c114854d 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -19,7 +19,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup SSH - uses: webfactory/ssh-agent@v0.8.0 + uses: webfactory/ssh-agent@v0.9.0 with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - uses: actions/checkout@v4 @@ -46,7 +46,7 @@ jobs: DYLD_ROOT_PATH: "/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app" steps: - name: Setup SSH - uses: webfactory/ssh-agent@v0.8.0 + uses: webfactory/ssh-agent@v0.9.0 with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - uses: actions/checkout@v4 diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml index 022db629..8f011389 100644 --- a/.github/workflows/security-audit.yml +++ b/.github/workflows/security-audit.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup SSH - uses: webfactory/ssh-agent@v0.8.0 + uses: webfactory/ssh-agent@v0.9.0 with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - uses: actions/checkout@v4 diff --git a/.github/workflows/upload-release.yml b/.github/workflows/upload-release.yml index f46f80df..54f8ca37 100644 --- a/.github/workflows/upload-release.yml +++ b/.github/workflows/upload-release.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup SSH - uses: webfactory/ssh-agent@v0.8.0 + uses: webfactory/ssh-agent@v0.9.0 with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - name: Checkout code From 75d36681852a17684a8c5bddd8144f34570549b6 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 6 May 2024 14:08:08 -0700 Subject: [PATCH 58/80] NAUM-5 Add Term::as_str() --- crates/api/CHANGELOG.md | 2 + crates/api/src/composition.rs | 11 +- crates/api/src/term.rs | 128 ++++++++++++++++++++++ crates/api/src/term/display.rs | 51 +-------- crates/api/src/term/num_traits/inv.rs | 2 +- crates/api/src/unit.rs | 40 +++---- crates/api/src/unit/display.rs | 150 ++++++++++---------------- 7 files changed, 215 insertions(+), 169 deletions(-) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 1b1ecb77..ab74a71e 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -24,6 +24,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Added `measurement!()` macro for wrapping `Measurement::try_new().unwrap()`. - Added `crate::term::Factor` type alias for `u32`. - Added `crate::term::Exponent` type alias for `i32`. +- Added `crate::Term::as_str()`. - (Internal) Added constants for many but not all internal `Definition`s. ### Changed @@ -45,6 +46,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - `term` - `ucum_symbol` - (Internal) Moved `crate::parser` to `crate::unit::parser`. +- (Internal) `Display` implementation for `Unit` now uses `Term::as_str()` logic. ### Deprecated diff --git a/crates/api/src/composition.rs b/crates/api/src/composition.rs index 2e42e900..980530b4 100644 --- a/crates/api/src/composition.rs +++ b/crates/api/src/composition.rs @@ -484,13 +484,13 @@ mod tests { fn validate_insert() { let mut composition = Composition::default(); composition.insert(Dimension::Mass, 3); - assert_eq!(composition.to_string().as_str(), "M3"); + assert_eq!(composition.to_string(), "M3"); composition.insert(Dimension::Mass, 3); - assert_eq!(composition.to_string().as_str(), "M6"); + assert_eq!(composition.to_string(), "M6"); composition.insert(Dimension::Mass, -6); - assert_eq!(composition.to_string().as_str(), ""); + assert_eq!(composition.to_string(), ""); let mut composition = Composition::default(); composition.insert(Dimension::Mass, -1); @@ -500,10 +500,7 @@ mod tests { composition.insert(Dimension::Length, -5); composition.insert(Dimension::PlaneAngle, -6); composition.insert(Dimension::LuminousIntensity, -7); - assert_eq!( - composition.to_string().as_str(), - "Q-3.L-5.F-7.M-1.A-6.C-2.T-4" - ); + assert_eq!(composition.to_string(), "Q-3.L-5.F-7.M-1.A-6.C-2.T-4"); } #[test] diff --git a/crates/api/src/term.rs b/crates/api/src/term.rs index 097c8f51..01e6ef3a 100644 --- a/crates/api/src/term.rs +++ b/crates/api/src/term.rs @@ -9,6 +9,8 @@ mod partial_eq; mod reducible; mod ucum_unit; +use std::borrow::Cow; + use crate::{Atom, Prefix}; pub const UNITY: Term = { @@ -130,6 +132,79 @@ impl Term { pub fn factor_as_u32(&self) -> Factor { self.factor.unwrap_or(1) } + + /// Depending on the `Term`, its string representation could be anywhere from a `&'static str` + /// to a combination of all of its fields as a `String`. For those former cases, we want to + /// allow borrowing the `&'static str` to save on allocations. + /// + #[must_use] + pub fn as_cow_str(&self) -> Cow<'_, str> { + use crate::UcumSymbol; + + if self.is_unity() && self.annotation.is_none() { + return Cow::Borrowed("1"); + }; + + match ( + self.factor, + self.prefix, + self.atom, + self.exponent, + self.annotation.as_deref(), + ) { + (None, None, None, None, None) => Cow::Borrowed(""), + (None | Some(1), None, None, None | Some(1), Some(ann)) => { + Cow::Owned(format!("{{{ann}}}")) + } + (None, None, Some(atom), None | Some(1), None) => Cow::Borrowed(atom.primary_code()), + (None, None, Some(atom), None | Some(1), Some(ann)) => { + Cow::Owned(format!("{atom}{{{ann}}}")) + } + (None, None, Some(atom), Some(exp), None) => Cow::Owned(format!("{atom}{exp}")), + (None, None, Some(atom), Some(exp), Some(ann)) => { + Cow::Owned(format!("{atom}{exp}{{{ann}}}")) + } + (None, Some(prefix), Some(atom), None | Some(1), None) => { + Cow::Owned(format!("{prefix}{atom}")) + } + (None, Some(prefix), Some(atom), None | Some(1), Some(ann)) => { + Cow::Owned(format!("{prefix}{atom}{{{ann}}}")) + } + (None, Some(prefix), Some(atom), Some(exp), None) => { + Cow::Owned(format!("{prefix}{atom}{exp}")) + } + (None, Some(prefix), Some(atom), Some(exp), Some(ann)) => { + Cow::Owned(format!("{prefix}{atom}{exp}{{{ann}}}")) + } + (Some(factor), None, None, None, None) => Cow::Owned(factor.to_string()), + (Some(factor), None, None, None, Some(ann)) => Cow::Owned(format!("{factor}{{{ann}}}")), + (Some(factor), None, Some(atom), None | Some(1), None) => { + Cow::Owned(format!("{factor}{atom}")) + } + (Some(factor), None, Some(atom), None | Some(1), Some(ann)) => { + Cow::Owned(format!("{factor}{atom}{{{ann}}}")) + } + (Some(factor), None, Some(atom), Some(exp), None) => { + Cow::Owned(format!("{factor}{atom}{exp}")) + } + (Some(factor), None, Some(atom), Some(exp), Some(ann)) => { + Cow::Owned(format!("{factor}{atom}{exp}{{{ann}}}")) + } + (Some(factor), Some(prefix), Some(atom), None | Some(1), None) => { + Cow::Owned(format!("{factor}{prefix}{atom}")) + } + (Some(factor), Some(prefix), Some(atom), None | Some(1), Some(ann)) => { + Cow::Owned(format!("{factor}{prefix}{atom}{{{ann}}}")) + } + (Some(factor), Some(prefix), Some(atom), Some(exp), None) => { + Cow::Owned(format!("{factor}{prefix}{atom}{exp}")) + } + (Some(factor), Some(prefix), Some(atom), Some(exp), Some(ann)) => { + Cow::Owned(format!("{factor}{prefix}{atom}{exp}{{{ann}}}")) + } + _ => unreachable!("Invalid Term: {self:?}"), + } + } } #[cfg(test)] @@ -140,4 +215,57 @@ mod tests { fn validate_new_unity() { assert_eq!(UNITY.to_string(), "1"); } + + #[test] + fn as_str_test() { + assert_eq!(UNITY.as_cow_str(), "1"); + + // None, None, None, None, None + assert_eq!(Term::default().as_cow_str(), ""); + + // None | Some(1), None, None, None, Some(ann) + assert_eq!(term!(annotation: "hi".to_string()).as_cow_str(), "{hi}"); + assert_eq!( + term!(factor: 1, annotation: "hi".to_string()).as_cow_str(), + "{hi}" + ); + + // None, None, Some(atom), None | Some(1), None + assert_eq!(term!(Meter).as_cow_str(), "m"); + assert_eq!(term!(Meter, exponent: 1).as_cow_str(), "m"); + + // None, None, Some(atom), None | Some(1), Some(ann) + assert_eq!( + term!(Meter, annotation: "hi".to_string()).as_cow_str(), + "m{hi}" + ); + assert_eq!( + term!(Meter, exponent: 1, annotation: "hi".to_string()).as_cow_str(), + "m{hi}" + ); + + assert_eq!(term!(Meter, exponent: 2).as_cow_str(), "m2"); + assert_eq!(term!(Meter, exponent: -1).as_cow_str(), "m-1"); + + assert_eq!( + term!(Meter, exponent: 2, annotation: "hi".to_string()).as_cow_str(), + "m2{hi}" + ); + + assert_eq!(term!(Kilo, Meter).as_cow_str(), "km"); + + assert_eq!( + term!(Kilo, Meter, annotation: "hi".to_string()).as_cow_str(), + "km{hi}" + ); + + assert_eq!( + term!(Kilo, Meter, exponent: 1, annotation: "hi".to_string()).as_cow_str(), + "km{hi}" + ); + assert_eq!( + term!(Kilo, Meter, exponent: 2, annotation: "hi".to_string()).as_cow_str(), + "km2{hi}" + ); + } } diff --git a/crates/api/src/term/display.rs b/crates/api/src/term/display.rs index 5b48cc5e..b3d272b1 100644 --- a/crates/api/src/term/display.rs +++ b/crates/api/src/term/display.rs @@ -1,53 +1,10 @@ use std::fmt; -use super::{Factor, Term}; +use super::Term; impl fmt::Display for Term { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", extract_term_string(self)) - } -} - -fn extract_term_string(term: &Term) -> String { - if term.is_unity() && term.annotation.is_none() { - return String::from("1"); - }; - - let mut term_string = String::new(); - extract_term_string_factor(&mut term_string, term.factor); - extract_term_string_atom(&mut term_string, term); - - if let Some(ref annotation) = term.annotation { - term_string.push_str(&format!("{{{annotation}}}")); - } - - term_string -} - -fn extract_term_string_factor(term_string: &mut String, term_factor: Option) { - if let Some(factor) = term_factor { - if factor != 1 { - term_string.push_str(&factor.to_string()); - } - } -} - -fn extract_term_string_atom(term_string: &mut String, term: &Term) { - if let Some(atom) = term.atom { - if let Some(prefix) = term.prefix { - term_string.push_str(&prefix.to_string()); - } - - match term.exponent { - Some(exponent) => { - if exponent == 1 { - term_string.push_str(&atom.to_string()); - } else { - term_string.push_str(&format!("{atom}{exponent}")); - } - } - None => term_string.push_str(&atom.to_string()), - } + write!(f, "{}", self.as_cow_str()) } } @@ -60,7 +17,7 @@ mod tests { #[test] fn $test_name() { let term = $term; - assert_eq!(term.to_string().as_str(), $output); + assert_eq!(term.to_string(), $output); } }; @@ -68,7 +25,7 @@ mod tests { #[test] fn $test_name() { let term = term!(); - assert_eq!(term.to_string().as_str(), $output); + assert_eq!(term.to_string(), $output); } }; } diff --git a/crates/api/src/term/num_traits/inv.rs b/crates/api/src/term/num_traits/inv.rs index 256a82e8..fac870d1 100644 --- a/crates/api/src/term/num_traits/inv.rs +++ b/crates/api/src/term/num_traits/inv.rs @@ -50,7 +50,7 @@ pub(crate) fn inv_terms(terms: &mut Vec) { // This solves not being able to `impl Inv for Vec`. // pub(crate) fn inv_terms_into(terms: Vec) -> Vec { - terms.into_iter().map(num_traits::Inv::inv).collect() + terms.into_iter().map(Inv::inv).collect() } #[cfg(test)] diff --git a/crates/api/src/unit.rs b/crates/api/src/unit.rs index 6230d695..1a0621a1 100644 --- a/crates/api/src/unit.rs +++ b/crates/api/src/unit.rs @@ -135,7 +135,7 @@ impl Unit { /// use wise_units::Unit; /// /// let u = Unit::from_str("[acr_us].[in_i]/[acr_us]").unwrap(); - /// assert_eq!(u.expression().as_str(), "[acr_us].[in_i]/[acr_us]"); + /// assert_eq!(u.expression(), "[acr_us].[in_i]/[acr_us]"); /// ``` /// #[inline] @@ -153,7 +153,7 @@ impl Unit { /// use wise_units::Unit; /// /// let u = Unit::from_str("[acr_us].[in_i]/[acr_us]").unwrap(); - /// assert_eq!(u.expression_reduced().as_str(), "[in_i]"); + /// assert_eq!(u.expression_reduced(), "[in_i]"); /// ``` /// #[inline] @@ -205,55 +205,55 @@ mod tests { #[test] fn validate_expression_reduced() { let unit = Unit::from_str("m").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "m"); + assert_eq!(unit.expression_reduced(), "m"); let unit = Unit::from_str("M").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "m"); + assert_eq!(unit.expression_reduced(), "m"); let unit = Unit::from_str("km/10m").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "km/10m"); + assert_eq!(unit.expression_reduced(), "km/10m"); let unit = Unit::from_str("m-1").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "/m"); + assert_eq!(unit.expression_reduced(), "/m"); let unit = Unit::from_str("10m").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "10m"); + assert_eq!(unit.expression_reduced(), "10m"); let unit = Unit::from_str("10km").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "10km"); + assert_eq!(unit.expression_reduced(), "10km"); let unit = Unit::from_str("10km-1").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "/10km"); + assert_eq!(unit.expression_reduced(), "/10km"); let unit = Unit::from_str("km-1/m2").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "/m2.km"); + assert_eq!(unit.expression_reduced(), "/m2.km"); let unit = Unit::from_str("km/m2.cm").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "km/m2.cm"); + assert_eq!(unit.expression_reduced(), "km/m2.cm"); let unit = Unit::from_str("km-1/m2.cm").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "/m2.cm.km"); + assert_eq!(unit.expression_reduced(), "/m2.cm.km"); let unit = Unit::from_str("m/s2").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "m/s2"); + assert_eq!(unit.expression_reduced(), "m/s2"); let unit = Unit::from_str("km3/nm2").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "km3/nm2"); + assert_eq!(unit.expression_reduced(), "km3/nm2"); let unit = Unit::from_str("Kibit").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "Kibit"); + assert_eq!(unit.expression_reduced(), "Kibit"); let unit = Unit::from_str("KiBy").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "KiBy"); + assert_eq!(unit.expression_reduced(), "KiBy"); let unit = Unit::from_str("MiBy").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "MiBy"); + assert_eq!(unit.expression_reduced(), "MiBy"); let unit = Unit::from_str("GiBy").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "GiBy"); + assert_eq!(unit.expression_reduced(), "GiBy"); let unit = Unit::from_str("TiBy").unwrap(); - assert_eq!(unit.expression_reduced().as_str(), "TiBy"); + assert_eq!(unit.expression_reduced(), "TiBy"); } #[cfg(feature = "cffi")] @@ -267,7 +267,7 @@ mod tests { let unit = unsafe { custom_ffi::unit_init(core::ffi_string!(expression)) }; let c_expression = unsafe { custom_ffi::get_unit_expression(unit) }; assert_eq!(expression, unsafe { - ffi_common::core::string::string_from_c(c_expression) + core::string::string_from_c(c_expression) }); unsafe { unit_ffi::unit_free(unit) }; } diff --git a/crates/api/src/unit/display.rs b/crates/api/src/unit/display.rs index 932ea3ac..6a27af00 100644 --- a/crates/api/src/unit/display.rs +++ b/crates/api/src/unit/display.rs @@ -1,99 +1,55 @@ +use std::{borrow::Cow, fmt}; + use crate::{Term, Unit}; -use std::fmt; //----------------------------------------------------------------------------- // impl Display //----------------------------------------------------------------------------- impl fmt::Display for Unit { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", decompose(self)) - } -} - -/// Turns `terms` into a `String` for display. -/// -fn decompose(unit: &Unit) -> String { - let numerator = string_from_collection(&unit.terms, extract_numerator); - let denominator = string_from_collection(&unit.terms, extract_denominator); + let (numerators, denominators) = decompose(&self.terms); - format_output(numerator, denominator) -} - -fn format_output(numerator: Option, denominator: Option) -> String { - match (numerator, denominator) { - (Some(n), Some(d)) => [n, d].join("/"), - (Some(n), None) => n, - (None, Some(d)) => format!("/{d}"), - (None, None) => "1".to_string(), + write!(f, "{}", recompose(&numerators, &denominators)) } } -fn string_from_collection(terms: &[Term], func: F) -> Option -where - F: Fn(&Term) -> Option, -{ - terms - .iter() - .filter_map(func) - .fold(None, |acc: Option, term_string: String| match acc { - Some(mut a) => { - a.push('.'); - a.push_str(&term_string); - - Some(a) - } - None => Some(term_string), - }) -} - -/// Specifically for use with `filter_map()`, this returns `None` if the `Term` is not positive. -/// -fn extract_numerator(term: &Term) -> Option { - if !term.has_value() || !term.exponent_is_positive() { - return None; - } - - Some(term.to_string()) -} - -/// Specifically for use with `filter_map()`, this returns `None` if the `Term` is not negative. +/// Turns `terms` into two groups of strings: one for numerator terms, one for denominator terms. +/// These just need to be properly jointed by dots and slashes. /// -fn extract_denominator(term: &Term) -> Option { - if !term.has_value() || !term.exponent_is_negative() { - return None; - } - - let mut term_string = String::new(); - - term.factor_and_is_not_one(|factor| term_string.push_str(&factor.to_string())); - - extract_denominator_atom(term, &mut term_string); - - if let Some(ref annotation) = term.annotation { - term_string.push_str(&format!("{{{annotation}}}")); - } - - Some(term_string) -} - -fn extract_denominator_atom(term: &Term, term_string: &mut String) { - if let Some(atom) = term.atom { - if let Some(prefix) = term.prefix { - term_string.push_str(&prefix.to_string()); - } +fn decompose(terms: &[Term]) -> (Vec>, Vec) { + let mut numerators = Vec::new(); + let mut denominators = Vec::new(); + for term in terms { if let Some(exponent) = term.exponent { - let ex_abs = exponent.abs(); - - if ex_abs == 1 { - term_string.push_str(&atom.to_string()); + if exponent.is_positive() { + numerators.push(term.as_cow_str()); } else { - term_string.push_str(&format!("{atom}{ex_abs}")); + let mut positive_exponent_term = term.clone(); + positive_exponent_term.exponent = Some(exponent.abs()); + + denominators.push(positive_exponent_term.to_string()); } } else { - term_string.push_str(&atom.to_string()); + numerators.push(term.as_cow_str()); } } + + (numerators, denominators) +} + +fn recompose<'a>(numerators: &[Cow<'a, str>], denominators: &[String]) -> Cow<'a, str> { + match (numerators.len(), denominators.len()) { + (0, 0) => Cow::Borrowed("1"), + (0, _) => Cow::Owned(format!("/{}", denominators.join("."))), + (1, 0) => numerators[0].clone(), + (_, 0) => Cow::Owned(numerators.join(".")), + (_, _) => Cow::Owned(format!( + "{}/{}", + numerators.join("."), + denominators.join("."), + )), + } } #[cfg(test)] @@ -104,54 +60,60 @@ mod tests { #[test] fn validate_display() { let unit = Unit::from_str("1").unwrap(); - assert_eq!(unit.to_string().as_str(), "1"); + assert_eq!(unit.to_string(), "1"); let unit = Unit::from_str("m").unwrap(); - assert_eq!(unit.to_string().as_str(), "m"); + assert_eq!(unit.to_string(), "m"); let unit = Unit::from_str("M").unwrap(); - assert_eq!(unit.to_string().as_str(), "m"); + assert_eq!(unit.to_string(), "m"); let unit = Unit::from_str("{stuff}").unwrap(); - assert_eq!(unit.to_string().as_str(), "{stuff}"); + assert_eq!(unit.to_string(), "{stuff}"); + + let unit = Unit::from_str("/{stuff}").unwrap(); + assert_eq!(unit.to_string(), "/{stuff}"); let unit = Unit::from_str("m{stuff}").unwrap(); - assert_eq!(unit.to_string().as_str(), "m{stuff}"); + assert_eq!(unit.to_string(), "m{stuff}"); let unit = Unit::from_str("km/10m").unwrap(); - assert_eq!(unit.to_string().as_str(), "km/10m"); + assert_eq!(unit.to_string(), "km/10m"); let unit = Unit::from_str("m-1").unwrap(); - assert_eq!(unit.to_string().as_str(), "/m"); + assert_eq!(unit.to_string(), "/m"); let unit = Unit::from_str("m-1{stuff}").unwrap(); - assert_eq!(unit.to_string().as_str(), "/m{stuff}"); + assert_eq!(unit.to_string(), "/m{stuff}"); let unit = Unit::from_str("10m").unwrap(); - assert_eq!(unit.to_string().as_str(), "10m"); + assert_eq!(unit.to_string(), "10m"); let unit = Unit::from_str("10km").unwrap(); - assert_eq!(unit.to_string().as_str(), "10km"); + assert_eq!(unit.to_string(), "10km"); let unit = Unit::from_str("10km-1").unwrap(); - assert_eq!(unit.to_string().as_str(), "/10km"); + assert_eq!(unit.to_string(), "/10km"); let unit = Unit::from_str("km-1/m2").unwrap(); - assert_eq!(unit.to_string().as_str(), "/km.m2"); + assert_eq!(unit.to_string(), "/km.m2"); let unit = Unit::from_str("km/m2.cm").unwrap(); - assert_eq!(unit.to_string().as_str(), "km/m2.cm"); + assert_eq!(unit.to_string(), "km/m2.cm"); let unit = Unit::from_str("km-1/m2.cm").unwrap(); - assert_eq!(unit.to_string().as_str(), "/km.m2.cm"); + assert_eq!(unit.to_string(), "/km.m2.cm"); let unit = Unit::from_str("m/s2").unwrap(); - assert_eq!(unit.to_string().as_str(), "m/s2"); + assert_eq!(unit.to_string(), "m/s2"); let unit = Unit::from_str("km3/nm2").unwrap(); - assert_eq!(unit.to_string().as_str(), "km3/nm2"); + assert_eq!(unit.to_string(), "km3/nm2"); let unit = Unit::from_str("km3{foo}/nm2{bar}").unwrap(); - assert_eq!(unit.to_string().as_str(), "km3{foo}/nm2{bar}"); + assert_eq!(unit.to_string(), "km3{foo}/nm2{bar}"); + + let unit = Unit::from_str("{foo}/{bar}").unwrap(); + assert_eq!(unit.to_string(), "{foo}/{bar}"); } } From a32d936c25e80b2bc63a96d82d99a53f3bbc180f Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 6 May 2024 14:34:28 -0700 Subject: [PATCH 59/80] Add TODO for later --- crates/api/CHANGELOG.md | 4 ++-- crates/api/src/unit.rs | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index ab74a71e..17d2d0f8 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -24,7 +24,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Added `measurement!()` macro for wrapping `Measurement::try_new().unwrap()`. - Added `crate::term::Factor` type alias for `u32`. - Added `crate::term::Exponent` type alias for `i32`. -- Added `crate::Term::as_str()`. +- NAUM-5: Added `crate::Term::as_cow_str()`. - (Internal) Added constants for many but not all internal `Definition`s. ### Changed @@ -46,7 +46,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - `term` - `ucum_symbol` - (Internal) Moved `crate::parser` to `crate::unit::parser`. -- (Internal) `Display` implementation for `Unit` now uses `Term::as_str()` logic. +- NAUM-5: (Internal) `Display` implementation for `Unit` now uses `Term::as_cow_str()` logic. ### Deprecated diff --git a/crates/api/src/unit.rs b/crates/api/src/unit.rs index 1a0621a1..47dca6ca 100644 --- a/crates/api/src/unit.rs +++ b/crates/api/src/unit.rs @@ -165,6 +165,8 @@ impl Unit { } } +// TODO: This is silly; remove. +// impl AsRef for Unit { fn as_ref(&self) -> &Self { self From 7a8cab79696c0dd233f0645b625b3d2008fdafbb Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 10 May 2024 14:37:29 -0700 Subject: [PATCH 60/80] NAUM-5 Derive ParitalOrd for Composition --- crates/api/CHANGELOG.md | 1 + crates/api/src/composition.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 17d2d0f8..8470e298 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -18,6 +18,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - PLCC-287: `impl num_traits::NumCast for Measurement`. - PLCC-287: `impl num_traits::Pow for Measurement`, `Unit`, `Term`. - PLCC-287: `impl std::ops::Neg for Measurement`. +- NAUM-4: Derive `PartialOrd` for `Composition` - Added `Unit::into_terms()` for cases where you only need the `Term`s of the `Unit`. - Added `unit` constant: `UNITY` - Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. diff --git a/crates/api/src/composition.rs b/crates/api/src/composition.rs index 980530b4..ed4cf283 100644 --- a/crates/api/src/composition.rs +++ b/crates/api/src/composition.rs @@ -63,7 +63,7 @@ pub const SPECIFIC_HEAT: Composition = /// /// For more info, see [https://en.wikipedia.org/wiki/Dimensional_analysis](https://en.wikipedia.org/wiki/Dimensional_analysis). /// -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Hash, Default)] pub struct Composition { electric_charge: Option, length: Option, From c482914a8b9642afd8f6992bb61917d3ea595df9 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 10 May 2024 14:49:36 -0700 Subject: [PATCH 61/80] NAUM-4 impl From for Composition --- crates/api/CHANGELOG.md | 3 ++- crates/api/src/composition.rs | 48 +++++++++++++++++++++++++++++++++-- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 8470e298..bc5ef5bb 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -18,14 +18,15 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - PLCC-287: `impl num_traits::NumCast for Measurement`. - PLCC-287: `impl num_traits::Pow for Measurement`, `Unit`, `Term`. - PLCC-287: `impl std::ops::Neg for Measurement`. +- NAUM-5: Added `crate::Term::as_cow_str()`. - NAUM-4: Derive `PartialOrd` for `Composition` +- NAUM-4: `impl From for Composition` - Added `Unit::into_terms()` for cases where you only need the `Term`s of the `Unit`. - Added `unit` constant: `UNITY` - Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. - Added `measurement!()` macro for wrapping `Measurement::try_new().unwrap()`. - Added `crate::term::Factor` type alias for `u32`. - Added `crate::term::Exponent` type alias for `i32`. -- NAUM-5: Added `crate::Term::as_cow_str()`. - (Internal) Added constants for many but not all internal `Definition`s. ### Changed diff --git a/crates/api/src/composition.rs b/crates/api/src/composition.rs index ed4cf283..1a6c04c8 100644 --- a/crates/api/src/composition.rs +++ b/crates/api/src/composition.rs @@ -314,7 +314,9 @@ impl Composition { } } -// impl Display +// ╭──────────────╮ +// │ impl Display │ +// ╰──────────────╯ impl fmt::Display for Composition { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.is_empty() { @@ -349,7 +351,9 @@ fn push_display_expression( } } -// impl Mul +// ╭──────────╮ +// │ impl Mul │ +// ╰──────────╯ /// Used for combining two `Compositions`. /// #[cfg_attr(feature = "cargo-clippy", allow(clippy::suspicious_arithmetic_impl))] @@ -435,6 +439,20 @@ const fn set_exponent(exponent: Exponent) -> Option { } } +impl From for Composition { + fn from(value: Dimension) -> Self { + match value { + Dimension::ElectricCharge => Self::new_electric_charge(1), + Dimension::Length => Self::new_length(1), + Dimension::LuminousIntensity => Self::new_luminous_intensity(1), + Dimension::Mass => Self::new_mass(1), + Dimension::PlaneAngle => Self::new_plane_angle(1), + Dimension::Temperature => Self::new_temperature(1), + Dimension::Time => Self::new_time(1), + } + } +} + #[cfg(test)] mod tests { use super::{super::Dimension, Composition}; @@ -718,4 +736,30 @@ mod tests { let product = subject * -2; assert_eq!(product.mass, Some(-4)); } + + #[test] + fn from_dimension_test() { + assert_eq!( + Composition::from(Dimension::ElectricCharge), + Composition::new_electric_charge(1) + ); + assert_eq!( + Composition::from(Dimension::Length), + Composition::new_length(1) + ); + assert_eq!( + Composition::from(Dimension::LuminousIntensity), + Composition::new_luminous_intensity(1) + ); + assert_eq!(Composition::from(Dimension::Mass), Composition::new_mass(1)); + assert_eq!( + Composition::from(Dimension::PlaneAngle), + Composition::new_plane_angle(1) + ); + assert_eq!( + Composition::from(Dimension::Temperature), + Composition::new_temperature(1) + ); + assert_eq!(Composition::from(Dimension::Time), Composition::new_time(1)); + } } From e469d7e51144f0834bed98f86faeacfffc3e3f36 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 10 May 2024 14:51:03 -0700 Subject: [PATCH 62/80] NAUM-4 Derive Hash for Property --- crates/api/CHANGELOG.md | 1 + crates/api/src/property.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index bc5ef5bb..7c008d1f 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -21,6 +21,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - NAUM-5: Added `crate::Term::as_cow_str()`. - NAUM-4: Derive `PartialOrd` for `Composition` - NAUM-4: `impl From for Composition` +- NAUM-4: Derive `Hash` for `Property` - Added `Unit::into_terms()` for cases where you only need the `Term`s of the `Unit`. - Added `unit` constant: `UNITY` - Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. diff --git a/crates/api/src/property.rs b/crates/api/src/property.rs index 2e8c6f88..a0dc205a 100644 --- a/crates/api/src/property.rs +++ b/crates/api/src/property.rs @@ -9,7 +9,7 @@ use std::fmt; /// HTML spec, but is used throughout the /// [XML description](http://unitsofmeasure.org/ucum-essence.xml). /// -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Property { Acceleration, Acidity, From c6c7f3dddadd36f68690d6c043d8ce987aec5fba Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 10 May 2024 15:06:19 -0700 Subject: [PATCH 63/80] NAUM-4 impl PartialOrd for Term --- crates/api/CHANGELOG.md | 1 + crates/api/src/term.rs | 1 + crates/api/src/term/partial_eq.rs | 6 +-- crates/api/src/term/partial_ord.rs | 69 ++++++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 4 deletions(-) create mode 100644 crates/api/src/term/partial_ord.rs diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 7c008d1f..3b9fbd50 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -22,6 +22,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - NAUM-4: Derive `PartialOrd` for `Composition` - NAUM-4: `impl From for Composition` - NAUM-4: Derive `Hash` for `Property` +- NAUM-4: `impl PartialOrd for Term` - Added `Unit::into_terms()` for cases where you only need the `Term`s of the `Unit`. - Added `unit` constant: `UNITY` - Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. diff --git a/crates/api/src/term.rs b/crates/api/src/term.rs index 01e6ef3a..703e72a4 100644 --- a/crates/api/src/term.rs +++ b/crates/api/src/term.rs @@ -6,6 +6,7 @@ mod invert; mod is_compatible_with; pub(crate) mod num_traits; mod partial_eq; +mod partial_ord; mod reducible; mod ucum_unit; diff --git a/crates/api/src/term/partial_eq.rs b/crates/api/src/term/partial_eq.rs index 2b960174..e92f8f06 100644 --- a/crates/api/src/term/partial_eq.rs +++ b/crates/api/src/term/partial_eq.rs @@ -1,9 +1,7 @@ -use crate::{is_compatible_with::IsCompatibleWith, ucum_unit::UcumUnit, Term}; use approx::ulps_eq; -//----------------------------------------------------------------------------- -// impl PartialEq -//----------------------------------------------------------------------------- +use crate::{is_compatible_with::IsCompatibleWith, ucum_unit::UcumUnit, Term}; + /// `Term`s are `PartialEq` if /// /// a) they are compatible diff --git a/crates/api/src/term/partial_ord.rs b/crates/api/src/term/partial_ord.rs new file mode 100644 index 00000000..240bee16 --- /dev/null +++ b/crates/api/src/term/partial_ord.rs @@ -0,0 +1,69 @@ +use crate::{is_compatible_with::IsCompatibleWith, ucum_unit::UcumUnit, Term}; + +/// `Term`s are `PartialOrd` if +/// +/// a) they are compatible +/// b) their `scalar()` values are comparable +/// +/// ```rust +/// use std::cmp::Ordering; +/// use wise_units::{Atom, Prefix, Term}; +/// +/// let lhs = Term { +/// factor: Some(1000), +/// prefix: None, +/// atom: Some(Atom::Meter), +/// exponent: None, +/// annotation: None +/// }; +/// let rhs = Term { +/// factor: None, +/// prefix: Some(Prefix::Kilo), +/// atom: Some(Atom::Meter), +/// exponent: None, +/// annotation: None +/// }; +/// assert_eq!(lhs.partial_cmp(&rhs), Some(Ordering::Equal)); +/// +/// let lhs = Term { +/// factor: None, +/// prefix: None, +/// atom: Some(Atom::Meter), +/// exponent: None, +/// annotation: None +/// }; +/// let rhs = Term { +/// factor: None, +/// prefix: Some(Prefix::Kilo), +/// atom: Some(Atom::Meter), +/// exponent: None, +/// annotation: None +/// }; +/// assert_eq!(lhs.partial_cmp(&rhs), Some(Ordering::Less)); +/// +/// let lhs = Term { +/// factor: None, +/// prefix: None, +/// atom: Some(Atom::Meter), +/// exponent: None, +/// annotation: None +/// }; +/// let rhs = Term { +/// factor: None, +/// prefix: None, +/// atom: Some(Atom::Gram), +/// exponent: None, +/// annotation: None +/// }; +/// assert_eq!(lhs.partial_cmp(&rhs), None); +/// ``` +/// +impl PartialOrd for Term { + fn partial_cmp(&self, other: &Self) -> Option { + if !self.is_compatible_with(other) { + return None; + } + + self.scalar().partial_cmp(&other.scalar()) + } +} From e1650bffe491f3cb34d5b44efa01d5d27a0927e5 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 13 May 2024 12:06:48 -0700 Subject: [PATCH 64/80] NAUM-6 lazy_static Units -> consts This also gets rid of lazy_static as a dev dep. --- crates/api/Cargo.toml | 1 - crates/api/src/lib.rs | 2 + crates/api/src/testing.rs | 112 +++++++++++++++++++++++++++++ crates/api/src/unit.rs | 2 +- crates/api/src/unit/as_fraction.rs | 32 ++++----- crates/api/src/unit/ops.rs | 30 ++++---- 6 files changed, 145 insertions(+), 34 deletions(-) create mode 100644 crates/api/src/testing.rs diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index b8f7749e..e7a6d7ef 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -20,7 +20,6 @@ thiserror = "1.0" [dev-dependencies] bincode = "1.3" criterion = "0.5" -lazy_static.workspace = true rmp-serde = "1.0" serde_json = "1.0" diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 24df737b..0a0d3572 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -42,6 +42,8 @@ mod ucum_symbol; pub mod unit; mod reducible; +#[cfg(test)] +mod testing; mod ucum_unit; pub use crate::{ diff --git a/crates/api/src/testing.rs b/crates/api/src/testing.rs new file mode 100644 index 00000000..a677b333 --- /dev/null +++ b/crates/api/src/testing.rs @@ -0,0 +1,112 @@ +pub(crate) mod const_units { + use std::borrow::Cow; + + use crate::{Atom, Prefix, Term, Unit}; + + pub(crate) const METER: Unit = Unit { + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Meter), + exponent: None, + annotation: None, + }]), + }; + + pub(crate) const KILOMETER: Unit = Unit { + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: Some(Prefix::Kilo), + atom: Some(Atom::Meter), + exponent: None, + annotation: None, + }]), + }; + + pub(crate) const GRAM_METER: Unit = Unit { + terms: Cow::Borrowed(&[ + Term { + factor: None, + prefix: None, + atom: Some(Atom::Gram), + exponent: None, + annotation: None, + }, + Term { + factor: None, + prefix: None, + atom: Some(Atom::Meter), + exponent: None, + annotation: None, + }, + ]), + }; + + pub(crate) const PER_GRAM_METER: Unit = Unit { + terms: Cow::Borrowed(&[ + Term { + factor: None, + prefix: None, + atom: Some(Atom::Gram), + exponent: Some(-1), + annotation: None, + }, + Term { + factor: None, + prefix: None, + atom: Some(Atom::Meter), + exponent: Some(-1), + annotation: None, + }, + ]), + }; + + pub(crate) const SECOND: Unit = Unit { + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Second), + exponent: None, + annotation: None, + }]), + }; + + pub(crate) const PER_SECOND: Unit = Unit { + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Second), + exponent: Some(-1), + annotation: None, + }]), + }; + + pub(crate) const METER_PER_SECOND: Unit = Unit { + terms: Cow::Borrowed(&[ + Term { + factor: None, + prefix: None, + atom: Some(Atom::Meter), + exponent: None, + annotation: None, + }, + Term { + factor: None, + prefix: None, + atom: Some(Atom::Second), + exponent: Some(-1), + annotation: None, + }, + ]), + }; + + pub(crate) const ACRE: Unit = Unit { + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::AcreUS), + exponent: None, + annotation: None, + }]), + }; +} diff --git a/crates/api/src/unit.rs b/crates/api/src/unit.rs index 47dca6ca..068832c8 100644 --- a/crates/api/src/unit.rs +++ b/crates/api/src/unit.rs @@ -48,7 +48,7 @@ pub const UNITY: Unit = Unit { )] #[derive(Clone, Debug)] pub struct Unit { - terms: Cow<'static, [Term]>, + pub(crate) terms: Cow<'static, [Term]>, } /// A `Unit` is the piece of data that represents a *valid* UCUM unit or diff --git a/crates/api/src/unit/as_fraction.rs b/crates/api/src/unit/as_fraction.rs index b97353af..9c0ccdf7 100644 --- a/crates/api/src/unit/as_fraction.rs +++ b/crates/api/src/unit/as_fraction.rs @@ -43,21 +43,17 @@ impl AsFraction for Unit { #[cfg(test)] mod tests { - use super::Unit; use std::str::FromStr; - lazy_static::lazy_static! { - static ref METER: Unit = Unit::from_str("m").unwrap(); - static ref SECOND: Unit = Unit::from_str("s").unwrap(); - static ref GRAM_METER: Unit = Unit::from_str("g.m").unwrap(); - static ref METER_PER_SECOND: Unit = Unit::from_str("m/s").unwrap(); - static ref PER_SECOND: Unit = Unit::from_str("/s").unwrap(); - static ref PER_GRAM_METER: Unit = Unit::from_str("/g.m").unwrap(); - } + use crate::{ + as_fraction::AsFraction, + testing::const_units::{GRAM_METER, METER, METER_PER_SECOND, PER_SECOND}, + }; + + use super::Unit; #[test] fn validate_as_fraction() { - use crate::as_fraction::AsFraction; let (num, den) = Unit::from_str("m/s").unwrap().as_fraction(); assert!(num.is_some()); @@ -66,24 +62,23 @@ mod tests { mod numerator { use super::*; - use crate::as_fraction::AsFraction; #[test] fn validate_one_numerator_term() { let numerator = METER.numerator().unwrap(); - assert_eq!(&numerator, &*METER); + assert_eq!(numerator, METER); } #[test] fn validate_two_numerator_terms() { let numerator = GRAM_METER.numerator().unwrap(); - assert_eq!(&numerator, &*GRAM_METER); + assert_eq!(numerator, GRAM_METER); } #[test] fn validate_one_numerator_term_one_denominator_term() { let numerator = METER_PER_SECOND.numerator().unwrap(); - assert_eq!(&numerator, &*METER); + assert_eq!(numerator, METER); } #[test] @@ -94,8 +89,9 @@ mod tests { } mod denominator { + use crate::testing::const_units::{PER_GRAM_METER, SECOND}; + use super::*; - use crate::as_fraction::AsFraction; #[test] fn validate_one_numerator_term() { @@ -112,19 +108,19 @@ mod tests { #[test] fn validate_one_numerator_term_one_denominator_term() { let denominator = METER_PER_SECOND.denominator().unwrap(); - assert_eq!(&denominator, &*SECOND); + assert_eq!(denominator, SECOND); } #[test] fn validate_one_denominator_term() { let denominator = PER_SECOND.denominator().unwrap(); - assert_eq!(&denominator, &*SECOND); + assert_eq!(denominator, SECOND); } #[test] fn validate_two_denominator_terms() { let denominator = PER_GRAM_METER.denominator().unwrap(); - assert_eq!(&denominator, &*GRAM_METER); + assert_eq!(denominator, GRAM_METER); } } } diff --git a/crates/api/src/unit/ops.rs b/crates/api/src/unit/ops.rs index 38eb9f12..cb712cd7 100644 --- a/crates/api/src/unit/ops.rs +++ b/crates/api/src/unit/ops.rs @@ -117,37 +117,39 @@ impl<'a> Mul for &'a Unit { #[cfg(test)] mod tests { - use super::*; use std::str::FromStr; - lazy_static::lazy_static! { - static ref ACRE: Unit = Unit::from_str("[acr_us]").unwrap(); - static ref METER: Unit = Unit::from_str("m").unwrap(); - static ref KILOMETER: Unit = Unit::from_str("km").unwrap(); - static ref SEED: Unit = Unit::from_str("{seed}").unwrap(); - static ref UNITY: Unit = Unit::from_str("1").unwrap(); + use crate::{ + testing::const_units::{ACRE, KILOMETER, METER}, + unit::UNITY, + }; + + use super::*; + + fn seed() -> Unit { + Unit::from_str("{seed}").unwrap() } #[test] #[allow(clippy::eq_op)] fn validate_div() { let expected = Unit::from_str("m/km").unwrap(); - assert_eq!(&*METER / &*KILOMETER, expected); + assert_eq!(METER / KILOMETER, expected); let unit = Unit::from_str("10m").unwrap(); let other = Unit::from_str("20m").unwrap(); let expected = Unit::from_str("10m/20m").unwrap(); assert_eq!(unit / other, expected); - assert_eq!(&*SEED / &*SEED, *UNITY); - assert_eq!(&*UNITY / &*SEED, Unit::from_str("/{seed}").unwrap()); - assert_eq!(&*SEED / &*ACRE, Unit::from_str("{seed}/[acr_us]").unwrap()); + assert_eq!(seed() / seed(), UNITY); + assert_eq!(UNITY / seed(), Unit::from_str("/{seed}").unwrap()); + assert_eq!(seed() / ACRE, Unit::from_str("{seed}/[acr_us]").unwrap()); } #[test] fn validate_mul() { let expected = Unit::from_str("m.km").unwrap(); - assert_eq!(&*METER * &*KILOMETER, expected); + assert_eq!(METER * KILOMETER, expected); let unit = Unit::from_str("10m").unwrap(); let other = Unit::from_str("20m").unwrap(); @@ -155,9 +157,9 @@ mod tests { assert_eq!(unit * other, expected); let per_seed = Unit::from_str("/{seed}").unwrap(); - assert_eq!(&*SEED * &per_seed, *UNITY); + assert_eq!(seed() * &per_seed, UNITY); let seed_per_acre = Unit::from_str("{seed}/[acr_us]").unwrap(); - assert_eq!(seed_per_acre * &*ACRE, *SEED); + assert_eq!(seed_per_acre * ACRE, seed()); } } From 6435bdaa3ca0f04e5983645f428d08632adf2df0 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 13 May 2024 14:37:07 -0700 Subject: [PATCH 65/80] NAUM-6 Update as_fraction() impl to iterate Terms once ...instead of twice (once for numerators, once for denominators). --- crates/api/CHANGELOG.md | 2 ++ crates/api/src/unit/as_fraction.rs | 37 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 3b9fbd50..daec32a0 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -51,6 +51,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - `ucum_symbol` - (Internal) Moved `crate::parser` to `crate::unit::parser`. - NAUM-5: (Internal) `Display` implementation for `Unit` now uses `Term::as_cow_str()` logic. +- NAUM-6: Updated `AsFraction::as_fraction()` implementation to iterate through `Term`s once instead + of twice for building the numerator and denominator. ### Deprecated diff --git a/crates/api/src/unit/as_fraction.rs b/crates/api/src/unit/as_fraction.rs index 9c0ccdf7..0046bba6 100644 --- a/crates/api/src/unit/as_fraction.rs +++ b/crates/api/src/unit/as_fraction.rs @@ -6,6 +6,43 @@ impl AsFraction for Unit { type Numerator = Option; type Denominator = Option; + fn as_fraction(&self) -> (Self::Numerator, Self::Denominator) { + use crate::Term; + + #[derive(Default)] + struct Parts { + numerators: Vec, + denominators: Vec, + } + + let mut parts = Parts::default(); + + for term in &*self.terms { + match term.exponent { + Some(e) => { + if e.is_negative() { + parts.denominators.push(term.inv()); + } else { + parts.numerators.push(term.clone()); + } + } + None => { + parts.numerators.push(term.clone()); + } + } + } + + match (parts.numerators.is_empty(), parts.denominators.is_empty()) { + (true, true) => (None, None), + (true, _) => (None, Some(Self::new(parts.denominators))), + (_, true) => (Some(Self::new(parts.numerators)), None), + (_, _) => ( + Some(Self::new(parts.numerators)), + Some(Self::new(parts.denominators)), + ), + } + } + #[inline] fn numerator(&self) -> Self::Numerator { let positive_terms: Vec = self From e420caf5834ccaec814a9f361683149495cf9d19 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 13 May 2024 14:53:53 -0700 Subject: [PATCH 66/80] NAUM-6 Add v2 feature, module; add v2::convert::ToFraction ...and implement it for Unit. --- README.md | 6 ++ crates/api/CHANGELOG.md | 5 +- crates/api/Cargo.toml | 2 + crates/api/src/lib.rs | 15 +++-- crates/api/src/unit.rs | 2 + crates/api/src/unit/v2.rs | 1 + crates/api/src/unit/v2/convert.rs | 102 ++++++++++++++++++++++++++++++ crates/api/src/v2.rs | 1 + crates/api/src/v2/convert.rs | 11 ++++ 9 files changed, 138 insertions(+), 7 deletions(-) create mode 100644 crates/api/src/unit/v2.rs create mode 100644 crates/api/src/unit/v2/convert.rs create mode 100644 crates/api/src/v2.rs create mode 100644 crates/api/src/v2/convert.rs diff --git a/README.md b/README.md index e9364798..4f4abf6b 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,12 @@ This feature is disabled by default. To enable it: wise_units = { version = "0.22", features = ["serde"] } ``` +### Feature `v2` + +The `v2` feature makes some new traits available--traits that are "fixed" versions of existing +traits. Putting these behind this feature flag allows us to try out these new traits in downstream +crates before switching them to be the main traits in `wise_units`. + ## Examples A `Measurement` is made up of some quantifier, the `value`, and the unit of measure, diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index daec32a0..52181630 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -18,11 +18,14 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - PLCC-287: `impl num_traits::NumCast for Measurement`. - PLCC-287: `impl num_traits::Pow for Measurement`, `Unit`, `Term`. - PLCC-287: `impl std::ops::Neg for Measurement`. -- NAUM-5: Added `crate::Term::as_cow_str()`. - NAUM-4: Derive `PartialOrd` for `Composition` - NAUM-4: `impl From for Composition` - NAUM-4: Derive `Hash` for `Property` - NAUM-4: `impl PartialOrd for Term` +- NAUM-5: Added `crate::Term::as_cow_str()`. +- NAUM-6 + - Add new `"v2"` feature. + - Add `v2::convert::ToFraction` trait. - Added `Unit::into_terms()` for cases where you only need the `Term`s of the `Unit`. - Added `unit` constant: `UNITY` - Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index e7a6d7ef..a2aacbd4 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -30,6 +30,8 @@ default = [] # additional ffi module will be generated for each supported resource type. cffi = ["ffi_common"] +v2 = [] + [[bench]] name = "measurements_benchmarks" harness = false diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 0a0d3572..0556e046 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -21,29 +21,32 @@ #[macro_use] mod macros; -pub(crate) mod annotation_composition; pub mod as_fraction; pub mod atom; pub mod classification; -mod composable; pub mod composition; pub mod convertible; -mod dimension; pub mod error; pub mod field_eq; pub mod invert; pub mod is_compatible_with; pub mod measurement; -mod prefix; pub mod property; pub mod reduce; -pub(crate) mod term; -mod ucum_symbol; pub mod unit; +#[cfg(feature = "v2")] +pub mod v2; +pub(crate) mod annotation_composition; +pub(crate) mod term; + +mod composable; +mod dimension; +mod prefix; mod reducible; #[cfg(test)] mod testing; +mod ucum_symbol; mod ucum_unit; pub use crate::{ diff --git a/crates/api/src/unit.rs b/crates/api/src/unit.rs index 068832c8..c7ebd2cb 100644 --- a/crates/api/src/unit.rs +++ b/crates/api/src/unit.rs @@ -14,6 +14,8 @@ mod partial_ord; mod reducible; mod term_reducing; mod to_reduced; +#[cfg(feature = "v2")] +mod v2; #[allow(clippy::module_name_repetitions)] mod ucum_unit; diff --git a/crates/api/src/unit/v2.rs b/crates/api/src/unit/v2.rs new file mode 100644 index 00000000..bb13da4f --- /dev/null +++ b/crates/api/src/unit/v2.rs @@ -0,0 +1 @@ +mod convert; diff --git a/crates/api/src/unit/v2/convert.rs b/crates/api/src/unit/v2/convert.rs new file mode 100644 index 00000000..b37de8ca --- /dev/null +++ b/crates/api/src/unit/v2/convert.rs @@ -0,0 +1,102 @@ +use crate::{as_fraction::AsFraction, v2::convert::ToFraction, Unit}; + +impl ToFraction for Unit { + fn to_fraction(&self) -> (Option, Option) { + // Just delegate to the old trait impl for now. + AsFraction::as_fraction(self) + } + + fn to_numerator(&self) -> Option { + // Just delegate to the old trait impl for now. + AsFraction::numerator(self) + } + + fn to_denominator(&self) -> Option { + // Just delegate to the old trait impl for now. + AsFraction::denominator(self) + } +} + +#[cfg(test)] +mod tests { + use std::str::FromStr; + + use crate::{ + testing::const_units::{GRAM_METER, METER, METER_PER_SECOND, PER_SECOND}, + Unit, + }; + + use super::ToFraction; + + #[test] + fn validate_to_fraction() { + let (num, den) = Unit::from_str("m/s").unwrap().to_fraction(); + + assert!(num.is_some()); + assert!(den.is_some()); + } + + mod numerator { + use super::*; + + #[test] + fn validate_one_numerator_term() { + let numerator = METER.to_numerator().unwrap(); + assert_eq!(numerator, METER); + } + + #[test] + fn validate_two_numerator_terms() { + let numerator = GRAM_METER.to_numerator().unwrap(); + assert_eq!(numerator, GRAM_METER); + } + + #[test] + fn validate_one_numerator_term_one_denominator_term() { + let numerator = METER_PER_SECOND.to_numerator().unwrap(); + assert_eq!(numerator, METER); + } + + #[test] + fn validate_one_denominator_term() { + let numerator = PER_SECOND.to_numerator(); + assert!(numerator.is_none()); + } + } + + mod denominator { + use crate::testing::const_units::{PER_GRAM_METER, SECOND}; + + use super::*; + + #[test] + fn validate_one_numerator_term() { + let denominator = METER.to_denominator(); + assert!(denominator.is_none()); + } + + #[test] + fn validate_two_numerator_terms() { + let denominator = GRAM_METER.to_denominator(); + assert!(denominator.is_none()); + } + + #[test] + fn validate_one_numerator_term_one_denominator_term() { + let denominator = METER_PER_SECOND.to_denominator().unwrap(); + assert_eq!(denominator, SECOND); + } + + #[test] + fn validate_one_denominator_term() { + let denominator = PER_SECOND.to_denominator().unwrap(); + assert_eq!(denominator, SECOND); + } + + #[test] + fn validate_two_denominator_terms() { + let denominator = PER_GRAM_METER.to_denominator().unwrap(); + assert_eq!(denominator, GRAM_METER); + } + } +} diff --git a/crates/api/src/v2.rs b/crates/api/src/v2.rs new file mode 100644 index 00000000..b5b67213 --- /dev/null +++ b/crates/api/src/v2.rs @@ -0,0 +1 @@ +pub mod convert; diff --git a/crates/api/src/v2/convert.rs b/crates/api/src/v2/convert.rs new file mode 100644 index 00000000..a42ecdac --- /dev/null +++ b/crates/api/src/v2/convert.rs @@ -0,0 +1,11 @@ +/// This is the next version of `AsFraction`, which was incorrectly named, according to Rust +/// API guidelines. The difference with this trait is that a) you can specify the output type for +/// the `to_fraction()` call, letting wrapper crates use this trait (since other types may not +/// easily be able to convert from `(Self::Numerator, Self::Denominator)`). +/// +pub trait ToFraction, D = Option, F = (N, D)> { + fn to_fraction(&self) -> F; + + fn to_numerator(&self) -> N; + fn to_denominator(&self) -> D; +} From 6784b91a25a7bca173fdf0f8314fcb4c514ee800 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 13 May 2024 17:15:25 -0700 Subject: [PATCH 67/80] NAUM-6 Impl ToFraction for Measurement --- crates/api/CHANGELOG.md | 1 + crates/api/src/measurement.rs | 2 + crates/api/src/measurement/v2.rs | 1 + crates/api/src/measurement/v2/convert.rs | 99 ++++++++++++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 crates/api/src/measurement/v2.rs create mode 100644 crates/api/src/measurement/v2/convert.rs diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 52181630..814c5b82 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -26,6 +26,7 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - NAUM-6 - Add new `"v2"` feature. - Add `v2::convert::ToFraction` trait. + - Implemented `v2::convert::ToFraction` trait for `Unit`, `Measurement`. - Added `Unit::into_terms()` for cases where you only need the `Term`s of the `Unit`. - Added `unit` constant: `UNITY` - Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. diff --git a/crates/api/src/measurement.rs b/crates/api/src/measurement.rs index 215e62e7..25af27f3 100644 --- a/crates/api/src/measurement.rs +++ b/crates/api/src/measurement.rs @@ -12,6 +12,8 @@ mod partial_ord; mod reducible; mod to_reduced; mod ucum_unit; +#[cfg(feature = "v2")] +mod v2; use crate::{reducible::Reducible, ucum_unit::UcumUnit, unit::Unit}; diff --git a/crates/api/src/measurement/v2.rs b/crates/api/src/measurement/v2.rs new file mode 100644 index 00000000..bb13da4f --- /dev/null +++ b/crates/api/src/measurement/v2.rs @@ -0,0 +1 @@ +mod convert; diff --git a/crates/api/src/measurement/v2/convert.rs b/crates/api/src/measurement/v2/convert.rs new file mode 100644 index 00000000..701ba807 --- /dev/null +++ b/crates/api/src/measurement/v2/convert.rs @@ -0,0 +1,99 @@ +use crate::{unit, v2::convert::ToFraction, Measurement, Unit}; + +impl ToFraction> for Measurement { + fn to_fraction(&self) -> (Self, Option) { + let unit_parts = self.unit.to_fraction(); + + ( + Self { + value: self.value, + unit: unit_parts.0.unwrap_or(unit::UNITY), + }, + unit_parts.1, + ) + } + + fn to_numerator(&self) -> Self { + Self { + value: self.value, + unit: self.unit.to_numerator().unwrap_or(unit::UNITY), + } + } + + fn to_denominator(&self) -> Option { + self.unit.to_denominator() + } +} + +#[cfg(test)] +mod tests { + use crate::{ + testing::const_units::{GRAM_METER, METER, METER_PER_SECOND, PER_SECOND, SECOND}, + unit::UNITY, + Measurement, + }; + + use super::*; + + macro_rules! validate_fraction_parts { + ( + $measurement:expr, + expected_numerator => $expected_numerator:expr, + expected_denominator => $expected_denominator:expr + ) => { + let fraction = $measurement.to_fraction(); + assert_eq!(&fraction.0, &$expected_numerator); + assert_eq!(fraction.1, $expected_denominator); + + let numerator = $measurement.to_numerator(); + assert_eq!(numerator, $expected_numerator); + + let denominator = $measurement.to_denominator(); + assert_eq!(denominator, $expected_denominator); + }; + } + + #[test] + fn validate_one_numerator_term() { + let measurement = Measurement::new(42.0, METER); + + validate_fraction_parts!( + measurement, + expected_numerator => measurement, + expected_denominator => None + ); + } + + #[test] + fn validate_two_numerator_terms() { + let measurement = Measurement::new(42.0, GRAM_METER); + + validate_fraction_parts!( + measurement, + expected_numerator => measurement, + expected_denominator => None + ); + } + + #[test] + fn validate_one_numerator_term_one_denominator_term() { + let measurement = Measurement::new(42.0, METER_PER_SECOND); + + validate_fraction_parts!( + measurement, + expected_numerator => Measurement::new(42.0, METER), + expected_denominator => Some(SECOND) + ); + } + + #[test] + fn validate_one_denominator_term() { + let measurement = Measurement::new(42.0, PER_SECOND); + + validate_fraction_parts!( + measurement, + expected_numerator => Measurement::new(42.0, UNITY), + expected_denominator => Some(SECOND) + ); + } +} From db808b28f04fdfe403edac06d537b6121748dcb7 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Mon, 13 May 2024 17:16:51 -0700 Subject: [PATCH 68/80] cargo clippy, fmt --- crates/api/src/composition.rs | 2 +- crates/api/src/macros.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/api/src/composition.rs b/crates/api/src/composition.rs index 1a6c04c8..f780cd22 100644 --- a/crates/api/src/composition.rs +++ b/crates/api/src/composition.rs @@ -356,7 +356,7 @@ fn push_display_expression( // ╰──────────╯ /// Used for combining two `Compositions`. /// -#[cfg_attr(feature = "cargo-clippy", allow(clippy::suspicious_arithmetic_impl))] +#[allow(clippy::suspicious_arithmetic_impl)] impl Mul for Composition { type Output = Self; diff --git a/crates/api/src/macros.rs b/crates/api/src/macros.rs index 29d870ae..b8e9183c 100644 --- a/crates/api/src/macros.rs +++ b/crates/api/src/macros.rs @@ -69,7 +69,7 @@ macro_rules! terms { #[cfg(test)] mod tests { - use crate::{Term, Atom, Prefix}; + use crate::{Atom, Prefix, Term}; #[test] fn validate_term_macro() { From 4a93dafb9db32a9c72ca1ea2c9af3154bc346953 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Wed, 15 May 2024 18:25:02 -0700 Subject: [PATCH 69/80] NAUM-7 Add v2::convert::ConvertTo, TryConvertTo ...and impl for Measurement. Also refactor original impl of Convertible for Measurement. --- crates/api/CHANGELOG.md | 9 +- crates/api/src/macros.rs | 7 + crates/api/src/measurement/convertible.rs | 107 +++++------- crates/api/src/measurement/v2/convert.rs | 201 ++++++++++++++++------ crates/api/src/v2/convert.rs | 31 ++++ 5 files changed, 241 insertions(+), 114 deletions(-) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 814c5b82..8142eb75 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -24,9 +24,11 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - NAUM-4: `impl PartialOrd for Term` - NAUM-5: Added `crate::Term::as_cow_str()`. - NAUM-6 - - Add new `"v2"` feature. - - Add `v2::convert::ToFraction` trait. + - Added new `"v2"` feature. + - Added `v2::convert::ToFraction` trait. - Implemented `v2::convert::ToFraction` trait for `Unit`, `Measurement`. +- NAUM-7: Added traits `v2::convert::ConvertTo` and `v2::convert::TryConvertTo` and + implemented for `Measurement`. - Added `Unit::into_terms()` for cases where you only need the `Term`s of the `Unit`. - Added `unit` constant: `UNITY` - Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. @@ -57,6 +59,9 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - NAUM-5: (Internal) `Display` implementation for `Unit` now uses `Term::as_cow_str()` logic. - NAUM-6: Updated `AsFraction::as_fraction()` implementation to iterate through `Term`s once instead of twice for building the numerator and denominator. +- NAUM-7 (Internal): Updated `Convertible` implementation for `Measurement` to: + 1. skip the `field_eq()` check when converting, + 2. remove unnecessary `.clone()` call when converting from a `&str`. ### Deprecated diff --git a/crates/api/src/macros.rs b/crates/api/src/macros.rs index b8e9183c..e83f8667 100644 --- a/crates/api/src/macros.rs +++ b/crates/api/src/macros.rs @@ -5,6 +5,13 @@ macro_rules! measurement { }; } +#[macro_export] +macro_rules! unit { + ($($term:expr),+) => { + $crate::Unit::new(vec![$($term)+]) + }; +} + /// The `term!` macro makes building `Term`s slightly more ergonomic and terse. /// It was initially made for testing purposes (since `Term`s are really mainly /// used by internal APIs), but since they are used all over the place, it may diff --git a/crates/api/src/measurement/convertible.rs b/crates/api/src/measurement/convertible.rs index ee0368be..de5ec0c2 100644 --- a/crates/api/src/measurement/convertible.rs +++ b/crates/api/src/measurement/convertible.rs @@ -1,7 +1,7 @@ #![allow(clippy::large_enum_variant)] #![allow(clippy::result_large_err)] -use crate::{Convertible, Error, FieldEq, IsCompatibleWith, Measurement, Unit}; +use crate::{Convertible, Error, IsCompatibleWith, Measurement, Unit}; use std::str::FromStr; /// This implementation of `Convertible` lets you pass in a `&str` for the @@ -16,9 +16,19 @@ impl<'a> Convertible<&'a str> for Measurement { #[inline] fn convert_to(&self, expression: &'a str) -> Result { - let other_unit = Unit::from_str(expression)?; - - convert_measurement(self, &other_unit) + let dest_unit = Unit::from_str(expression)?; + + if self.is_compatible_with(&dest_unit) { + Ok(Self { + value: self.converted_scalar(&dest_unit), + unit: dest_unit, + }) + } else { + Err(Error::IncompatibleUnitTypes { + lhs: self.unit.expression(), + rhs: expression.to_string(), + }) + } } } @@ -31,108 +41,85 @@ impl<'a> Convertible<&'a Unit> for Measurement { type ConversionError = Error; #[inline] - fn convert_to(&self, other_unit: &'a Unit) -> Result { - convert_measurement(self, other_unit) - } -} - -fn convert_measurement(lhs: &Measurement, dest_unit: &Unit) -> Result { - // Short-circuit if `dest_unit` is the same as the Measurement's Unit. - if lhs.unit.field_eq(dest_unit) { - return Ok(lhs.clone()); - } - - let source_unit = &lhs.unit; - - if !source_unit.is_compatible_with(dest_unit) { - let e = Error::IncompatibleUnitTypes { - lhs: source_unit.expression(), - rhs: dest_unit.expression(), - }; - return Err(e); + fn convert_to(&self, rhs: &'a Unit) -> Result { + if self.is_compatible_with(rhs) { + Ok(Self { + value: self.converted_scalar(rhs), + unit: rhs.clone(), + }) + } else { + Err(Error::IncompatibleUnitTypes { + lhs: self.unit.expression(), + rhs: rhs.expression(), + }) + } } - - let new_measurement = Measurement { - value: lhs.converted_scalar(dest_unit), - unit: dest_unit.clone(), - }; - - Ok(new_measurement) } #[cfg(test)] mod tests { + use crate::testing::const_units::{KILOMETER, METER}; + use super::*; use approx::{assert_relative_eq, assert_ulps_eq}; + macro_rules! try_convert { + ($subject:expr, $unit:expr, $expected_value:expr) => { + let converted = $subject.convert_to($unit).unwrap(); + assert_eq!(converted, $subject); + assert_relative_eq!(converted.value, $expected_value); + assert_ulps_eq!(converted.value, $expected_value); + }; + } + #[test] fn validate_convert_to_meter_to_meter_str() { let meter = Measurement::try_new(1.0, "m").unwrap(); - let converted = meter.convert_to("m").unwrap(); - assert_eq!(converted, meter); - assert_relative_eq!(converted.value, 1.0); - assert_ulps_eq!(converted.value, 1.0); + try_convert!(meter, "m", 1.0); } #[test] fn validate_convert_to_meter_to_2meter_str() { let meter = Measurement::try_new(1.0, "m").unwrap(); - let converted = meter.convert_to("2m").unwrap(); - assert_relative_eq!(converted.value, 0.5); - assert_ulps_eq!(converted.value, 0.5); + try_convert!(meter, "2m", 0.5); } #[test] fn validate_convert_to_meter_to_km_str() { let meter = Measurement::try_new(1000.0, "m").unwrap(); - let converted = meter.convert_to("km").unwrap(); - assert_relative_eq!(converted.value, 1.0); - assert_ulps_eq!(converted.value, 1.0); + try_convert!(meter, "km", 1.0); } #[test] fn validate_convert_to_meter_to_2km_str() { let meter = Measurement::try_new(1000.0, "m").unwrap(); - let converted = meter.convert_to("2km").unwrap(); - assert_relative_eq!(converted.value, 0.5); - assert_ulps_eq!(converted.value, 0.5); + try_convert!(meter, "2km", 0.5); } #[test] fn validate_convert_to_meter_to_meter_unit() { let meter = Measurement::try_new(1.0, "m").unwrap(); - let unit = Unit::from_str("m").unwrap(); - let converted = meter.convert_to(&unit).unwrap(); - assert_eq!(converted, meter); - assert_relative_eq!(converted.value, 1.0); - assert_ulps_eq!(converted.value, 1.0); + try_convert!(meter, &METER, 1.0); } #[test] fn validate_convert_to_meter_to_2meter_unit() { let meter = Measurement::try_new(1.0, "m").unwrap(); - let unit = Unit::from_str("2m").unwrap(); - let converted = meter.convert_to(&unit).unwrap(); - assert_relative_eq!(converted.value, 0.5); - assert_ulps_eq!(converted.value, 0.5); + let unit = unit!(term!(Meter, factor: 2)); + try_convert!(meter, &unit, 0.5); } #[test] fn validate_convert_to_meter_to_km_unit() { let meter = Measurement::try_new(1000.0, "m").unwrap(); - let unit = Unit::from_str("km").unwrap(); - let converted = meter.convert_to(&unit).unwrap(); - assert_relative_eq!(converted.value, 1.0); - assert_ulps_eq!(converted.value, 1.0); + try_convert!(meter, &KILOMETER, 1.0); } #[test] fn validate_convert_to_meter_to_2km_unit() { let meter = Measurement::try_new(1000.0, "m").unwrap(); - let unit = Unit::from_str("2km").unwrap(); - let converted = meter.convert_to(&unit).unwrap(); - assert_relative_eq!(converted.value, 0.5); - assert_ulps_eq!(converted.value, 0.5); + let unit = unit!(term!(Kilo, Meter, factor: 2)); + try_convert!(meter, &unit, 0.5); } #[test] diff --git a/crates/api/src/measurement/v2/convert.rs b/crates/api/src/measurement/v2/convert.rs index 701ba807..5a59b74f 100644 --- a/crates/api/src/measurement/v2/convert.rs +++ b/crates/api/src/measurement/v2/convert.rs @@ -1,4 +1,8 @@ -use crate::{unit, v2::convert::ToFraction, Measurement, Unit}; +use crate::{ + unit, + v2::convert::{ToFraction, TryConvertTo}, + Error, Measurement, Unit, +}; impl ToFraction> for Measurement { fn to_fraction(&self) -> (Self, Option) { @@ -25,75 +29,168 @@ impl ToFraction> for Measurement { } } +impl<'a> TryConvertTo<&'a str> for Measurement { + type Error = Error; + + fn try_convert_to(&self, rhs: &'a str) -> Result { + // Delegate to old implementation for now. + crate::Convertible::convert_to(self, rhs) + } +} + +impl<'a> TryConvertTo<&'a Unit> for Measurement { + type Error = Error; + + fn try_convert_to(&self, rhs: &'a Unit) -> Result { + // Delegate to old implementation for now. + crate::Convertible::convert_to(self, rhs) + } +} + #[cfg(test)] mod tests { - use crate::{ - testing::const_units::{GRAM_METER, METER, METER_PER_SECOND, PER_SECOND, SECOND}, - unit::UNITY, - Measurement, - }; - use super::*; - macro_rules! validate_fraction_parts { - ( + mod to_fraction { + use crate::{ + testing::const_units::{GRAM_METER, METER, METER_PER_SECOND, PER_SECOND, SECOND}, + unit::UNITY, + Measurement, + }; + + use super::*; + + macro_rules! validate_fraction_parts { + ( $measurement:expr, expected_numerator => $expected_numerator:expr, expected_denominator => $expected_denominator:expr ) => { - let fraction = $measurement.to_fraction(); - assert_eq!(&fraction.0, &$expected_numerator); - assert_eq!(fraction.1, $expected_denominator); + let fraction = $measurement.to_fraction(); + assert_eq!(&fraction.0, &$expected_numerator); + assert_eq!(fraction.1, $expected_denominator); - let numerator = $measurement.to_numerator(); - assert_eq!(numerator, $expected_numerator); + let numerator = $measurement.to_numerator(); + assert_eq!(numerator, $expected_numerator); - let denominator = $measurement.to_denominator(); - assert_eq!(denominator, $expected_denominator); - }; - } + let denominator = $measurement.to_denominator(); + assert_eq!(denominator, $expected_denominator); + }; + } - #[test] - fn validate_one_numerator_term() { - let measurement = Measurement::new(42.0, METER); + #[test] + fn validate_one_numerator_term() { + let measurement = Measurement::new(42.0, METER); - validate_fraction_parts!( - measurement, - expected_numerator => measurement, - expected_denominator => None - ); - } + validate_fraction_parts!( + measurement, + expected_numerator => measurement, + expected_denominator => None + ); + } - #[test] - fn validate_two_numerator_terms() { - let measurement = Measurement::new(42.0, GRAM_METER); + #[test] + fn validate_two_numerator_terms() { + let measurement = Measurement::new(42.0, GRAM_METER); - validate_fraction_parts!( - measurement, - expected_numerator => measurement, - expected_denominator => None - ); - } + validate_fraction_parts!( + measurement, + expected_numerator => measurement, + expected_denominator => None + ); + } - #[test] - fn validate_one_numerator_term_one_denominator_term() { - let measurement = Measurement::new(42.0, METER_PER_SECOND); + #[test] + fn validate_one_numerator_term_one_denominator_term() { + let measurement = Measurement::new(42.0, METER_PER_SECOND); - validate_fraction_parts!( - measurement, - expected_numerator => Measurement::new(42.0, METER), - expected_denominator => Some(SECOND) - ); + validate_fraction_parts!( + measurement, + expected_numerator => Measurement::new(42.0, METER), + expected_denominator => Some(SECOND) + ); + } + + #[test] + fn validate_one_denominator_term() { + let measurement = Measurement::new(42.0, PER_SECOND); + + validate_fraction_parts!( + measurement, + expected_numerator => Measurement::new(42.0, UNITY), + expected_denominator => Some(SECOND) + ); + } } - #[test] - fn validate_one_denominator_term() { - let measurement = Measurement::new(42.0, PER_SECOND); + mod try_convert_to { + use std::str::FromStr; + + use approx::{assert_relative_eq, assert_ulps_eq}; - validate_fraction_parts!( - measurement, - expected_numerator => Measurement::new(42.0, UNITY), - expected_denominator => Some(SECOND) - ); + use crate::testing::const_units::{KILOMETER, METER}; + + use super::*; + + macro_rules! try_convert_test { + ($subject:expr, $unit:expr, $expected_value:expr) => { + let converted = $subject.try_convert_to($unit).unwrap(); + assert_eq!(converted, $subject); + assert_relative_eq!(converted.value, $expected_value); + assert_ulps_eq!(converted.value, $expected_value); + }; + } + + #[test] + fn try_convert_to_str_test() { + let meter = Measurement::new(1.0, METER); + try_convert_test!(meter, "m", 1.0); + try_convert_test!(meter, "2m", 0.5); + try_convert_test!(meter, "m2/m", 1.0); + // This seems like it should pass, but see docs in term/is_compatible_with.rs as to why + // it's not. + assert!(meter.try_convert_to("m{meow}").is_err()); + + let meter = Measurement::new(1000.0, METER); + try_convert_test!(meter, "km", 1.0); + try_convert_test!(meter, "2km", 0.5); + try_convert_test!(meter, "2km2/2km", 0.5); + assert!(meter.try_convert_to("g").is_err()); + } + + #[test] + fn try_convert_to_unit_test() { + { + let meter = Measurement::new(1.0, METER); + try_convert_test!(meter, &METER, 1.0); + try_convert_test!(meter, &KILOMETER, 0.001); + } + + { + let meter = Measurement::new(1000.0, METER); + try_convert_test!(meter, &KILOMETER, 1.0); + try_convert_test!(meter, &METER, 1000.0); + } + + { + let m1 = Measurement::try_new(10.0, "[acr_us]/{tree}").unwrap(); + + let u1 = Unit::from_str("m2/{tree}").unwrap(); + let u2 = Unit::from_str("m2/{vine}").unwrap(); + + try_convert_test!(m1, &u1, 40_468.726_098_742_52); + assert!(m1.try_convert_to(&u2).is_err()); + } + + { + let m1 = Measurement::try_new(10.0, "{tree}").unwrap(); + + let u1 = Unit::from_str("{tree}").unwrap(); + let u2 = Unit::from_str("{vine}").unwrap(); + + try_convert_test!(m1, &u1, 10.0); + assert!(m1.try_convert_to(&u2).is_err()); + } + } } } diff --git a/crates/api/src/v2/convert.rs b/crates/api/src/v2/convert.rs index a42ecdac..b7c2073e 100644 --- a/crates/api/src/v2/convert.rs +++ b/crates/api/src/v2/convert.rs @@ -9,3 +9,34 @@ pub trait ToFraction, D = Option, F = (N, D)> { fn to_numerator(&self) -> N; fn to_denominator(&self) -> D; } + +/// Trait for infallible conversion. +/// +/// The differences with this trait compared to `Convertible` are: +/// 1. it doesn't require the output to be a `Result` like the original does. This allows for +/// implementing for types that can guarantee a conversion. +/// 2. it can be implemented for multiple output types. +/// +#[allow(clippy::module_name_repetitions)] +pub trait ConvertTo { + /// _The_ method for doing the conversion. + /// + fn convert_to(&self, rhs: U) -> O; +} + +/// Trait for fallible conversion. +/// +/// The difference with this trait compared to `Convertible` is that it can be implemented for +/// multiple output types. +/// +pub trait TryConvertTo { + type Error; + + /// _The_ method for doing the conversion. + /// + /// # Errors + /// + /// This should fail if `self` couldn't be converted to `O`. + /// + fn try_convert_to(&self, rhs: U) -> Result; +} From c88ea38783e2e4915f72e09e058fb2d9197a2849 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Tue, 21 May 2024 14:22:57 -0700 Subject: [PATCH 70/80] NAUM-8 Add v2::ToReduced,TryToReduced; impl for Unit, Measurement Adds two traits that supercede `reduce::ToReduced` that a) distinguishes between fallible & infallible, and b) allows to implement over more than one output type. --- crates/api/src/measurement/v2/convert.rs | 11 +++++- crates/api/src/unit/v2/convert.rs | 13 +++++- crates/api/src/v2/convert.rs | 50 ++++++++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/crates/api/src/measurement/v2/convert.rs b/crates/api/src/measurement/v2/convert.rs index 5a59b74f..900fa0bd 100644 --- a/crates/api/src/measurement/v2/convert.rs +++ b/crates/api/src/measurement/v2/convert.rs @@ -1,6 +1,6 @@ use crate::{ unit, - v2::convert::{ToFraction, TryConvertTo}, + v2::convert::{ToFraction, TryConvertTo, TryToReduced}, Error, Measurement, Unit, }; @@ -47,6 +47,15 @@ impl<'a> TryConvertTo<&'a Unit> for Measurement { } } +impl TryToReduced for Measurement { + type Error = Error; + + fn try_to_reduced(&self) -> Result { + // Just delegate to the old trait impl for now. + crate::reduce::ToReduced::to_reduced(self) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/api/src/unit/v2/convert.rs b/crates/api/src/unit/v2/convert.rs index b37de8ca..3773edf0 100644 --- a/crates/api/src/unit/v2/convert.rs +++ b/crates/api/src/unit/v2/convert.rs @@ -1,4 +1,8 @@ -use crate::{as_fraction::AsFraction, v2::convert::ToFraction, Unit}; +use crate::{ + as_fraction::AsFraction, + v2::convert::{ToFraction, ToReduced}, + Unit, +}; impl ToFraction for Unit { fn to_fraction(&self) -> (Option, Option) { @@ -17,6 +21,13 @@ impl ToFraction for Unit { } } +impl ToReduced for Unit { + fn to_reduced(&self) -> Self { + // Just delegate to the old trait impl for now. + crate::reduce::ToReduced::to_reduced(self) + } +} + #[cfg(test)] mod tests { use std::str::FromStr; diff --git a/crates/api/src/v2/convert.rs b/crates/api/src/v2/convert.rs index b7c2073e..ec0c83d4 100644 --- a/crates/api/src/v2/convert.rs +++ b/crates/api/src/v2/convert.rs @@ -40,3 +40,53 @@ pub trait TryConvertTo { /// fn try_convert_to(&self, rhs: U) -> Result; } + +/// Trait for implementing infallible unit reduction. +/// +/// NOTE: This differs from the old implementation in that it allows for reducing to more than one +/// output type. +/// +pub trait ToReduced { + fn to_reduced(&self) -> T; +} + +/// Analog to `ToReduced`, this consumes the caller. Useful for if you don't care about keeping the +/// old `Self` around after reducing. +/// +/// NOTE: This is automatically implemented for all types that `impl ToReduced for T`. +/// +pub trait IntoReduced { + fn into_reduced(self) -> T; +} + +impl IntoReduced for T +where + T: ToReduced, +{ + fn into_reduced(self) -> U { + ToReduced::to_reduced(&self) + } +} + +/// Trait for implementing fallible unit reduction. +/// +pub trait TryToReduced { + type Error; + + /// # Errors + /// + /// This should error if/when a type's units can't be reduced to the output type `T`. + /// + fn try_to_reduced(&self) -> Result; +} + +impl TryToReduced for T +where + T: ToReduced, +{ + type Error = std::convert::Infallible; + + fn try_to_reduced(&self) -> Result { + Ok(ToReduced::to_reduced(self)) + } +} From 560909f6fcd2001a6d9e93a991bfa86818115df4 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Tue, 21 May 2024 15:02:17 -0700 Subject: [PATCH 71/80] NAUM-8 Add benchmarks for Unit::to_reduced() --- crates/api/benches/unit_benchmarks.rs | 31 ++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/crates/api/benches/unit_benchmarks.rs b/crates/api/benches/unit_benchmarks.rs index 5b073e14..fe036b37 100644 --- a/crates/api/benches/unit_benchmarks.rs +++ b/crates/api/benches/unit_benchmarks.rs @@ -6,7 +6,7 @@ mod common; use criterion::{BenchmarkId, Criterion}; use std::str::FromStr; -use wise_units::{Composable, IsCompatibleWith, UcumUnit, Unit}; +use wise_units::{reduce::ToReduced, Composable, IsCompatibleWith, UcumUnit, Unit}; macro_rules! bench_over_inputs_method { ($function_name:ident, $test_name:expr, $method_name:ident) => { @@ -64,6 +64,34 @@ bench_over_inputs_method!( expression_reduced ); +fn to_reduced_group(c: &mut Criterion) { + const REDUCIBLES: [&str; 7] = [ + "m2", + "m4/m2", + "har/m2", + "har2/m2", + "g.m2/har", + "g.m4/har", + "[acr_us]/m2/har/[sft_i]", + ]; + + let mut group = c.benchmark_group("Unit::to_reduced()"); + + for unit_str in REDUCIBLES { + group.bench_with_input( + BenchmarkId::new("to_reduced", unit_str), + &unit_str, + |b, unit_str| { + let unit = Unit::from_str(unit_str).unwrap(); + + b.iter(|| unit.to_reduced()); + }, + ); + } + + group.finish() +} + //----------------------------------------------------------------------------- // impl Composable //----------------------------------------------------------------------------- @@ -139,6 +167,7 @@ criterion_group!( magnitude_group, expression_group, expression_reduced_group, + to_reduced_group, composition_group, is_compatible_with_group, display_group, From 73c92b7d9432e7d5fb6660c203f884e70ac2a444 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Tue, 21 May 2024 15:16:17 -0700 Subject: [PATCH 72/80] NAUM-8 Refactor Unit::to_reduced() Previously, the code was hard to read/understand and repeated work (when iterating through the Unit's internal Terms). This fixes that. Benchmarks show 100-500% throughput increase. --- crates/api/CHANGELOG.md | 5 + crates/api/src/composition.rs | 18 +++ crates/api/src/measurement/to_reduced.rs | 8 +- crates/api/src/reduce.rs | 1 + crates/api/src/unit/to_reduced.rs | 147 ++++++++++------------- 5 files changed, 91 insertions(+), 88 deletions(-) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 8142eb75..a627141d 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -29,6 +29,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Implemented `v2::convert::ToFraction` trait for `Unit`, `Measurement`. - NAUM-7: Added traits `v2::convert::ConvertTo` and `v2::convert::TryConvertTo` and implemented for `Measurement`. +- NAUM-8: Added traits `v2::convert::ToReduced` and `TryToReduced`, and implemented for `Unit` + and `Measurement`, respectively. - Added `Unit::into_terms()` for cases where you only need the `Term`s of the `Unit`. - Added `unit` constant: `UNITY` - Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. @@ -62,6 +64,9 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - NAUM-7 (Internal): Updated `Convertible` implementation for `Measurement` to: 1. skip the `field_eq()` check when converting, 2. remove unnecessary `.clone()` call when converting from a `&str`. +- _BREAKING_ NAUM-8 (Internal): Refactored `convert::ToReduced` to simplify and speed up. The + potentially breaking part here is that where units of opposing dimensions (ex. `[acr_us]/m2/har`) + used to reduce to the first remainder unit (ex. `[acr_us]`), they now reduce to the last. ### Deprecated diff --git a/crates/api/src/composition.rs b/crates/api/src/composition.rs index f780cd22..c1e138fe 100644 --- a/crates/api/src/composition.rs +++ b/crates/api/src/composition.rs @@ -1,5 +1,7 @@ use std::{fmt, ops::Mul}; +use num_traits::Inv; + use crate::{term::Exponent, Dimension}; pub const DIMLESS: Composition = Composition::new_dimless(); @@ -453,6 +455,22 @@ impl From for Composition { } } +impl Inv for Composition { + type Output = Self; + + fn inv(self) -> Self::Output { + Self { + electric_charge: self.electric_charge.map(|e| -e), + length: self.length.map(|e| -e), + luminous_intensity: self.luminous_intensity.map(|e| -e), + mass: self.mass.map(|e| -e), + plane_angle: self.plane_angle.map(|e| -e), + temperature: self.temperature.map(|e| -e), + time: self.time.map(|e| -e), + } + } +} + #[cfg(test)] mod tests { use super::{super::Dimension, Composition}; diff --git a/crates/api/src/measurement/to_reduced.rs b/crates/api/src/measurement/to_reduced.rs index 4a402c8c..381b3ef7 100644 --- a/crates/api/src/measurement/to_reduced.rs +++ b/crates/api/src/measurement/to_reduced.rs @@ -92,9 +92,9 @@ mod tests { ); validate_reduction!( - validate_acr_us_per_m2_per_har, + validate_har_per_m2_per_acr_us, 1.0, - "[acr_us]/m2/har", + "har/m2/[acr_us]", 10_000.0, "[acr_us]" ); @@ -160,9 +160,9 @@ mod tests { ); validate_reduction!( - validate_acr_us_per_m2_per_har, + validate_har_per_m2_per_acr_us, 1.0, - "[acr_us]/m2/har", + "har/m2/[acr_us]", 10_000.0, "[acr_us]" ); diff --git a/crates/api/src/reduce.rs b/crates/api/src/reduce.rs index fa7445ae..504900cb 100644 --- a/crates/api/src/reduce.rs +++ b/crates/api/src/reduce.rs @@ -1,4 +1,5 @@ #![allow(clippy::doc_markdown)] + /// Defines an interface for reducing `Unit`s and `Measurements`, where "reducing" is on cancelling /// out `Unit`s that have the same dimension (ex. "[acr_us]" and "har" both have the dimension /// "L2", so they can effectively be canceled out). diff --git a/crates/api/src/unit/to_reduced.rs b/crates/api/src/unit/to_reduced.rs index 4e46e18c..d1dda9fa 100644 --- a/crates/api/src/unit/to_reduced.rs +++ b/crates/api/src/unit/to_reduced.rs @@ -1,8 +1,10 @@ -use crate::{as_fraction::AsFraction, reduce::ToReduced, Composable, Composition, Term}; +use std::borrow::Cow; -use super::Unit; +use num_traits::Inv; + +use crate::{reduce::ToReduced, Composable, Term}; -type OptionCombos = Vec>; +use super::Unit; /// The implementation here checks for `Unit`s in `self`'s numerator and denominator that have the /// same `Composition` (aka "dimension"). For example, if `self` is effectively @@ -47,78 +49,59 @@ impl ToReduced for Unit { /// #[inline] fn to_reduced(&self) -> Self::Output { - match self.as_fraction() { - (Some(numerator), Some(denominator)) => { - let (new_numerators, new_denominators) = - build_unit_parts(&numerator.terms, &denominator.terms); + let mut terms: Vec<_> = self.terms.iter().map(|t| Some(Cow::Borrowed(t))).collect(); - let mut new_terms: Vec = - Vec::with_capacity(new_numerators.len() + new_denominators.len()); - new_terms.extend_from_slice(&new_numerators); + 'outer: for (i, outer_term) in self.terms.iter().enumerate() { + if terms[i].is_none() { + continue 'outer; + } - let new_denominators = - crate::term::num_traits::inv::inv_terms_into(new_denominators); - new_terms.extend_from_slice(&new_denominators); + let next_outer = i + 1; + let remainder = &self.terms[next_outer..]; - Self::new(super::term_reducing::reduce_terms(&new_terms)) - } - (_, _) => Self::new(super::term_reducing::reduce_terms(&self.terms)), - } - } -} + 'inner: for (j, inner_term) in remainder.iter().enumerate() { + let terms_offset = next_outer + j; -/// Iterates through `numerator_terms` and `denominator_terms`, comparing each `Term`s -/// `Composition`. If the `Composition` from the numerator matches one in the denominator, the -/// `Term`s are excluded from the resulting sets of `Term`s. -/// -fn build_unit_parts( - numerator_terms: &[Term], - denominator_terms: &[Term], -) -> (Vec, Vec) { - let mut new_numerator_combos = build_terms_and_compositions(numerator_terms); - let mut new_denominator_combos = build_terms_and_compositions(denominator_terms); - - 'outer: for numerator_combo in new_numerator_combos.iter_mut().rev() { - 'inner: for new_denominator_combo in &mut new_denominator_combos { - match (&numerator_combo, &new_denominator_combo) { - (Some(nc), Some(dc)) => { - if nc.1 == dc.1 { - *numerator_combo = None; - *new_denominator_combo = None; - continue 'outer; - } + if terms[terms_offset].is_none() { + continue 'inner; } - (None, Some(_)) => continue 'outer, - (_, None) => continue 'inner, - } - } - } - ( - filter_results(new_numerator_combos), - filter_results(new_denominator_combos), - ) -} + if outer_term.composition() == inner_term.composition().inv() { + terms[i] = None; + terms[terms_offset] = None; + continue 'outer; + } -/// Takes each `Term` and builds an `Option<(Term, Composition)>`, where each will be used to -/// compare against each numerator/denominator `Term`'s `Composition`. They're wrapped in an -/// `Option` so that when one needs to be removed from the result set, it can just be set to a -/// `None`. -/// -fn build_terms_and_compositions(terms: &[Term]) -> OptionCombos { - terms - .iter() - .map(|term| Some((term.clone(), term.composition()))) - .collect() -} + if outer_term.atom == inner_term.atom + && outer_term.factor == inner_term.factor + && outer_term.annotation == inner_term.annotation + { + let mut new_term = outer_term.clone(); + + new_term.exponent = match (new_term.exponent, inner_term.exponent) { + (None, None) => None, + (None, Some(rhs)) => Some(rhs), + (Some(lhs), None) => Some(lhs), + (Some(lhs), Some(rhs)) => { + let x = lhs + rhs; + + if x == 0 || x == 1 { + None + } else { + Some(x) + } + } + }; + terms[i] = Some(Cow::Owned(new_term)); + terms[next_outer] = None; + continue 'outer; + } + } + } -/// Builds a set of `Terms` from the reduced `option_combos`. -/// -fn filter_results(option_combos: OptionCombos) -> Vec { - option_combos - .into_iter() - .filter_map(|combo| combo.map(|c| c.0)) - .collect() + let terms: Vec = terms.into_iter().flatten().map(Cow::into_owned).collect(); + Self::new(terms) + } } #[cfg(test)] @@ -130,38 +113,38 @@ mod tests { use std::str::FromStr; macro_rules! validate_reduction { - ($test_name:ident, $input:expr, $expected:expr) => { + ($test_name:ident, $input:expr, expected: $expected:expr) => { #[test] fn $test_name() { let unit = Unit::from_str($input).unwrap(); let actual = unit.to_reduced(); let expected = Unit::from_str($expected).unwrap(); - assert_eq!(&actual, &expected); assert_eq!(actual.expression(), expected.expression()); + assert_eq!(&actual, &expected); } }; } - validate_reduction!(validate_m, "m", "m"); - validate_reduction!(validate_m2_per_m, "m2/m", "m"); - validate_reduction!(validate_100m2_per_m, "100m2/m", "100m2/m"); - validate_reduction!(validate_m2_dot_m2, "m2.m2", "m4"); - validate_reduction!(validate_m2_dot_m2_per_s_dot_s, "m2.m2/s.s", "m4/s2"); - validate_reduction!(validate_m2_dot_s_per_s_dot_m2, "m2.s/s.m2", "1"); + validate_reduction!(validate_m, "m", expected: "m"); + validate_reduction!(validate_m2_per_m, "m2/m", expected: "m"); + validate_reduction!(validate_100m2_per_m, "100m2/m", expected: "100m2/m"); + validate_reduction!(validate_m2_dot_m2, "m2.m2", expected: "m4"); + validate_reduction!(validate_m2_dot_m2_per_s_dot_s, "m2.m2/s.s", expected: "m4/s2"); + validate_reduction!(validate_m2_dot_s_per_s_dot_m2, "m2.s/s.m2", expected: "1"); - validate_reduction!(validate_lb_av_dot_har_per_m2, "[lb_av].har/m2", "[lb_av]"); - validate_reduction!(validate_lb_av_dot_har_per_m2_dot_g, "[lb_av].har/m2.g", "1"); + validate_reduction!(validate_lb_av_dot_har_per_m2, "[lb_av].har/m2", expected: "[lb_av]"); + validate_reduction!(validate_lb_av_dot_har_per_m2_dot_g, "[lb_av].har/m2.g", expected: "1"); validate_reduction!( validate_acr_us_per_m2_per_har, "[acr_us]/m2/har", - "[acr_us]" + expected: "har" ); validate_reduction!( validate_acr_us_per_m2_per_har_per_sft_i, "[acr_us]/m2/har/[sft_i]", - "1" + expected: "1" ); } @@ -194,11 +177,7 @@ mod tests { validate_reduction!(validate_lb_av_dot_har_per_m2, "[lb_av].har/m2", "[lb_av]"); validate_reduction!(validate_lb_av_dot_har_per_m2_dot_g, "[lb_av].har/m2.g", "1"); - validate_reduction!( - validate_acr_us_per_m2_per_har, - "[acr_us]/m2/har", - "[acr_us]" - ); + validate_reduction!(validate_acr_us_per_m2_per_har, "[acr_us]/m2/har", "har"); validate_reduction!( validate_acr_us_per_m2_per_har_per_sft_i, "[acr_us]/m2/har/[sft_i]", From 35bcfe2ce87da75d99eef90015ad63e92b78d77a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 20:39:27 +0000 Subject: [PATCH 73/80] Bump actions/cache from 3 to 4 Bumps [actions/cache](https://github.com/actions/cache) from 3 to 4. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/rust-ci.yml | 4 ++-- .github/workflows/security-audit.yml | 2 +- .github/workflows/upload-release.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index c114854d..9aee19a8 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -23,7 +23,7 @@ jobs: with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - uses: actions/checkout@v4 - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: | ~/.cargo/bin/ @@ -50,7 +50,7 @@ jobs: with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - uses: actions/checkout@v4 - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: | ~/.cargo/bin/ diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml index 8f011389..fc923072 100644 --- a/.github/workflows/security-audit.yml +++ b/.github/workflows/security-audit.yml @@ -26,7 +26,7 @@ jobs: with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - uses: actions/checkout@v4 - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: | ~/.cargo/bin/ diff --git a/.github/workflows/upload-release.yml b/.github/workflows/upload-release.yml index 54f8ca37..7172e9fb 100644 --- a/.github/workflows/upload-release.yml +++ b/.github/workflows/upload-release.yml @@ -29,7 +29,7 @@ jobs: uses: actions/checkout@v4 with: ref: ${{ env.TAG }} - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: | ~/.cargo/bin/ From 108c5f0dbcc31e6c513c04766b1b54136b2fc4b0 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 24 May 2024 12:11:28 -0700 Subject: [PATCH 74/80] Move checkout step; trying to workaround ssh-agent bug https://github.com/webfactory/ssh-agent/issues/207 --- .github/workflows/rust-ci.yml | 4 ++-- .github/workflows/security-audit.yml | 2 +- .github/workflows/upload-release.yml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index 9aee19a8..f668e621 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -18,11 +18,11 @@ jobs: name: Test runs-on: ubuntu-latest steps: + - uses: actions/checkout@v4 - name: Setup SSH uses: webfactory/ssh-agent@v0.9.0 with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - - uses: actions/checkout@v4 - uses: actions/cache@v4 with: path: | @@ -45,11 +45,11 @@ jobs: env: DYLD_ROOT_PATH: "/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app" steps: + - uses: actions/checkout@v4 - name: Setup SSH uses: webfactory/ssh-agent@v0.9.0 with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - - uses: actions/checkout@v4 - uses: actions/cache@v4 with: path: | diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml index fc923072..491ba9e1 100644 --- a/.github/workflows/security-audit.yml +++ b/.github/workflows/security-audit.yml @@ -21,11 +21,11 @@ jobs: security-audit: runs-on: ubuntu-latest steps: + - uses: actions/checkout@v4 - name: Setup SSH uses: webfactory/ssh-agent@v0.9.0 with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - - uses: actions/checkout@v4 - uses: actions/cache@v4 with: path: | diff --git a/.github/workflows/upload-release.yml b/.github/workflows/upload-release.yml index 7172e9fb..0a347b4d 100644 --- a/.github/workflows/upload-release.yml +++ b/.github/workflows/upload-release.yml @@ -21,12 +21,12 @@ jobs: name: Upload Release Asset runs-on: ubuntu-latest steps: + - name: Checkout code + uses: actions/checkout@v4 - name: Setup SSH uses: webfactory/ssh-agent@v0.9.0 with: ssh-private-key: ${{ secrets.TELUS_AGCG_MACHINE_USER_KEY }} - - name: Checkout code - uses: actions/checkout@v4 with: ref: ${{ env.TAG }} - uses: actions/cache@v4 From 3979196b617e37af742f967618dd433fa3515baa Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 24 May 2024 14:24:27 -0700 Subject: [PATCH 75/80] NAUM-9 Move annotation_composition -> term::annotation_composable --- crates/api/src/annotation_composition.rs | 13 ------------- crates/api/src/lib.rs | 1 - crates/api/src/term/annotation_composable.rs | 17 +++++++++++++---- crates/api/src/term/is_compatible_with.rs | 4 +++- 4 files changed, 16 insertions(+), 19 deletions(-) delete mode 100644 crates/api/src/annotation_composition.rs diff --git a/crates/api/src/annotation_composition.rs b/crates/api/src/annotation_composition.rs deleted file mode 100644 index 119b73d9..00000000 --- a/crates/api/src/annotation_composition.rs +++ /dev/null @@ -1,13 +0,0 @@ -use std::collections::HashMap; - -use crate::term::Exponent; - -pub type AnnotationComposition = HashMap; - -/// Similar to `Composable`, this is only to allow for checking compatibility on `Unit`s that have -/// annotations. For those cases, we want to be able to ensure that, for example, `m{foo}` is not -/// comparable to `m{bar}`. -/// -pub(crate) trait AnnotationComposable { - fn annotation_composition(self) -> Option; -} diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index 0556e046..191c2e16 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -37,7 +37,6 @@ pub mod unit; #[cfg(feature = "v2")] pub mod v2; -pub(crate) mod annotation_composition; pub(crate) mod term; mod composable; diff --git a/crates/api/src/term/annotation_composable.rs b/crates/api/src/term/annotation_composable.rs index 0372bc40..926aca79 100644 --- a/crates/api/src/term/annotation_composable.rs +++ b/crates/api/src/term/annotation_composable.rs @@ -1,7 +1,16 @@ -use crate::{ - annotation_composition::{AnnotationComposable, AnnotationComposition}, - Term, -}; +use std::collections::HashMap; + +use super::{Exponent, Term}; + +pub(crate) type AnnotationComposition = HashMap; + +/// Similar to `Composable`, this is only to allow for checking compatibility on `Unit`s that have +/// annotations. For those cases, we want to be able to ensure that, for example, `m{foo}` is not +/// comparable to `m{bar}`. +/// +pub(crate) trait AnnotationComposable { + fn annotation_composition(self) -> Option; +} /// Similar to `Composable`, this is only to allow for checking compatibility on `Unit`s whose /// `Term`s have annotations. For those cases, we want to be able to ensure that, for example, diff --git a/crates/api/src/term/is_compatible_with.rs b/crates/api/src/term/is_compatible_with.rs index d2c22afc..f7f8916f 100644 --- a/crates/api/src/term/is_compatible_with.rs +++ b/crates/api/src/term/is_compatible_with.rs @@ -1,6 +1,8 @@ use std::borrow::Cow; -use crate::{annotation_composition::AnnotationComposable, Composable, IsCompatibleWith, Term}; +use crate::{Composable, IsCompatibleWith, Term}; + +use super::annotation_composable::AnnotationComposable; /// In order to enforce compatibility on "non-units" (ex. `{each}`, `{total}`, `{heartbeats}`), /// `Term`s need to compare their annotations along with their `Composition`s. In practice, and From 03a8f8906cb0a35a7bc3fac89a0d4fdf68bd2a47 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 24 May 2024 15:09:15 -0700 Subject: [PATCH 76/80] NAUM-9 Add v2::dim::Dimension and IsCommensurableWith --- crates/api/CHANGELOG.md | 2 ++ crates/api/src/atom.rs | 3 ++ crates/api/src/atom/v2.rs | 1 + crates/api/src/atom/v2/dim.rs | 7 +++++ crates/api/src/measurement/v2.rs | 1 + crates/api/src/measurement/v2/dim.rs | 22 +++++++++++++ crates/api/src/term.rs | 2 ++ crates/api/src/term/is_compatible_with.rs | 5 +-- crates/api/src/term/v2.rs | 1 + crates/api/src/term/v2/dim.rs | 34 ++++++++++++++++++++ crates/api/src/unit/v2.rs | 1 + crates/api/src/unit/v2/dim.rs | 22 +++++++++++++ crates/api/src/v2.rs | 1 + crates/api/src/v2/dim.rs | 35 +++++++++++++++++++++ crates/atom_generator/src/generator/atom.rs | 8 +++++ 15 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 crates/api/src/atom/v2.rs create mode 100644 crates/api/src/atom/v2/dim.rs create mode 100644 crates/api/src/measurement/v2/dim.rs create mode 100644 crates/api/src/term/v2.rs create mode 100644 crates/api/src/term/v2/dim.rs create mode 100644 crates/api/src/unit/v2/dim.rs create mode 100644 crates/api/src/v2/dim.rs diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index a627141d..4273b64a 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -31,6 +31,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). implemented for `Measurement`. - NAUM-8: Added traits `v2::convert::ToReduced` and `TryToReduced`, and implemented for `Unit` and `Measurement`, respectively. +- NAUM-9: Added traits `v2::dim::Dimension` and `IsCommensurableWith` and implemented, + respectively for `Atom`, `Measurement`, `Term`, `Cow<'a, [Term]'>`, `Unit`. - Added `Unit::into_terms()` for cases where you only need the `Term`s of the `Unit`. - Added `unit` constant: `UNITY` - Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. diff --git a/crates/api/src/atom.rs b/crates/api/src/atom.rs index 3e85ba9f..3908239d 100644 --- a/crates/api/src/atom.rs +++ b/crates/api/src/atom.rs @@ -16,6 +16,9 @@ mod hash; mod partial_eq; mod reducible; +#[cfg(feature = "v2")] +mod v2; + #[cfg(test)] mod atom_test; diff --git a/crates/api/src/atom/v2.rs b/crates/api/src/atom/v2.rs new file mode 100644 index 00000000..b1f14854 --- /dev/null +++ b/crates/api/src/atom/v2.rs @@ -0,0 +1 @@ +mod dim; diff --git a/crates/api/src/atom/v2/dim.rs b/crates/api/src/atom/v2/dim.rs new file mode 100644 index 00000000..b4ac338a --- /dev/null +++ b/crates/api/src/atom/v2/dim.rs @@ -0,0 +1,7 @@ +use crate::{v2::dim::Dimension, Atom, Composable, Composition}; + +impl Dimension for Atom { + fn dimension(&self) -> Composition { + Composable::composition(self) + } +} diff --git a/crates/api/src/measurement/v2.rs b/crates/api/src/measurement/v2.rs index bb13da4f..ec305d01 100644 --- a/crates/api/src/measurement/v2.rs +++ b/crates/api/src/measurement/v2.rs @@ -1 +1,2 @@ mod convert; +mod dim; diff --git a/crates/api/src/measurement/v2/dim.rs b/crates/api/src/measurement/v2/dim.rs new file mode 100644 index 00000000..f255fa26 --- /dev/null +++ b/crates/api/src/measurement/v2/dim.rs @@ -0,0 +1,22 @@ +use crate::{ + v2::dim::{Dimension, IsCommensurableWith}, + Composable, Composition, IsCompatibleWith, Measurement, Unit, +}; + +impl Dimension for Measurement { + fn dimension(&self) -> Composition { + Composable::composition(self) + } +} + +impl IsCommensurableWith for Measurement { + fn is_commensurable_with(&self, rhs: &Self) -> bool { + IsCompatibleWith::is_compatible_with(self, rhs) + } +} + +impl IsCommensurableWith for Measurement { + fn is_commensurable_with(&self, rhs: &Unit) -> bool { + IsCompatibleWith::is_compatible_with(self, rhs) + } +} diff --git a/crates/api/src/term.rs b/crates/api/src/term.rs index 703e72a4..b58eb00d 100644 --- a/crates/api/src/term.rs +++ b/crates/api/src/term.rs @@ -9,6 +9,8 @@ mod partial_eq; mod partial_ord; mod reducible; mod ucum_unit; +#[cfg(feature = "v2")] +mod v2; use std::borrow::Cow; diff --git a/crates/api/src/term/is_compatible_with.rs b/crates/api/src/term/is_compatible_with.rs index f7f8916f..7028a9f2 100644 --- a/crates/api/src/term/is_compatible_with.rs +++ b/crates/api/src/term/is_compatible_with.rs @@ -41,11 +41,8 @@ impl IsCompatibleWith for Term { impl<'a> IsCompatibleWith for Cow<'a, [Term]> { fn is_compatible_with(&self, rhs: &Self) -> bool { - let lhs_annotation_composition = self.annotation_composition(); - let rhs_annotation_composition = rhs.annotation_composition(); - self.composition() == rhs.composition() - && rhs_annotation_composition == lhs_annotation_composition + && self.annotation_composition() == rhs.annotation_composition() } } diff --git a/crates/api/src/term/v2.rs b/crates/api/src/term/v2.rs new file mode 100644 index 00000000..b1f14854 --- /dev/null +++ b/crates/api/src/term/v2.rs @@ -0,0 +1 @@ +mod dim; diff --git a/crates/api/src/term/v2/dim.rs b/crates/api/src/term/v2/dim.rs new file mode 100644 index 00000000..f3f43e55 --- /dev/null +++ b/crates/api/src/term/v2/dim.rs @@ -0,0 +1,34 @@ +use std::borrow::Cow; + +use crate::{ + v2::dim::{Dimension, IsCommensurableWith}, + Composable, Composition, IsCompatibleWith, Term, +}; + +impl Dimension for Term { + fn dimension(&self) -> Composition { + Composable::composition(self) + } +} + +impl IsCommensurableWith for Term { + /// See `impl IsCompatibleWith for Term` as to why this has a special implementation here. + /// + fn is_commensurable_with(&self, rhs: &Self) -> bool { + IsCompatibleWith::is_compatible_with(self, rhs) + } +} + +impl<'a> Dimension for Cow<'a, [Term]> { + fn dimension(&self) -> Composition { + Composable::composition(self) + } +} + +impl<'a> IsCommensurableWith for Cow<'a, [Term]> { + /// See `impl<'a> IsCompatibleWith for Cow<'a, [Term]>` as to why this has a special implementation here. + /// + fn is_commensurable_with(&self, rhs: &Self) -> bool { + IsCompatibleWith::is_compatible_with(self, rhs) + } +} diff --git a/crates/api/src/unit/v2.rs b/crates/api/src/unit/v2.rs index bb13da4f..ec305d01 100644 --- a/crates/api/src/unit/v2.rs +++ b/crates/api/src/unit/v2.rs @@ -1 +1,2 @@ mod convert; +mod dim; diff --git a/crates/api/src/unit/v2/dim.rs b/crates/api/src/unit/v2/dim.rs new file mode 100644 index 00000000..db61cf0c --- /dev/null +++ b/crates/api/src/unit/v2/dim.rs @@ -0,0 +1,22 @@ +use crate::{ + v2::dim::{Dimension, IsCommensurableWith}, + Composable, Composition, IsCompatibleWith, Measurement, Unit, +}; + +impl Dimension for Unit { + fn dimension(&self) -> Composition { + Composable::composition(self) + } +} + +impl IsCommensurableWith for Unit { + fn is_commensurable_with(&self, rhs: &Self) -> bool { + IsCompatibleWith::is_compatible_with(self, rhs) + } +} + +impl IsCommensurableWith for Unit { + fn is_commensurable_with(&self, rhs: &Measurement) -> bool { + IsCompatibleWith::is_compatible_with(self, rhs) + } +} diff --git a/crates/api/src/v2.rs b/crates/api/src/v2.rs index b5b67213..ce6bd86e 100644 --- a/crates/api/src/v2.rs +++ b/crates/api/src/v2.rs @@ -1 +1,2 @@ pub mod convert; +pub mod dim; diff --git a/crates/api/src/v2/dim.rs b/crates/api/src/v2/dim.rs new file mode 100644 index 00000000..6e55118a --- /dev/null +++ b/crates/api/src/v2/dim.rs @@ -0,0 +1,35 @@ +//! Types here deal with core aspects of dimensional analysis of other types. +//! + +use std::ops::Mul; + +/// A type that can represent the dimension of another type must implement this. +/// +pub trait Dimension +where + D: PartialEq + Mul, +{ + /// Returns the dimension of `self`, which may be a combination of more than one dimension () + /// + fn dimension(&self) -> D; +} + +/// Trait for determining if two things are dimensionally equal, aka commensurable. Per [Dimensional analysis#Dimensional homogeneity +/// (commensurability)](https://en.wikipedia.org/wiki/Dimensional_analysis#Dimensional_homogeneity_(commensurability): +/// +/// > The most basic rule of dimensional analysis is that of dimensional homogeneity.[6] +/// > Only commensurable quantities (physical quantities having the same dimension) may be +/// > compared, equated, added, or subtracted. +/// +/// Will replace `crate::IsCompatibleWith`. +/// +pub trait IsCommensurableWith: Dimension +where + Rhs: IsCommensurableWith, + D: PartialEq + Mul, +{ + #[inline] + fn is_commensurable_with(&self, rhs: &Rhs) -> bool { + self.dimension() == rhs.dimension() + } +} diff --git a/crates/atom_generator/src/generator/atom.rs b/crates/atom_generator/src/generator/atom.rs index 1bc7eae9..ca42f6d4 100644 --- a/crates/atom_generator/src/generator/atom.rs +++ b/crates/atom_generator/src/generator/atom.rs @@ -24,11 +24,19 @@ pub(super) fn generate_file_body(atom_list: &RustAtomList) -> String { #![allow(clippy::unreadable_literal, clippy::too_many_lines, clippy::match_same_arms)] mod composable; + mod definition; mod display; + mod function_set; mod hash; mod partial_eq; mod reducible; + #[cfg(feature = "v2")] + mod v2; + + #[cfg(test)] + mod atom_test; + use crate::{ is_compatible_with::DefaultCompatibility, reducible::Reducible, Classification, Property, UcumSymbol, UcumUnit, Unit, From f4abf3fca11ffd3bc70e6a7e7c3565e5795c5275 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Fri, 24 May 2024 17:43:25 -0700 Subject: [PATCH 77/80] NAUM-10 Add v2::ops::CommensurableEq trait and impl ...for Measurement, Unit, Term, and Atom. --- crates/api/CHANGELOG.md | 6 ++-- crates/api/benches/unit_benchmarks.rs | 24 +++++++++++++++ crates/api/src/atom/v2.rs | 1 + crates/api/src/atom/v2/dim.rs | 11 ++++++- crates/api/src/atom/v2/ops.rs | 30 +++++++++++++++++++ crates/api/src/measurement/partial_eq.rs | 3 +- crates/api/src/measurement/v2.rs | 1 + crates/api/src/measurement/v2/ops.rs | 38 ++++++++++++++++++++++++ crates/api/src/term/v2.rs | 1 + crates/api/src/term/v2/ops.rs | 36 ++++++++++++++++++++++ crates/api/src/testing.rs | 10 +++++++ crates/api/src/unit/ops.rs | 2 ++ crates/api/src/unit/v2.rs | 1 + crates/api/src/unit/v2/ops.rs | 36 ++++++++++++++++++++++ crates/api/src/v2.rs | 1 + crates/api/src/v2/ops.rs | 32 ++++++++++++++++++++ 16 files changed, 229 insertions(+), 4 deletions(-) create mode 100644 crates/api/src/atom/v2/ops.rs create mode 100644 crates/api/src/measurement/v2/ops.rs create mode 100644 crates/api/src/term/v2/ops.rs create mode 100644 crates/api/src/unit/v2/ops.rs create mode 100644 crates/api/src/v2/ops.rs diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 4273b64a..a5243e78 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -31,8 +31,10 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). implemented for `Measurement`. - NAUM-8: Added traits `v2::convert::ToReduced` and `TryToReduced`, and implemented for `Unit` and `Measurement`, respectively. -- NAUM-9: Added traits `v2::dim::Dimension` and `IsCommensurableWith` and implemented, - respectively for `Atom`, `Measurement`, `Term`, `Cow<'a, [Term]'>`, `Unit`. +- NAUM-9: Added traits `v2::dim::Dimension` and `IsCommensurableWith` and implemented for + `Atom`, `Measurement`, `Term`, `Cow<'a, [Term]'>`, `Unit`. +- NAUM-10: Added trait `v2::ops::IsCommensurableWith` and implemented for `Measurement`, `Unit`, + `Term`, and `Atom`. - Added `Unit::into_terms()` for cases where you only need the `Term`s of the `Unit`. - Added `unit` constant: `UNITY` - Added `term` constants: `UNITY`, `UNITY_ARRAY`, and `UNITY_ARRAY_REF`. diff --git a/crates/api/benches/unit_benchmarks.rs b/crates/api/benches/unit_benchmarks.rs index fe036b37..2bb6935b 100644 --- a/crates/api/benches/unit_benchmarks.rs +++ b/crates/api/benches/unit_benchmarks.rs @@ -145,6 +145,29 @@ fn from_str_group(c: &mut Criterion) { //----------------------------------------------------------------------------- bench_over_inputs_math!(partial_eq_group, "Unit::partial_eq()", ==); +fn commensurable_eq_group(c: &mut Criterion) { + #[cfg(feature = "v2")] + { + use wise_units::v2::ops::CommensurableEq; + + let mut group = c.benchmark_group("Unit::commensurable_eq()"); + + for pair in common::UNIT_PAIRS { + group.bench_with_input( + BenchmarkId::new("commensurable_eq", format!("{}->{}", pair.0, pair.1)), + &pair, + |b, (lhs_str, rhs_str)| { + let lhs = Unit::from_str(lhs_str).unwrap(); + let rhs = Unit::from_str(rhs_str).unwrap(); + + b.iter(|| lhs.commensurable_eq(&rhs)); + }, + ); + } + + group.finish() + } +} //----------------------------------------------------------------------------- // impl PartialOrd //----------------------------------------------------------------------------- @@ -173,6 +196,7 @@ criterion_group!( display_group, from_str_group, partial_eq_group, + commensurable_eq_group, mul_group, div_group, partial_ord_gt_group, diff --git a/crates/api/src/atom/v2.rs b/crates/api/src/atom/v2.rs index b1f14854..02c9e4fb 100644 --- a/crates/api/src/atom/v2.rs +++ b/crates/api/src/atom/v2.rs @@ -1 +1,2 @@ mod dim; +mod ops; diff --git a/crates/api/src/atom/v2/dim.rs b/crates/api/src/atom/v2/dim.rs index b4ac338a..42e9feac 100644 --- a/crates/api/src/atom/v2/dim.rs +++ b/crates/api/src/atom/v2/dim.rs @@ -1,7 +1,16 @@ -use crate::{v2::dim::Dimension, Atom, Composable, Composition}; +use crate::{ + v2::dim::{Dimension, IsCommensurableWith}, + Atom, Composable, Composition, IsCompatibleWith, +}; impl Dimension for Atom { fn dimension(&self) -> Composition { Composable::composition(self) } } + +impl IsCommensurableWith for Atom { + fn is_commensurable_with(&self, rhs: &Self) -> bool { + IsCompatibleWith::is_compatible_with(self, rhs) + } +} diff --git a/crates/api/src/atom/v2/ops.rs b/crates/api/src/atom/v2/ops.rs new file mode 100644 index 00000000..1049f2ff --- /dev/null +++ b/crates/api/src/atom/v2/ops.rs @@ -0,0 +1,30 @@ +use approx::ulps_eq; + +use crate::{ + v2::{dim::IsCommensurableWith, ops::CommensurableEq}, + Atom, Composition, UcumUnit, +}; + +impl CommensurableEq for Atom { + fn commensurable_eq(&self, other: &Self) -> Option { + if !self.is_commensurable_with(other) { + return None; + } + + Some(ulps_eq!(self.scalar(), other.scalar())) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn commensurable_eq_test() { + let lhs = Atom::Meter; + + assert_eq!(lhs.commensurable_eq(&lhs), Some(true)); + assert_eq!(lhs.commensurable_eq(&Atom::FootInternational), Some(false)); + assert!(lhs.commensurable_eq(&Atom::Gram).is_none()); + } +} diff --git a/crates/api/src/measurement/partial_eq.rs b/crates/api/src/measurement/partial_eq.rs index ec9417c5..b1cc18a7 100644 --- a/crates/api/src/measurement/partial_eq.rs +++ b/crates/api/src/measurement/partial_eq.rs @@ -1,6 +1,7 @@ -use crate::{is_compatible_with::IsCompatibleWith, measurement::Measurement, ucum_unit::UcumUnit}; use approx::ulps_eq; +use crate::{is_compatible_with::IsCompatibleWith, measurement::Measurement, ucum_unit::UcumUnit}; + /// `Measurement`s are `PartialEq` if /// /// a) their `Unit`s are compatible diff --git a/crates/api/src/measurement/v2.rs b/crates/api/src/measurement/v2.rs index ec305d01..1149c80c 100644 --- a/crates/api/src/measurement/v2.rs +++ b/crates/api/src/measurement/v2.rs @@ -1,2 +1,3 @@ mod convert; mod dim; +mod ops; diff --git a/crates/api/src/measurement/v2/ops.rs b/crates/api/src/measurement/v2/ops.rs new file mode 100644 index 00000000..594441ac --- /dev/null +++ b/crates/api/src/measurement/v2/ops.rs @@ -0,0 +1,38 @@ +use approx::ulps_eq; + +use crate::{ + v2::{dim::IsCommensurableWith, ops::CommensurableEq}, + Composition, Measurement, UcumUnit, +}; + +impl CommensurableEq for Measurement { + fn commensurable_eq(&self, other: &Self) -> Option { + if !self.is_commensurable_with(other) { + return None; + } + + Some(ulps_eq!(self.scalar(), other.scalar())) + } +} + +#[cfg(test)] +mod tests { + use crate::testing::const_units::{GRAM, KILOMETER, METER}; + + use super::*; + + #[test] + fn commensurable_eq_test() { + let lhs = Measurement::new(1000.0, METER); + assert_eq!(lhs.commensurable_eq(&lhs), Some(true)); + + let rhs = Measurement::new(1.0, KILOMETER); + assert_eq!(lhs.commensurable_eq(&rhs), Some(true)); + + let rhs = Measurement::new(1.1, KILOMETER); + assert_eq!(lhs.commensurable_eq(&rhs), Some(false)); + + let rhs = Measurement::new(1000.0, GRAM); + assert_eq!(lhs.commensurable_eq(&rhs), None); + } +} diff --git a/crates/api/src/term/v2.rs b/crates/api/src/term/v2.rs index b1f14854..02c9e4fb 100644 --- a/crates/api/src/term/v2.rs +++ b/crates/api/src/term/v2.rs @@ -1 +1,2 @@ mod dim; +mod ops; diff --git a/crates/api/src/term/v2/ops.rs b/crates/api/src/term/v2/ops.rs new file mode 100644 index 00000000..6452c4cc --- /dev/null +++ b/crates/api/src/term/v2/ops.rs @@ -0,0 +1,36 @@ +use approx::ulps_eq; + +use crate::{ + v2::{dim::IsCommensurableWith, ops::CommensurableEq}, + Composition, Term, UcumUnit, +}; + +impl CommensurableEq for Term { + fn commensurable_eq(&self, other: &Self) -> Option { + if !self.is_commensurable_with(other) { + return None; + } + + Some(ulps_eq!(self.scalar(), other.scalar())) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn commensurable_eq_test() { + let lhs = term!(Meter, factor: 1000); + let rhs = term!(Kilo, Meter); + assert_eq!(lhs.commensurable_eq(&rhs), Some(true)); + + let lhs = term!(Meter, factor: 10); + let rhs = term!(Kilo, Meter); + assert_eq!(lhs.commensurable_eq(&rhs), Some(false)); + + let lhs = term!(Meter); + let rhs = term!(Gram); + assert!(lhs.commensurable_eq(&rhs).is_none()); + } +} diff --git a/crates/api/src/testing.rs b/crates/api/src/testing.rs index a677b333..d47673d5 100644 --- a/crates/api/src/testing.rs +++ b/crates/api/src/testing.rs @@ -23,6 +23,16 @@ pub(crate) mod const_units { }]), }; + pub(crate) const GRAM: Unit = Unit { + terms: Cow::Borrowed(&[Term { + factor: None, + prefix: None, + atom: Some(Atom::Gram), + exponent: None, + annotation: None, + }]), + }; + pub(crate) const GRAM_METER: Unit = Unit { terms: Cow::Borrowed(&[ Term { diff --git a/crates/api/src/unit/ops.rs b/crates/api/src/unit/ops.rs index cb712cd7..07c4b91d 100644 --- a/crates/api/src/unit/ops.rs +++ b/crates/api/src/unit/ops.rs @@ -133,6 +133,8 @@ mod tests { #[test] #[allow(clippy::eq_op)] fn validate_div() { + assert_eq!(METER / METER, UNITY); + let expected = Unit::from_str("m/km").unwrap(); assert_eq!(METER / KILOMETER, expected); diff --git a/crates/api/src/unit/v2.rs b/crates/api/src/unit/v2.rs index ec305d01..1149c80c 100644 --- a/crates/api/src/unit/v2.rs +++ b/crates/api/src/unit/v2.rs @@ -1,2 +1,3 @@ mod convert; mod dim; +mod ops; diff --git a/crates/api/src/unit/v2/ops.rs b/crates/api/src/unit/v2/ops.rs new file mode 100644 index 00000000..45a7657e --- /dev/null +++ b/crates/api/src/unit/v2/ops.rs @@ -0,0 +1,36 @@ +use approx::ulps_eq; + +use crate::{ + v2::{dim::IsCommensurableWith, ops::CommensurableEq}, + Composition, UcumUnit, Unit, +}; + +impl CommensurableEq for Unit { + fn commensurable_eq(&self, other: &Self) -> Option { + if !self.is_commensurable_with(other) { + return None; + } + + Some(ulps_eq!(self.scalar(), other.scalar())) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn commensurable_eq_test() { + let lhs = unit!(term!(Meter, factor: 1000)); + let rhs = unit!(term!(Kilo, Meter)); + assert_eq!(lhs.commensurable_eq(&rhs), Some(true)); + + let lhs = unit!(term!(Meter, factor: 10)); + let rhs = unit!(term!(Kilo, Meter)); + assert_eq!(lhs.commensurable_eq(&rhs), Some(false)); + + let lhs = unit!(term!(Meter)); + let rhs = unit!(term!(Gram)); + assert!(lhs.commensurable_eq(&rhs).is_none()); + } +} diff --git a/crates/api/src/v2.rs b/crates/api/src/v2.rs index ce6bd86e..e35856ab 100644 --- a/crates/api/src/v2.rs +++ b/crates/api/src/v2.rs @@ -1,2 +1,3 @@ pub mod convert; pub mod dim; +pub mod ops; diff --git a/crates/api/src/v2/ops.rs b/crates/api/src/v2/ops.rs new file mode 100644 index 00000000..82973ce1 --- /dev/null +++ b/crates/api/src/v2/ops.rs @@ -0,0 +1,32 @@ +use std::ops::Mul; + +use super::dim::IsCommensurableWith; + +/// Trait for comparisons that checks for equality first. Equality checks must only be done with +/// types that are commensurable. Return `None` if types are _not_ commensurable, otherwise +/// `Some(result)`. +/// +/// This trait should be (well, should become) the de facto method for checking equality between +/// measurements (notice lower-case "m" there, indicating objects that can measure, not necessarily +/// only `Measurement`), etc. Historically, we've used `PartialEq` implementations, but those +/// should've been reserved for object equality, not semantic equality (this trait checks the +/// latter, not the former). +/// +pub trait CommensurableEq: IsCommensurableWith +where + Rhs: IsCommensurableWith, + D: PartialEq + Mul, +{ + /// This method tests the commensurability between `self` and `other`, then checks if their + /// scalar values are equal. + /// + fn commensurable_eq(&self, other: &Rhs) -> Option; + + /// This method tests the commensurability between `self` and `other`, then checks if their + /// scalar values are _not_ equal. + /// + #[inline] + fn commensurable_ne(&self, other: &Rhs) -> Option { + self.commensurable_eq(other).map(|r| !r) + } +} From 084f135dd76813397b0fd0d618583146013831a2 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Thu, 30 May 2024 10:38:15 -0700 Subject: [PATCH 78/80] NAUM-57 Fix typos in Atom, Property, parser --- crates/api/src/atom.rs | 20 +- crates/api/src/property.rs | 18 +- crates/api/src/unit/parser.rs | 4 +- .../api/src/unit/parser/symbols/symbol.pest | 8 +- crates/atom_generator/Atoms.toml | 2554 ++++++++--------- 5 files changed, 1302 insertions(+), 1302 deletions(-) diff --git a/crates/api/src/atom.rs b/crates/api/src/atom.rs index 3908239d..ffb63016 100644 --- a/crates/api/src/atom.rs +++ b/crates/api/src/atom.rs @@ -334,7 +334,7 @@ pub enum Atom { Barn, TechnicalAtmosphere, Mho, - PoundPerSqareInch, + PoundPerSquareInch, Circle, Spere, MetricCarat, @@ -694,7 +694,7 @@ impl Atom { Self::Barn => BARN, Self::TechnicalAtmosphere => Definition::new_value_terms(1f64, "kgf/cm2"), Self::Mho => MHO, - Self::PoundPerSqareInch => Definition::new_value_terms(1f64, "[lbf_av]/[in_i]2"), + Self::PoundPerSquareInch => Definition::new_value_terms(1f64, "[lbf_av]/[in_i]2"), Self::Circle => Definition::new_value_terms(2f64, "[pi].rad"), Self::Spere => Definition::new_value_terms(4f64, "[pi].sr"), Self::MetricCarat => METRIC_CARAT, @@ -1025,10 +1025,10 @@ impl Atom { Self::FocusFormingUnits => Property::AmountOfAnInfectiousAgent, Self::ColonyFormingUnits => Property::AmountOfAProliferatingOrganism, Self::IndexOfReactivity => { - Property::AmountOfAnAllergenCallibratedThroughInVivoTestingUsingTheStallergenesMethod + Property::AmountOfAnAllergenCalibratedThroughInVivoTestingUsingTheStallergenesMethod } Self::BioequivalentAllergenUnit => { - Property::AmountOfAnAllergenCallibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters + Property::AmountOfAnAllergenCalibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters } Self::AllergenUnit => { Property::ProcedureDefinedAmountOfAnAllergenUsingSomeReferenceStandard @@ -1064,7 +1064,7 @@ impl Atom { Self::Barn => Property::ActionArea, Self::TechnicalAtmosphere => Property::Pressure, Self::Mho => Property::ElectricConductance, - Self::PoundPerSqareInch => Property::Pressure, + Self::PoundPerSquareInch => Property::Pressure, Self::Circle => Property::PlaneAngle, Self::Spere => Property::SolidAngle, Self::MetricCarat => Property::Mass, @@ -1384,7 +1384,7 @@ impl UcumSymbol for Atom { Self::Barn => Classification::Misc, Self::TechnicalAtmosphere => Classification::Misc, Self::Mho => Classification::Misc, - Self::PoundPerSqareInch => Classification::Misc, + Self::PoundPerSquareInch => Classification::Misc, Self::Circle => Classification::Misc, Self::Spere => Classification::Misc, Self::MetricCarat => Classification::Misc, @@ -1744,7 +1744,7 @@ impl UcumSymbol for Atom { Self::Barn => vec!["barn"], Self::TechnicalAtmosphere => vec!["technical atmosphere"], Self::Mho => vec!["mho"], - Self::PoundPerSqareInch => vec!["pound per sqare inch"], + Self::PoundPerSquareInch => vec!["pound per square inch"], Self::Circle => vec!["circle"], Self::Spere => vec!["spere"], Self::MetricCarat => vec!["metric carat"], @@ -2060,7 +2060,7 @@ impl UcumSymbol for Atom { Self::Barn => "b", Self::TechnicalAtmosphere => "att", Self::Mho => "mho", - Self::PoundPerSqareInch => "[psi]", + Self::PoundPerSquareInch => "[psi]", Self::Circle => "circ", Self::Spere => "sph", Self::MetricCarat => "[car_m]", @@ -2267,7 +2267,7 @@ impl UcumSymbol for Atom { Self::Barn => Some("b"), Self::TechnicalAtmosphere => Some("at"), Self::Mho => Some("mho"), - Self::PoundPerSqareInch => Some("psi"), + Self::PoundPerSquareInch => Some("psi"), Self::Circle => Some("circ"), Self::Spere => Some("sph"), Self::MetricCarat => Some("ctm"), @@ -2580,7 +2580,7 @@ impl UcumSymbol for Atom { Self::Barn => Some("BRN"), Self::TechnicalAtmosphere => Some("ATT"), Self::Mho => Some("MHO"), - Self::PoundPerSqareInch => Some("[PSI]"), + Self::PoundPerSquareInch => Some("[PSI]"), Self::Circle => Some("CIRC"), Self::Spere => Some("SPH"), Self::MetricCarat => Some("[CAR_M]"), diff --git a/crates/api/src/property.rs b/crates/api/src/property.rs index a0dc205a..ac1b57db 100644 --- a/crates/api/src/property.rs +++ b/crates/api/src/property.rs @@ -16,8 +16,8 @@ pub enum Property { Action, ActionArea, AmountOfAProliferatingOrganism, - AmountOfAnAllergenCallibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters, - AmountOfAnAllergenCallibratedThroughInVivoTestingUsingTheStallergenesMethod, + AmountOfAnAllergenCalibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters, + AmountOfAnAllergenCalibratedThroughInVivoTestingUsingTheStallergenesMethod, AmountOfAnInfectiousAgent, AmountOfFibrinogenBrokenDownIntoTheMeasuredDDimers, AmountOfInformation, @@ -131,10 +131,10 @@ impl Property { Self::Action => vec![Atom::PlanckConstant,], Self::ActionArea => vec![Atom::Barn,], Self::AmountOfAProliferatingOrganism => vec![Atom::ColonyFormingUnits,], - Self::AmountOfAnAllergenCallibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters => { + Self::AmountOfAnAllergenCalibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters => { vec![Atom::BioequivalentAllergenUnit,] } - Self::AmountOfAnAllergenCallibratedThroughInVivoTestingUsingTheStallergenesMethod => { + Self::AmountOfAnAllergenCalibratedThroughInVivoTestingUsingTheStallergenesMethod => { vec![Atom::IndexOfReactivity,] } Self::AmountOfAnInfectiousAgent => { @@ -345,7 +345,7 @@ impl Property { vec![ Atom::Bar, Atom::InchOfMercuryColumn, Atom::InchOfWaterColumn, Atom::MeterOfMercuryColumn, Atom::MeterOfWaterColumn, Atom::Pascal, - Atom::PoundPerSqareInch, Atom::StandardAtmosphere, + Atom::PoundPerSquareInch, Atom::StandardAtmosphere, Atom::TechnicalAtmosphere, ] } @@ -426,11 +426,11 @@ impl fmt::Display for Property { Self::Action => "Action", Self::ActionArea => "ActionArea", Self::AmountOfAProliferatingOrganism => "AmountOfAProliferatingOrganism", - Self::AmountOfAnAllergenCallibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters => { - "AmountOfAnAllergenCallibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters" + Self::AmountOfAnAllergenCalibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters => { + "AmountOfAnAllergenCalibratedThroughInVivoTestingBasedOnTheId50ealMethodOfIntradermalDilutionFor50mmSumOfErythemaDiameters" } - Self::AmountOfAnAllergenCallibratedThroughInVivoTestingUsingTheStallergenesMethod => { - "AmountOfAnAllergenCallibratedThroughInVivoTestingUsingTheStallergenesMethod" + Self::AmountOfAnAllergenCalibratedThroughInVivoTestingUsingTheStallergenesMethod => { + "AmountOfAnAllergenCalibratedThroughInVivoTestingUsingTheStallergenesMethod" } Self::AmountOfAnInfectiousAgent => "AmountOfAnInfectiousAgent", Self::AmountOfFibrinogenBrokenDownIntoTheMeasuredDDimers => { diff --git a/crates/api/src/unit/parser.rs b/crates/api/src/unit/parser.rs index 8766e0b3..d0de9398 100644 --- a/crates/api/src/unit/parser.rs +++ b/crates/api/src/unit/parser.rs @@ -513,8 +513,8 @@ impl Visit for Atom { SymbolRule::pri_pound_force_avoirdupois | SymbolRule::sec_pound_force_avoirdupois => { Self::PoundForceAvoirdupois } - SymbolRule::pri_pound_per_sqare_inch | SymbolRule::sec_pound_per_sqare_inch => { - Self::PoundPerSqareInch + SymbolRule::pri_pound_per_square_inch | SymbolRule::sec_pound_per_square_inch => { + Self::PoundPerSquareInch } SymbolRule::pri_pound_troy | SymbolRule::sec_pound_troy => Self::PoundTroy, SymbolRule::pri_printers_pica | SymbolRule::sec_printers_pica => Self::PrintersPica, diff --git a/crates/api/src/unit/parser/symbols/symbol.pest b/crates/api/src/unit/parser/symbols/symbol.pest index d8549108..6f701214 100644 --- a/crates/api/src/unit/parser/symbols/symbol.pest +++ b/crates/api/src/unit/parser/symbols/symbol.pest @@ -257,7 +257,7 @@ pri_atom = { | pri_point | pri_parts_per_billion | pri_parts_per_million - | pri_pound_per_sqare_inch + | pri_pound_per_square_inch | pri_section | pri_township | pri_bit_logarithmus_dualis @@ -569,7 +569,7 @@ pri_pica = { "[pca]" } pri_point = { "[pnt]" } pri_parts_per_billion = { "[ppb]" } pri_parts_per_million = { "[ppm]" } -pri_pound_per_sqare_inch = { "[psi]" } +pri_pound_per_square_inch = { "[psi]" } pri_section = { "[sct]" } pri_township = { "[twp]" } pri_bit_logarithmus_dualis = { "bit_s" } @@ -945,7 +945,7 @@ sec_atom = { | sec_parts_per_billion | sec_parts_per_million | sec_peripheral_vascular_resistance_unit - | sec_pound_per_sqare_inch + | sec_pound_per_square_inch | sec_radiation_absorbed_dose | sec_radiation_equivalent_man | sec_section @@ -1256,7 +1256,7 @@ sec_protein_nitrogen_unit = { "[PNU]" } sec_parts_per_billion = { "[PPB]" } sec_parts_per_million = { "[PPM]" } sec_peripheral_vascular_resistance_unit = { "[PRU]" } -sec_pound_per_sqare_inch = { "[PSI]" } +sec_pound_per_square_inch = { "[PSI]" } sec_radiation_absorbed_dose = { "[RAD]" } sec_radiation_equivalent_man = { "[REM]" } sec_section = { "[SCT]" } diff --git a/crates/atom_generator/Atoms.toml b/crates/atom_generator/Atoms.toml index e278bb68..a846f027 100644 --- a/crates/atom_generator/Atoms.toml +++ b/crates/atom_generator/Atoms.toml @@ -207,10 +207,10 @@ names = ['the number ten for arbitrary powers'] printSymbol = '10' property = 'number' - [unit.value] - Unit = '1' - UNIT = '1' - value = 10 +[unit.value] +Unit = '1' +UNIT = '1' +value = 10 [[unit]] Code = '10^' @@ -221,10 +221,10 @@ names = ['the number ten for arbitrary powers'] printSymbol = '10' property = 'number' - [unit.value] - Unit = '1' - UNIT = '1' - value = 10 +[unit.value] +Unit = '1' +UNIT = '1' +value = 10 [[unit]] Code = '[pi]' @@ -235,10 +235,10 @@ names = ['the number pi'] printSymbol = 'π' property = 'number' - [unit.value] - Unit = '1' - UNIT = '1' - value = 3.1415926535897932384626433832795028841971693993751058209749445923 +[unit.value] +Unit = '1' +UNIT = '1' +value = 3.1415926535897932384626433832795028841971693993751058209749445923 [[unit]] Code = '%' @@ -249,10 +249,10 @@ names = ['percent'] printSymbol = '%' property = 'fraction' - [unit.value] - Unit = '10*-2' - UNIT = '10*-2' - value = 1 +[unit.value] +Unit = '10*-2' +UNIT = '10*-2' +value = 1 [[unit]] Code = '[ppth]' @@ -263,10 +263,10 @@ names = ['parts per thousand'] printSymbol = 'ppth' property = 'fraction' - [unit.value] - Unit = '10*-3' - UNIT = '10*-3' - value = 1 +[unit.value] +Unit = '10*-3' +UNIT = '10*-3' +value = 1 [[unit]] Code = '[ppm]' @@ -277,10 +277,10 @@ names = ['parts per million'] printSymbol = 'ppm' property = 'fraction' - [unit.value] - Unit = '10*-6' - UNIT = '10*-6' - value = 1 +[unit.value] +Unit = '10*-6' +UNIT = '10*-6' +value = 1 [[unit]] Code = '[ppb]' @@ -291,10 +291,10 @@ names = ['parts per billion'] printSymbol = 'ppb' property = 'fraction' - [unit.value] - Unit = '10*-9' - UNIT = '10*-9' - value = 1 +[unit.value] +Unit = '10*-9' +UNIT = '10*-9' +value = 1 [[unit]] Code = '[pptr]' @@ -305,10 +305,10 @@ names = ['parts per trillion'] printSymbol = 'pptr' property = 'fraction' - [unit.value] - Unit = '10*-12' - UNIT = '10*-12' - value = 1 +[unit.value] +Unit = '10*-12' +UNIT = '10*-12' +value = 1 [[unit]] Code = 'mol' @@ -319,10 +319,10 @@ names = ['mole'] printSymbol = 'mol' property = 'amount of substance' - [unit.value] - Unit = '10*23' - UNIT = '10*23' - value = 6.0221367 +[unit.value] +Unit = '10*23' +UNIT = '10*23' +value = 6.0221367 [[unit]] Code = 'sr' @@ -333,10 +333,10 @@ names = ['steradian'] printSymbol = 'sr' property = 'solid angle' - [unit.value] - Unit = 'rad2' - UNIT = 'RAD2' - value = 1 +[unit.value] +Unit = 'rad2' +UNIT = 'RAD2' +value = 1 [[unit]] Code = 'Hz' @@ -347,10 +347,10 @@ names = ['hertz'] printSymbol = 'Hz' property = 'frequency' - [unit.value] - Unit = 's-1' - UNIT = 'S-1' - value = 1 +[unit.value] +Unit = 's-1' +UNIT = 'S-1' +value = 1 [[unit]] Code = 'N' @@ -361,10 +361,10 @@ names = ['newton'] printSymbol = 'N' property = 'force' - [unit.value] - Unit = 'kg.m/s2' - UNIT = 'KG.M/S2' - value = 1 +[unit.value] +Unit = 'kg.m/s2' +UNIT = 'KG.M/S2' +value = 1 [[unit]] Code = 'Pa' @@ -375,10 +375,10 @@ names = ['pascal'] printSymbol = 'Pa' property = 'pressure' - [unit.value] - Unit = 'N/m2' - UNIT = 'N/M2' - value = 1 +[unit.value] +Unit = 'N/m2' +UNIT = 'N/M2' +value = 1 [[unit]] Code = 'J' @@ -389,10 +389,10 @@ names = ['joule'] printSymbol = 'J' property = 'energy' - [unit.value] - Unit = 'N.m' - UNIT = 'N.M' - value = 1 +[unit.value] +Unit = 'N.m' +UNIT = 'N.M' +value = 1 [[unit]] Code = 'W' @@ -403,10 +403,10 @@ names = ['watt'] printSymbol = 'W' property = 'power' - [unit.value] - Unit = 'J/s' - UNIT = 'J/S' - value = 1 +[unit.value] +Unit = 'J/s' +UNIT = 'J/S' +value = 1 [[unit]] Code = 'A' @@ -417,10 +417,10 @@ names = ['ampère'] printSymbol = 'A' property = 'electric current' - [unit.value] - Unit = 'C/s' - UNIT = 'C/S' - value = 1 +[unit.value] +Unit = 'C/s' +UNIT = 'C/S' +value = 1 [[unit]] Code = 'V' @@ -431,10 +431,10 @@ names = ['volt'] printSymbol = 'V' property = 'electric potential' - [unit.value] - Unit = 'J/C' - UNIT = 'J/C' - value = 1 +[unit.value] +Unit = 'J/C' +UNIT = 'J/C' +value = 1 [[unit]] Code = 'F' @@ -445,10 +445,10 @@ names = ['farad'] printSymbol = 'F' property = 'electric capacitance' - [unit.value] - Unit = 'C/V' - UNIT = 'C/V' - value = 1 +[unit.value] +Unit = 'C/V' +UNIT = 'C/V' +value = 1 [[unit]] Code = 'Ohm' @@ -459,10 +459,10 @@ names = ['ohm'] printSymbol = 'Ω' property = 'electric resistance' - [unit.value] - Unit = 'V/A' - UNIT = 'V/A' - value = 1 +[unit.value] +Unit = 'V/A' +UNIT = 'V/A' +value = 1 [[unit]] Code = 'S' @@ -473,10 +473,10 @@ names = ['siemens'] printSymbol = 'S' property = 'electric conductance' - [unit.value] - Unit = 'Ohm-1' - UNIT = 'OHM-1' - value = 1 +[unit.value] +Unit = 'Ohm-1' +UNIT = 'OHM-1' +value = 1 [[unit]] Code = 'Wb' @@ -487,10 +487,10 @@ names = ['weber'] printSymbol = 'Wb' property = 'magnetic flux' - [unit.value] - Unit = 'V.s' - UNIT = 'V.S' - value = 1 +[unit.value] +Unit = 'V.s' +UNIT = 'V.S' +value = 1 [[unit]] Code = 'Cel' @@ -502,14 +502,14 @@ names = ['degree Celsius'] printSymbol = '°C' property = 'temperature' - [unit.value] - Unit = 'cel(1 K)' - UNIT = 'CEL(1 K)' +[unit.value] +Unit = 'cel(1 K)' +UNIT = 'CEL(1 K)' - [unit.value.function] - name = 'Cel' - value = 1 - Unit = 'K' +[unit.value.function] +name = 'Cel' +value = 1 +Unit = 'K' [[unit]] Code = 'T' @@ -520,10 +520,10 @@ names = ['tesla'] printSymbol = 'T' property = 'magnetic flux density' - [unit.value] - Unit = 'Wb/m2' - UNIT = 'WB/M2' - value = 1 +[unit.value] +Unit = 'Wb/m2' +UNIT = 'WB/M2' +value = 1 [[unit]] Code = 'H' @@ -534,10 +534,10 @@ names = ['henry'] printSymbol = 'H' property = 'inductance' - [unit.value] - Unit = 'Wb/A' - UNIT = 'WB/A' - value = 1 +[unit.value] +Unit = 'Wb/A' +UNIT = 'WB/A' +value = 1 [[unit]] Code = 'lm' @@ -548,10 +548,10 @@ names = ['lumen'] printSymbol = 'lm' property = 'luminous flux' - [unit.value] - Unit = 'cd.sr' - UNIT = 'CD.SR' - value = 1 +[unit.value] +Unit = 'cd.sr' +UNIT = 'CD.SR' +value = 1 [[unit]] Code = 'lx' @@ -562,10 +562,10 @@ names = ['lux'] printSymbol = 'lx' property = 'illuminance' - [unit.value] - Unit = 'lm/m2' - UNIT = 'LM/M2' - value = 1 +[unit.value] +Unit = 'lm/m2' +UNIT = 'LM/M2' +value = 1 [[unit]] Code = 'Bq' @@ -576,10 +576,10 @@ names = ['becquerel'] printSymbol = 'Bq' property = 'radioactivity' - [unit.value] - Unit = 's-1' - UNIT = 'S-1' - value = 1 +[unit.value] +Unit = 's-1' +UNIT = 'S-1' +value = 1 [[unit]] Code = 'Gy' @@ -590,10 +590,10 @@ names = ['gray'] printSymbol = 'Gy' property = 'energy dose' - [unit.value] - Unit = 'J/kg' - UNIT = 'J/KG' - value = 1 +[unit.value] +Unit = 'J/kg' +UNIT = 'J/KG' +value = 1 [[unit]] Code = 'Sv' @@ -604,10 +604,10 @@ names = ['sievert'] printSymbol = 'Sv' property = 'dose equivalent' - [unit.value] - Unit = 'J/kg' - UNIT = 'J/KG' - value = 1 +[unit.value] +Unit = 'J/kg' +UNIT = 'J/KG' +value = 1 [[unit]] Code = 'gon' @@ -618,10 +618,10 @@ names = ['gon', 'grade'] printSymbol = '□g' property = 'plane angle' - [unit.value] - Unit = 'deg' - UNIT = 'DEG' - value = 0.9 +[unit.value] +Unit = 'deg' +UNIT = 'DEG' +value = 0.9 [[unit]] Code = 'deg' @@ -632,10 +632,10 @@ names = ['degree'] printSymbol = '°' property = 'plane angle' - [unit.value] - Unit = '[pi].rad/360' - UNIT = '[PI].RAD/360' - value = 2 +[unit.value] +Unit = '[pi].rad/360' +UNIT = '[PI].RAD/360' +value = 2 [[unit]] Code = "'" @@ -646,10 +646,10 @@ names = ['minute'] printSymbol = "'" property = 'plane angle' - [unit.value] - Unit = 'deg/60' - UNIT = 'DEG/60' - value = 1 +[unit.value] +Unit = 'deg/60' +UNIT = 'DEG/60' +value = 1 [[unit]] Code = "''" @@ -660,10 +660,10 @@ names = ['second'] printSymbol = "''" property = 'plane angle' - [unit.value] - Unit = "'/60" - UNIT = "'/60" - value = 1 +[unit.value] +Unit = "'/60" +UNIT = "'/60" +value = 1 [[unit]] Code = 'l' @@ -674,10 +674,10 @@ names = ['liter'] printSymbol = 'l' property = 'volume' - [unit.value] - Unit = 'dm3' - UNIT = 'DM3' - value = 1 +[unit.value] +Unit = 'dm3' +UNIT = 'DM3' +value = 1 [[unit]] Code = 'L' @@ -687,9 +687,9 @@ names = ['liter'] printSymbol = 'L' property = 'volume' - [unit.value] - Unit = 'l' - value = 1 +[unit.value] +Unit = 'l' +value = 1 [[unit]] Code = 'ar' @@ -700,10 +700,10 @@ names = ['are'] printSymbol = 'a' property = 'area' - [unit.value] - Unit = 'm2' - UNIT = 'M2' - value = 100 +[unit.value] +Unit = 'm2' +UNIT = 'M2' +value = 100 [[unit]] Code = 'min' @@ -714,10 +714,10 @@ names = ['minute'] printSymbol = 'min' property = 'time' - [unit.value] - Unit = 's' - UNIT = 'S' - value = 60 +[unit.value] +Unit = 's' +UNIT = 'S' +value = 60 [[unit]] Code = 'h' @@ -728,10 +728,10 @@ names = ['hour'] printSymbol = 'h' property = 'time' - [unit.value] - Unit = 'min' - UNIT = 'MIN' - value = 60 +[unit.value] +Unit = 'min' +UNIT = 'MIN' +value = 60 [[unit]] Code = 'd' @@ -742,10 +742,10 @@ names = ['day'] printSymbol = 'd' property = 'time' - [unit.value] - Unit = 'h' - UNIT = 'HR' - value = 24 +[unit.value] +Unit = 'h' +UNIT = 'HR' +value = 24 [[unit]] Code = 'a_t' @@ -756,10 +756,10 @@ names = ['tropical year'] printSymbol = 'at' property = 'time' - [unit.value] - Unit = 'd' - UNIT = 'D' - value = 365.24219 +[unit.value] +Unit = 'd' +UNIT = 'D' +value = 365.24219 [[unit]] Code = 'a_j' @@ -770,10 +770,10 @@ names = ['mean Julian year'] printSymbol = 'aj' property = 'time' - [unit.value] - Unit = 'd' - UNIT = 'D' - value = 365.25 +[unit.value] +Unit = 'd' +UNIT = 'D' +value = 365.25 [[unit]] Code = 'a_g' @@ -784,10 +784,10 @@ names = ['mean Gregorian year'] printSymbol = 'ag' property = 'time' - [unit.value] - Unit = 'd' - UNIT = 'D' - value = 365.2425 +[unit.value] +Unit = 'd' +UNIT = 'D' +value = 365.2425 [[unit]] Code = 'a' @@ -798,10 +798,10 @@ names = ['year'] printSymbol = 'a' property = 'time' - [unit.value] - Unit = 'a_j' - UNIT = 'ANN_J' - value = 1 +[unit.value] +Unit = 'a_j' +UNIT = 'ANN_J' +value = 1 [[unit]] Code = 'wk' @@ -812,10 +812,10 @@ names = ['week'] printSymbol = 'wk' property = 'time' - [unit.value] - Unit = 'd' - UNIT = 'D' - value = 7 +[unit.value] +Unit = 'd' +UNIT = 'D' +value = 7 [[unit]] Code = 'mo_s' @@ -826,10 +826,10 @@ names = ['synodal month'] printSymbol = 'mos' property = 'time' - [unit.value] - Unit = 'd' - UNIT = 'D' - value = 29.53059 +[unit.value] +Unit = 'd' +UNIT = 'D' +value = 29.53059 [[unit]] Code = 'mo_j' @@ -840,10 +840,10 @@ names = ['mean Julian month'] printSymbol = 'moj' property = 'time' - [unit.value] - Unit = 'a_j/12' - UNIT = 'ANN_J/12' - value = 1 +[unit.value] +Unit = 'a_j/12' +UNIT = 'ANN_J/12' +value = 1 [[unit]] Code = 'mo_g' @@ -854,10 +854,10 @@ names = ['mean Gregorian month'] printSymbol = 'mog' property = 'time' - [unit.value] - Unit = 'a_g/12' - UNIT = 'ANN_G/12' - value = 1 +[unit.value] +Unit = 'a_g/12' +UNIT = 'ANN_G/12' +value = 1 [[unit]] Code = 'mo' @@ -868,10 +868,10 @@ names = ['month'] printSymbol = 'mo' property = 'time' - [unit.value] - Unit = 'mo_j' - UNIT = 'MO_J' - value = 1 +[unit.value] +Unit = 'mo_j' +UNIT = 'MO_J' +value = 1 [[unit]] Code = 't' @@ -882,10 +882,10 @@ names = ['tonne'] printSymbol = 't' property = 'mass' - [unit.value] - Unit = 'kg' - UNIT = 'KG' - value = 1e3 +[unit.value] +Unit = 'kg' +UNIT = 'KG' +value = 1e3 [[unit]] Code = 'bar' @@ -896,10 +896,10 @@ names = ['bar'] printSymbol = 'bar' property = 'pressure' - [unit.value] - Unit = 'Pa' - UNIT = 'PAL' - value = 1e5 +[unit.value] +Unit = 'Pa' +UNIT = 'PAL' +value = 1e5 [[unit]] Code = 'u' @@ -910,10 +910,10 @@ names = ['unified atomic mass unit'] printSymbol = 'u' property = 'mass' - [unit.value] - Unit = 'g' - UNIT = 'G' - value = 1.6605402e-24 +[unit.value] +Unit = 'g' +UNIT = 'G' +value = 1.6605402e-24 [[unit]] Code = 'eV' @@ -924,10 +924,10 @@ names = ['electronvolt'] printSymbol = 'eV' property = 'energy' - [unit.value] - Unit = '[e].V' - UNIT = '[E].V' - value = 1 +[unit.value] +Unit = '[e].V' +UNIT = '[E].V' +value = 1 [[unit]] Code = 'AU' @@ -938,10 +938,10 @@ names = ['astronomic unit'] printSymbol = 'AU' property = 'length' - [unit.value] - Unit = 'Mm' - UNIT = 'MAM' - value = 149597.870691 +[unit.value] +Unit = 'Mm' +UNIT = 'MAM' +value = 149597.870691 [[unit]] Code = 'pc' @@ -952,10 +952,10 @@ names = ['parsec'] printSymbol = 'pc' property = 'length' - [unit.value] - Unit = 'm' - UNIT = 'M' - value = 3.085678e16 +[unit.value] +Unit = 'm' +UNIT = 'M' +value = 3.085678e16 [[unit]] Code = '[c]' @@ -966,10 +966,10 @@ names = ['velocity of light'] printSymbol = 'c' property = 'velocity' - [unit.value] - Unit = 'm/s' - UNIT = 'M/S' - value = 299792458 +[unit.value] +Unit = 'm/s' +UNIT = 'M/S' +value = 299792458 [[unit]] Code = '[h]' @@ -980,10 +980,10 @@ names = ['Planck constant'] printSymbol = 'h' property = 'action' - [unit.value] - Unit = 'J.s' - UNIT = 'J.S' - value = 6.6260755e-34 +[unit.value] +Unit = 'J.s' +UNIT = 'J.S' +value = 6.6260755e-34 [[unit]] Code = '[k]' @@ -994,10 +994,10 @@ names = ['Boltzmann constant'] printSymbol = 'k' property = '(unclassified)' - [unit.value] - Unit = 'J/K' - UNIT = 'J/K' - value = 1.380658e-23 +[unit.value] +Unit = 'J/K' +UNIT = 'J/K' +value = 1.380658e-23 [[unit]] Code = '[eps_0]' @@ -1008,10 +1008,10 @@ names = ['permittivity of vacuum'] printSymbol = 'ε0' property = 'electric permittivity' - [unit.value] - Unit = 'F/m' - UNIT = 'F/M' - value = 8.854187817e-12 +[unit.value] +Unit = 'F/m' +UNIT = 'F/M' +value = 8.854187817e-12 [[unit]] Code = '[mu_0]' @@ -1022,10 +1022,10 @@ names = ['permeability of vacuum'] printSymbol = 'μ0' property = 'magnetic permeability' - [unit.value] - Unit = '4.[pi].10*-7.N/A2' - UNIT = '4.[PI].10*-7.N/A2' - value = 1 +[unit.value] +Unit = '4.[pi].10*-7.N/A2' +UNIT = '4.[PI].10*-7.N/A2' +value = 1 [[unit]] Code = '[e]' @@ -1036,10 +1036,10 @@ names = ['elementary charge'] printSymbol = 'e' property = 'electric charge' - [unit.value] - Unit = 'C' - UNIT = 'C' - value = 1.60217733e-19 +[unit.value] +Unit = 'C' +UNIT = 'C' +value = 1.60217733e-19 [[unit]] Code = '[m_e]' @@ -1050,10 +1050,10 @@ names = ['electron mass'] printSymbol = 'me' property = 'mass' - [unit.value] - Unit = 'g' - UNIT = 'g' - value = 9.1093897e-28 +[unit.value] +Unit = 'g' +UNIT = 'g' +value = 9.1093897e-28 [[unit]] Code = '[m_p]' @@ -1064,10 +1064,10 @@ names = ['proton mass'] printSymbol = 'mp' property = 'mass' - [unit.value] - Unit = 'g' - UNIT = 'g' - value = 1.6726231e-24 +[unit.value] +Unit = 'g' +UNIT = 'g' +value = 1.6726231e-24 [[unit]] Code = '[G]' @@ -1078,10 +1078,10 @@ names = ['Newtonian constant of gravitation'] printSymbol = 'G' property = '(unclassified)' - [unit.value] - Unit = 'm3.kg-1.s-2' - UNIT = 'M3.KG-1.S-2' - value = 6.67259e-11 +[unit.value] +Unit = 'm3.kg-1.s-2' +UNIT = 'M3.KG-1.S-2' +value = 6.67259e-11 [[unit]] Code = '[g]' @@ -1092,10 +1092,10 @@ names = ['standard acceleration of free fall'] printSymbol = 'gn' property = 'acceleration' - [unit.value] - Unit = 'm/s2' - UNIT = 'M/S2' - value = 980665e-5 +[unit.value] +Unit = 'm/s2' +UNIT = 'M/S2' +value = 980665e-5 [[unit]] Code = 'atm' @@ -1106,10 +1106,10 @@ names = ['standard atmosphere'] printSymbol = 'atm' property = 'pressure' - [unit.value] - Unit = 'Pa' - UNIT = 'PAL' - value = 101325 +[unit.value] +Unit = 'Pa' +UNIT = 'PAL' +value = 101325 [[unit]] Code = '[ly]' @@ -1120,10 +1120,10 @@ names = ['light-year'] printSymbol = 'l.y.' property = 'length' - [unit.value] - Unit = '[c].a_j' - UNIT = '[C].ANN_J' - value = 1 +[unit.value] +Unit = '[c].a_j' +UNIT = '[C].ANN_J' +value = 1 [[unit]] Code = 'gf' @@ -1134,10 +1134,10 @@ names = ['gram-force'] printSymbol = 'gf' property = 'force' - [unit.value] - Unit = 'g.[g]' - UNIT = 'G.[G]' - value = 1 +[unit.value] +Unit = 'g.[g]' +UNIT = 'G.[G]' +value = 1 [[unit]] Code = '[lbf_av]' @@ -1148,10 +1148,10 @@ names = ['pound force'] printSymbol = 'lbf' property = 'force' - [unit.value] - Unit = '[lb_av].[g]' - UNIT = '[LB_AV].[G]' - value = 1 +[unit.value] +Unit = '[lb_av].[g]' +UNIT = '[LB_AV].[G]' +value = 1 [[unit]] Code = 'Ky' @@ -1162,10 +1162,10 @@ names = ['Kayser'] printSymbol = 'K' property = 'lineic number' - [unit.value] - Unit = 'cm-1' - UNIT = 'CM-1' - value = 1 +[unit.value] +Unit = 'cm-1' +UNIT = 'CM-1' +value = 1 [[unit]] Code = 'Gal' @@ -1176,10 +1176,10 @@ names = ['Gal'] printSymbol = 'Gal' property = 'acceleration' - [unit.value] - Unit = 'cm/s2' - UNIT = 'CM/S2' - value = 1 +[unit.value] +Unit = 'cm/s2' +UNIT = 'CM/S2' +value = 1 [[unit]] Code = 'dyn' @@ -1190,10 +1190,10 @@ names = ['dyne'] printSymbol = 'dyn' property = 'force' - [unit.value] - Unit = 'g.cm/s2' - UNIT = 'G.CM/S2' - value = 1 +[unit.value] +Unit = 'g.cm/s2' +UNIT = 'G.CM/S2' +value = 1 [[unit]] Code = 'erg' @@ -1204,10 +1204,10 @@ names = ['erg'] printSymbol = 'erg' property = 'energy' - [unit.value] - Unit = 'dyn.cm' - UNIT = 'DYN.CM' - value = 1 +[unit.value] +Unit = 'dyn.cm' +UNIT = 'DYN.CM' +value = 1 [[unit]] Code = 'P' @@ -1218,10 +1218,10 @@ names = ['Poise'] printSymbol = 'P' property = 'dynamic viscosity' - [unit.value] - Unit = 'dyn.s/cm2' - UNIT = 'DYN.S/CM2' - value = 1 +[unit.value] +Unit = 'dyn.s/cm2' +UNIT = 'DYN.S/CM2' +value = 1 [[unit]] Code = 'Bi' @@ -1232,10 +1232,10 @@ names = ['Biot'] printSymbol = 'Bi' property = 'electric current' - [unit.value] - Unit = 'A' - UNIT = 'A' - value = 10 +[unit.value] +Unit = 'A' +UNIT = 'A' +value = 10 [[unit]] Code = 'St' @@ -1246,10 +1246,10 @@ names = ['Stokes'] printSymbol = 'St' property = 'kinematic viscosity' - [unit.value] - Unit = 'cm2/s' - UNIT = 'CM2/S' - value = 1 +[unit.value] +Unit = 'cm2/s' +UNIT = 'CM2/S' +value = 1 [[unit]] Code = 'Mx' @@ -1260,10 +1260,10 @@ names = ['Maxwell'] printSymbol = 'Mx' property = 'flux of magnetic induction' - [unit.value] - Unit = 'Wb' - UNIT = 'WB' - value = 1e-8 +[unit.value] +Unit = 'Wb' +UNIT = 'WB' +value = 1e-8 [[unit]] Code = 'G' @@ -1274,10 +1274,10 @@ names = ['Gauss'] printSymbol = 'Gs' property = 'magnetic flux density' - [unit.value] - Unit = 'T' - UNIT = 'T' - value = 1e-4 +[unit.value] +Unit = 'T' +UNIT = 'T' +value = 1e-4 [[unit]] Code = 'Oe' @@ -1288,10 +1288,10 @@ names = ['Oersted'] printSymbol = 'Oe' property = 'magnetic field intensity' - [unit.value] - Unit = '/[pi].A/m' - UNIT = '/[PI].A/M' - value = 250 +[unit.value] +Unit = '/[pi].A/m' +UNIT = '/[PI].A/M' +value = 250 [[unit]] Code = 'Gb' @@ -1302,10 +1302,10 @@ names = ['Gilbert'] printSymbol = 'Gb' property = 'magnetic tension' - [unit.value] - Unit = 'Oe.cm' - UNIT = 'OE.CM' - value = 1 +[unit.value] +Unit = 'Oe.cm' +UNIT = 'OE.CM' +value = 1 [[unit]] Code = 'sb' @@ -1316,10 +1316,10 @@ names = ['stilb'] printSymbol = 'sb' property = 'lum. intensity density' - [unit.value] - Unit = 'cd/cm2' - UNIT = 'CD/CM2' - value = 1 +[unit.value] +Unit = 'cd/cm2' +UNIT = 'CD/CM2' +value = 1 [[unit]] Code = 'Lmb' @@ -1330,10 +1330,10 @@ names = ['Lambert'] printSymbol = 'L' property = 'brightness' - [unit.value] - Unit = 'cd/cm2/[pi]' - UNIT = 'CD/CM2/[PI]' - value = 1 +[unit.value] +Unit = 'cd/cm2/[pi]' +UNIT = 'CD/CM2/[PI]' +value = 1 [[unit]] Code = 'ph' @@ -1344,10 +1344,10 @@ names = ['phot'] printSymbol = 'ph' property = 'illuminance' - [unit.value] - Unit = 'lx' - UNIT = 'LX' - value = 1e-4 +[unit.value] +Unit = 'lx' +UNIT = 'LX' +value = 1e-4 [[unit]] Code = 'Ci' @@ -1358,10 +1358,10 @@ names = ['Curie'] printSymbol = 'Ci' property = 'radioactivity' - [unit.value] - Unit = 'Bq' - UNIT = 'BQ' - value = 37e9 +[unit.value] +Unit = 'Bq' +UNIT = 'BQ' +value = 37e9 [[unit]] Code = 'R' @@ -1372,10 +1372,10 @@ names = ['Roentgen'] printSymbol = 'R' property = 'ion dose' - [unit.value] - Unit = 'C/kg' - UNIT = 'C/KG' - value = 2.58e-4 +[unit.value] +Unit = 'C/kg' +UNIT = 'C/KG' +value = 2.58e-4 [[unit]] Code = 'RAD' @@ -1386,10 +1386,10 @@ names = ['radiation absorbed dose'] printSymbol = 'RAD' property = 'energy dose' - [unit.value] - Unit = 'erg/g' - UNIT = 'ERG/G' - value = 100 +[unit.value] +Unit = 'erg/g' +UNIT = 'ERG/G' +value = 100 [[unit]] Code = 'REM' @@ -1400,10 +1400,10 @@ names = ['radiation equivalent man'] printSymbol = 'REM' property = 'dose equivalent' - [unit.value] - Unit = 'RAD' - UNIT = '[RAD]' - value = 1 +[unit.value] +Unit = 'RAD' +UNIT = '[RAD]' +value = 1 [[unit]] Code = '[in_i]' @@ -1414,10 +1414,10 @@ names = ['inch'] printSymbol = 'in' property = 'length' - [unit.value] - Unit = 'cm' - UNIT = 'CM' - value = 254e-2 +[unit.value] +Unit = 'cm' +UNIT = 'CM' +value = 254e-2 [[unit]] Code = '[ft_i]' @@ -1428,10 +1428,10 @@ names = ['foot'] printSymbol = 'ft' property = 'length' - [unit.value] - Unit = '[in_i]' - UNIT = '[IN_I]' - value = 12 +[unit.value] +Unit = '[in_i]' +UNIT = '[IN_I]' +value = 12 [[unit]] Code = '[yd_i]' @@ -1442,10 +1442,10 @@ names = ['yard'] printSymbol = 'yd' property = 'length' - [unit.value] - Unit = '[ft_i]' - UNIT = '[FT_I]' - value = 3 +[unit.value] +Unit = '[ft_i]' +UNIT = '[FT_I]' +value = 3 [[unit]] Code = '[mi_i]' @@ -1456,10 +1456,10 @@ names = ['mile'] printSymbol = 'mi' property = 'length' - [unit.value] - Unit = '[ft_i]' - UNIT = '[FT_I]' - value = 5280 +[unit.value] +Unit = '[ft_i]' +UNIT = '[FT_I]' +value = 5280 [[unit]] Code = '[fth_i]' @@ -1470,10 +1470,10 @@ names = ['fathom'] printSymbol = 'fth' property = 'depth of water' - [unit.value] - Unit = '[ft_i]' - UNIT = '[FT_I]' - value = 6 +[unit.value] +Unit = '[ft_i]' +UNIT = '[FT_I]' +value = 6 [[unit]] Code = '[nmi_i]' @@ -1484,10 +1484,10 @@ names = ['nautical mile'] printSymbol = 'n.mi' property = 'length' - [unit.value] - Unit = 'm' - UNIT = 'M' - value = 1852 +[unit.value] +Unit = 'm' +UNIT = 'M' +value = 1852 [[unit]] Code = '[kn_i]' @@ -1498,10 +1498,10 @@ names = ['knot'] printSymbol = 'knot' property = 'velocity' - [unit.value] - Unit = '[nmi_i]/h' - UNIT = '[NMI_I]/H' - value = 1 +[unit.value] +Unit = '[nmi_i]/h' +UNIT = '[NMI_I]/H' +value = 1 [[unit]] Code = '[sin_i]' @@ -1511,10 +1511,10 @@ class = 'intcust' names = ['square inch'] property = 'area' - [unit.value] - Unit = '[in_i]2' - UNIT = '[IN_I]2' - value = 1 +[unit.value] +Unit = '[in_i]2' +UNIT = '[IN_I]2' +value = 1 [[unit]] Code = '[sft_i]' @@ -1524,10 +1524,10 @@ class = 'intcust' names = ['square foot'] property = 'area' - [unit.value] - Unit = '[ft_i]2' - UNIT = '[FT_I]2' - value = 1 +[unit.value] +Unit = '[ft_i]2' +UNIT = '[FT_I]2' +value = 1 [[unit]] Code = '[syd_i]' @@ -1537,10 +1537,10 @@ class = 'intcust' names = ['square yard'] property = 'area' - [unit.value] - Unit = '[yd_i]2' - UNIT = '[YD_I]2' - value = 1 +[unit.value] +Unit = '[yd_i]2' +UNIT = '[YD_I]2' +value = 1 [[unit]] Code = '[cin_i]' @@ -1550,10 +1550,10 @@ class = 'intcust' names = ['cubic inch'] property = 'volume' - [unit.value] - Unit = '[in_i]3' - UNIT = '[IN_I]3' - value = 1 +[unit.value] +Unit = '[in_i]3' +UNIT = '[IN_I]3' +value = 1 [[unit]] Code = '[cft_i]' @@ -1563,10 +1563,10 @@ class = 'intcust' names = ['cubic foot'] property = 'volume' - [unit.value] - Unit = '[ft_i]3' - UNIT = '[FT_I]3' - value = 1 +[unit.value] +Unit = '[ft_i]3' +UNIT = '[FT_I]3' +value = 1 [[unit]] Code = '[cyd_i]' @@ -1577,10 +1577,10 @@ names = ['cubic yard'] printSymbol = 'cu.yd' property = 'volume' - [unit.value] - Unit = '[yd_i]3' - UNIT = '[YD_I]3' - value = 1 +[unit.value] +Unit = '[yd_i]3' +UNIT = '[YD_I]3' +value = 1 [[unit]] Code = '[bf_i]' @@ -1590,10 +1590,10 @@ class = 'intcust' names = ['board foot'] property = 'volume' - [unit.value] - Unit = '[in_i]3' - UNIT = '[IN_I]3' - value = 144 +[unit.value] +Unit = '[in_i]3' +UNIT = '[IN_I]3' +value = 144 [[unit]] Code = '[cr_i]' @@ -1603,10 +1603,10 @@ class = 'intcust' names = ['cord'] property = 'volume' - [unit.value] - Unit = '[ft_i]3' - UNIT = '[FT_I]3' - value = 128 +[unit.value] +Unit = '[ft_i]3' +UNIT = '[FT_I]3' +value = 128 [[unit]] Code = '[mil_i]' @@ -1617,10 +1617,10 @@ names = ['mil'] printSymbol = 'mil' property = 'length' - [unit.value] - Unit = '[in_i]' - UNIT = '[IN_I]' - value = 1e-3 +[unit.value] +Unit = '[in_i]' +UNIT = '[IN_I]' +value = 1e-3 [[unit]] Code = '[cml_i]' @@ -1631,10 +1631,10 @@ names = ['circular mil'] printSymbol = 'circ.mil' property = 'area' - [unit.value] - Unit = '[pi]/4.[mil_i]2' - UNIT = '[PI]/4.[MIL_I]2' - value = 1 +[unit.value] +Unit = '[pi]/4.[mil_i]2' +UNIT = '[PI]/4.[MIL_I]2' +value = 1 [[unit]] Code = '[hd_i]' @@ -1645,10 +1645,10 @@ names = ['hand'] printSymbol = 'hd' property = 'height of horses' - [unit.value] - Unit = '[in_i]' - UNIT = '[IN_I]' - value = 4 +[unit.value] +Unit = '[in_i]' +UNIT = '[IN_I]' +value = 4 [[unit]] Code = '[ft_us]' @@ -1659,10 +1659,10 @@ names = ['foot'] printSymbol = 'ftus' property = 'length' - [unit.value] - Unit = 'm/3937' - UNIT = 'M/3937' - value = 1200 +[unit.value] +Unit = 'm/3937' +UNIT = 'M/3937' +value = 1200 [[unit]] Code = '[yd_us]' @@ -1672,10 +1672,10 @@ class = 'us-lengths' names = ['yard'] property = 'length' - [unit.value] - Unit = '[ft_us]' - UNIT = '[FT_US]' - value = 3 +[unit.value] +Unit = '[ft_us]' +UNIT = '[FT_US]' +value = 3 [[unit]] Code = '[in_us]' @@ -1685,10 +1685,10 @@ class = 'us-lengths' names = ['inch'] property = 'length' - [unit.value] - Unit = '[ft_us]/12' - UNIT = '[FT_US]/12' - value = 1 +[unit.value] +Unit = '[ft_us]/12' +UNIT = '[FT_US]/12' +value = 1 [[unit]] Code = '[rd_us]' @@ -1698,10 +1698,10 @@ class = 'us-lengths' names = ['rod'] property = 'length' - [unit.value] - Unit = '[ft_us]' - UNIT = '[FT_US]' - value = 16.5 +[unit.value] +Unit = '[ft_us]' +UNIT = '[FT_US]' +value = 16.5 [[unit]] Code = '[ch_us]' @@ -1711,10 +1711,10 @@ class = 'us-lengths' names = ["Gunter's chain", "Surveyor's chain"] property = 'length' - [unit.value] - Unit = '[rd_us]' - UNIT = '[RD_US]' - value = 4 +[unit.value] +Unit = '[rd_us]' +UNIT = '[RD_US]' +value = 4 [[unit]] Code = '[lk_us]' @@ -1724,10 +1724,10 @@ class = 'us-lengths' names = ["link for Gunter's chain"] property = 'length' - [unit.value] - Unit = '[ch_us]/100' - UNIT = '[CH_US]/100' - value = 1 +[unit.value] +Unit = '[ch_us]/100' +UNIT = '[CH_US]/100' +value = 1 [[unit]] Code = '[rch_us]' @@ -1737,10 +1737,10 @@ class = 'us-lengths' names = ["Ramden's chain", "Engineer's chain"] property = 'length' - [unit.value] - Unit = '[ft_us]' - UNIT = '[FT_US]' - value = 100 +[unit.value] +Unit = '[ft_us]' +UNIT = '[FT_US]' +value = 100 [[unit]] Code = '[rlk_us]' @@ -1750,10 +1750,10 @@ class = 'us-lengths' names = ["link for Ramden's chain"] property = 'length' - [unit.value] - Unit = '[rch_us]/100' - UNIT = '[RCH_US]/100' - value = 1 +[unit.value] +Unit = '[rch_us]/100' +UNIT = '[RCH_US]/100' +value = 1 [[unit]] Code = '[fth_us]' @@ -1763,10 +1763,10 @@ class = 'us-lengths' names = ['fathom'] property = 'length' - [unit.value] - Unit = '[ft_us]' - UNIT = '[FT_US]' - value = 6 +[unit.value] +Unit = '[ft_us]' +UNIT = '[FT_US]' +value = 6 [[unit]] Code = '[fur_us]' @@ -1776,10 +1776,10 @@ class = 'us-lengths' names = ['furlong'] property = 'length' - [unit.value] - Unit = '[rd_us]' - UNIT = '[RD_US]' - value = 40 +[unit.value] +Unit = '[rd_us]' +UNIT = '[RD_US]' +value = 40 [[unit]] Code = '[mi_us]' @@ -1789,10 +1789,10 @@ class = 'us-lengths' names = ['mile'] property = 'length' - [unit.value] - Unit = '[fur_us]' - UNIT = '[FUR_US]' - value = 8 +[unit.value] +Unit = '[fur_us]' +UNIT = '[FUR_US]' +value = 8 [[unit]] Code = '[acr_us]' @@ -1802,10 +1802,10 @@ class = 'us-lengths' names = ['acre'] property = 'area' - [unit.value] - Unit = '[rd_us]2' - UNIT = '[RD_US]2' - value = 160 +[unit.value] +Unit = '[rd_us]2' +UNIT = '[RD_US]2' +value = 160 [[unit]] Code = '[srd_us]' @@ -1815,10 +1815,10 @@ class = 'us-lengths' names = ['square rod'] property = 'area' - [unit.value] - Unit = '[rd_us]2' - UNIT = '[RD_US]2' - value = 1 +[unit.value] +Unit = '[rd_us]2' +UNIT = '[RD_US]2' +value = 1 [[unit]] Code = '[smi_us]' @@ -1828,10 +1828,10 @@ class = 'us-lengths' names = ['square mile'] property = 'area' - [unit.value] - Unit = '[mi_us]2' - UNIT = '[MI_US]2' - value = 1 +[unit.value] +Unit = '[mi_us]2' +UNIT = '[MI_US]2' +value = 1 [[unit]] Code = '[sct]' @@ -1841,10 +1841,10 @@ class = 'us-lengths' names = ['section'] property = 'area' - [unit.value] - Unit = '[mi_us]2' - UNIT = '[MI_US]2' - value = 1 +[unit.value] +Unit = '[mi_us]2' +UNIT = '[MI_US]2' +value = 1 [[unit]] Code = '[twp]' @@ -1854,10 +1854,10 @@ class = 'us-lengths' names = ['township'] property = 'area' - [unit.value] - Unit = '[sct]' - UNIT = '[SCT]' - value = 36 +[unit.value] +Unit = '[sct]' +UNIT = '[SCT]' +value = 36 [[unit]] Code = '[mil_us]' @@ -1867,10 +1867,10 @@ class = 'us-lengths' names = ['mil'] property = 'length' - [unit.value] - Unit = '[in_us]' - UNIT = '[IN_US]' - value = 1e-3 +[unit.value] +Unit = '[in_us]' +UNIT = '[IN_US]' +value = 1e-3 [[unit]] Code = '[in_br]' @@ -1880,10 +1880,10 @@ class = 'brit-length' names = ['inch'] property = 'length' - [unit.value] - Unit = 'cm' - UNIT = 'CM' - value = 2.539998 +[unit.value] +Unit = 'cm' +UNIT = 'CM' +value = 2.539998 [[unit]] Code = '[ft_br]' @@ -1893,10 +1893,10 @@ class = 'brit-length' names = ['foot'] property = 'length' - [unit.value] - Unit = '[in_br]' - UNIT = '[IN_BR]' - value = 12 +[unit.value] +Unit = '[in_br]' +UNIT = '[IN_BR]' +value = 12 [[unit]] Code = '[rd_br]' @@ -1906,10 +1906,10 @@ class = 'brit-length' names = ['rod'] property = 'length' - [unit.value] - Unit = '[ft_br]' - UNIT = '[FT_BR]' - value = 16.5 +[unit.value] +Unit = '[ft_br]' +UNIT = '[FT_BR]' +value = 16.5 [[unit]] Code = '[ch_br]' @@ -1919,10 +1919,10 @@ class = 'brit-length' names = ["Gunter's chain"] property = 'length' - [unit.value] - Unit = '[rd_br]' - UNIT = '[RD_BR]' - value = 4 +[unit.value] +Unit = '[rd_br]' +UNIT = '[RD_BR]' +value = 4 [[unit]] Code = '[lk_br]' @@ -1932,10 +1932,10 @@ class = 'brit-length' names = ["link for Gunter's chain"] property = 'length' - [unit.value] - Unit = '[ch_br]/100' - UNIT = '[CH_BR]/100' - value = 1 +[unit.value] +Unit = '[ch_br]/100' +UNIT = '[CH_BR]/100' +value = 1 [[unit]] Code = '[fth_br]' @@ -1945,10 +1945,10 @@ class = 'brit-length' names = ['fathom'] property = 'length' - [unit.value] - Unit = '[ft_br]' - UNIT = '[FT_BR]' - value = 6 +[unit.value] +Unit = '[ft_br]' +UNIT = '[FT_BR]' +value = 6 [[unit]] Code = '[pc_br]' @@ -1958,10 +1958,10 @@ class = 'brit-length' names = ['pace'] property = 'length' - [unit.value] - Unit = '[ft_br]' - UNIT = '[FT_BR]' - value = 2.5 +[unit.value] +Unit = '[ft_br]' +UNIT = '[FT_BR]' +value = 2.5 [[unit]] Code = '[yd_br]' @@ -1971,10 +1971,10 @@ class = 'brit-length' names = ['yard'] property = 'length' - [unit.value] - Unit = '[ft_br]' - UNIT = '[FT_BR]' - value = 3 +[unit.value] +Unit = '[ft_br]' +UNIT = '[FT_BR]' +value = 3 [[unit]] Code = '[mi_br]' @@ -1984,10 +1984,10 @@ class = 'brit-length' names = ['mile'] property = 'length' - [unit.value] - Unit = '[ft_br]' - UNIT = '[FT_BR]' - value = 5280 +[unit.value] +Unit = '[ft_br]' +UNIT = '[FT_BR]' +value = 5280 [[unit]] Code = '[nmi_br]' @@ -1997,10 +1997,10 @@ class = 'brit-length' names = ['nautical mile'] property = 'length' - [unit.value] - Unit = '[ft_br]' - UNIT = '[FT_BR]' - value = 6080 +[unit.value] +Unit = '[ft_br]' +UNIT = '[FT_BR]' +value = 6080 [[unit]] Code = '[kn_br]' @@ -2010,10 +2010,10 @@ class = 'brit-length' names = ['knot'] property = 'velocity' - [unit.value] - Unit = '[nmi_br]/h' - UNIT = '[NMI_BR]/H' - value = 1 +[unit.value] +Unit = '[nmi_br]/h' +UNIT = '[NMI_BR]/H' +value = 1 [[unit]] Code = '[acr_br]' @@ -2023,10 +2023,10 @@ class = 'brit-length' names = ['acre'] property = 'area' - [unit.value] - Unit = '[yd_br]2' - UNIT = '[YD_BR]2' - value = 4840 +[unit.value] +Unit = '[yd_br]2' +UNIT = '[YD_BR]2' +value = 4840 [[unit]] Code = '[gal_us]' @@ -2036,10 +2036,10 @@ class = 'us-volumes' names = ["Queen Anne's wine gallon"] property = 'fluid volume' - [unit.value] - Unit = '[in_i]3' - UNIT = '[IN_I]3' - value = 231 +[unit.value] +Unit = '[in_i]3' +UNIT = '[IN_I]3' +value = 231 [[unit]] Code = '[bbl_us]' @@ -2049,10 +2049,10 @@ class = 'us-volumes' names = ['barrel'] property = 'fluid volume' - [unit.value] - Unit = '[gal_us]' - UNIT = '[GAL_US]' - value = 42 +[unit.value] +Unit = '[gal_us]' +UNIT = '[GAL_US]' +value = 42 [[unit]] Code = '[qt_us]' @@ -2062,10 +2062,10 @@ class = 'us-volumes' names = ['quart'] property = 'fluid volume' - [unit.value] - Unit = '[gal_us]/4' - UNIT = '[GAL_US]/4' - value = 1 +[unit.value] +Unit = '[gal_us]/4' +UNIT = '[GAL_US]/4' +value = 1 [[unit]] Code = '[pt_us]' @@ -2075,10 +2075,10 @@ class = 'us-volumes' names = ['pint'] property = 'fluid volume' - [unit.value] - Unit = '[qt_us]/2' - UNIT = '[QT_US]/2' - value = 1 +[unit.value] +Unit = '[qt_us]/2' +UNIT = '[QT_US]/2' +value = 1 [[unit]] Code = '[gil_us]' @@ -2088,10 +2088,10 @@ class = 'us-volumes' names = ['gill'] property = 'fluid volume' - [unit.value] - Unit = '[pt_us]/4' - UNIT = '[PT_US]/4' - value = 1 +[unit.value] +Unit = '[pt_us]/4' +UNIT = '[PT_US]/4' +value = 1 [[unit]] Code = '[foz_us]' @@ -2102,10 +2102,10 @@ names = ['fluid ounce'] printSymbol = 'oz fl' property = 'fluid volume' - [unit.value] - Unit = '[gil_us]/4' - UNIT = '[GIL_US]/4' - value = 1 +[unit.value] +Unit = '[gil_us]/4' +UNIT = '[GIL_US]/4' +value = 1 [[unit]] Code = '[fdr_us]' @@ -2115,10 +2115,10 @@ class = 'us-volumes' names = ['fluid dram'] property = 'fluid volume' - [unit.value] - Unit = '[foz_us]/8' - UNIT = '[FOZ_US]/8' - value = 1 +[unit.value] +Unit = '[foz_us]/8' +UNIT = '[FOZ_US]/8' +value = 1 [[unit]] Code = '[min_us]' @@ -2128,10 +2128,10 @@ class = 'us-volumes' names = ['minim'] property = 'fluid volume' - [unit.value] - Unit = '[fdr_us]/60' - UNIT = '[FDR_US]/60' - value = 1 +[unit.value] +Unit = '[fdr_us]/60' +UNIT = '[FDR_US]/60' +value = 1 [[unit]] Code = '[crd_us]' @@ -2141,10 +2141,10 @@ class = 'us-volumes' names = ['cord'] property = 'fluid volume' - [unit.value] - Unit = '[ft_i]3' - UNIT = '[FT_I]3' - value = 128 +[unit.value] +Unit = '[ft_i]3' +UNIT = '[FT_I]3' +value = 128 [[unit]] Code = '[bu_us]' @@ -2154,10 +2154,10 @@ class = 'us-volumes' names = ['bushel'] property = 'dry volume' - [unit.value] - Unit = '[in_i]3' - UNIT = '[IN_I]3' - value = 2150.42 +[unit.value] +Unit = '[in_i]3' +UNIT = '[IN_I]3' +value = 2150.42 [[unit]] Code = '[gal_wi]' @@ -2167,10 +2167,10 @@ class = 'us-volumes' names = ['historical winchester gallon'] property = 'dry volume' - [unit.value] - Unit = '[bu_us]/8' - UNIT = '[BU_US]/8' - value = 1 +[unit.value] +Unit = '[bu_us]/8' +UNIT = '[BU_US]/8' +value = 1 [[unit]] Code = '[pk_us]' @@ -2180,10 +2180,10 @@ class = 'us-volumes' names = ['peck'] property = 'dry volume' - [unit.value] - Unit = '[bu_us]/4' - UNIT = '[BU_US]/4' - value = 1 +[unit.value] +Unit = '[bu_us]/4' +UNIT = '[BU_US]/4' +value = 1 [[unit]] Code = '[dqt_us]' @@ -2193,10 +2193,10 @@ class = 'us-volumes' names = ['dry quart'] property = 'dry volume' - [unit.value] - Unit = '[pk_us]/8' - UNIT = '[PK_US]/8' - value = 1 +[unit.value] +Unit = '[pk_us]/8' +UNIT = '[PK_US]/8' +value = 1 [[unit]] Code = '[dpt_us]' @@ -2206,10 +2206,10 @@ class = 'us-volumes' names = ['dry pint'] property = 'dry volume' - [unit.value] - Unit = '[dqt_us]/2' - UNIT = '[DQT_US]/2' - value = 1 +[unit.value] +Unit = '[dqt_us]/2' +UNIT = '[DQT_US]/2' +value = 1 [[unit]] Code = '[tbs_us]' @@ -2219,10 +2219,10 @@ class = 'us-volumes' names = ['tablespoon'] property = 'volume' - [unit.value] - Unit = '[foz_us]/2' - UNIT = '[FOZ_US]/2' - value = 1 +[unit.value] +Unit = '[foz_us]/2' +UNIT = '[FOZ_US]/2' +value = 1 [[unit]] Code = '[tsp_us]' @@ -2232,10 +2232,10 @@ class = 'us-volumes' names = ['teaspoon'] property = 'volume' - [unit.value] - Unit = '[tbs_us]/3' - UNIT = '[TBS_US]/3' - value = 1 +[unit.value] +Unit = '[tbs_us]/3' +UNIT = '[TBS_US]/3' +value = 1 [[unit]] Code = '[cup_us]' @@ -2245,10 +2245,10 @@ class = 'us-volumes' names = ['cup'] property = 'volume' - [unit.value] - Unit = '[tbs_us]' - UNIT = '[TBS_US]' - value = 16 +[unit.value] +Unit = '[tbs_us]' +UNIT = '[TBS_US]' +value = 16 [[unit]] Code = '[foz_m]' @@ -2259,10 +2259,10 @@ names = ['metric fluid ounce'] printSymbol = 'oz fl' property = 'fluid volume' - [unit.value] - Unit = 'mL' - UNIT = 'ML' - value = 30 +[unit.value] +Unit = 'mL' +UNIT = 'ML' +value = 30 [[unit]] Code = '[cup_m]' @@ -2272,10 +2272,10 @@ class = 'us-volumes' names = ['metric cup'] property = 'volume' - [unit.value] - Unit = 'mL' - UNIT = 'ML' - value = 240 +[unit.value] +Unit = 'mL' +UNIT = 'ML' +value = 240 [[unit]] Code = '[tsp_m]' @@ -2285,10 +2285,10 @@ class = 'us-volumes' names = ['metric teaspoon'] property = 'volume' - [unit.value] - Unit = 'mL' - UNIT = 'mL' - value = 5 +[unit.value] +Unit = 'mL' +UNIT = 'mL' +value = 5 [[unit]] Code = '[tbs_m]' @@ -2298,10 +2298,10 @@ class = 'us-volumes' names = ['metric tablespoon'] property = 'volume' - [unit.value] - Unit = 'mL' - UNIT = 'mL' - value = 15 +[unit.value] +Unit = 'mL' +UNIT = 'mL' +value = 15 [[unit]] Code = '[gal_br]' @@ -2311,10 +2311,10 @@ class = 'brit-volumes' names = ['gallon'] property = 'volume' - [unit.value] - Unit = 'l' - UNIT = 'L' - value = 4.54609 +[unit.value] +Unit = 'l' +UNIT = 'L' +value = 4.54609 [[unit]] Code = '[pk_br]' @@ -2324,10 +2324,10 @@ class = 'brit-volumes' names = ['peck'] property = 'volume' - [unit.value] - Unit = '[gal_br]' - UNIT = '[GAL_BR]' - value = 2 +[unit.value] +Unit = '[gal_br]' +UNIT = '[GAL_BR]' +value = 2 [[unit]] Code = '[bu_br]' @@ -2337,10 +2337,10 @@ class = 'brit-volumes' names = ['bushel'] property = 'volume' - [unit.value] - Unit = '[pk_br]' - UNIT = '[PK_BR]' - value = 4 +[unit.value] +Unit = '[pk_br]' +UNIT = '[PK_BR]' +value = 4 [[unit]] Code = '[qt_br]' @@ -2350,10 +2350,10 @@ class = 'brit-volumes' names = ['quart'] property = 'volume' - [unit.value] - Unit = '[gal_br]/4' - UNIT = '[GAL_BR]/4' - value = 1 +[unit.value] +Unit = '[gal_br]/4' +UNIT = '[GAL_BR]/4' +value = 1 [[unit]] Code = '[pt_br]' @@ -2363,10 +2363,10 @@ class = 'brit-volumes' names = ['pint'] property = 'volume' - [unit.value] - Unit = '[qt_br]/2' - UNIT = '[QT_BR]/2' - value = 1 +[unit.value] +Unit = '[qt_br]/2' +UNIT = '[QT_BR]/2' +value = 1 [[unit]] Code = '[gil_br]' @@ -2376,10 +2376,10 @@ class = 'brit-volumes' names = ['gill'] property = 'volume' - [unit.value] - Unit = '[pt_br]/4' - UNIT = '[PT_BR]/4' - value = 1 +[unit.value] +Unit = '[pt_br]/4' +UNIT = '[PT_BR]/4' +value = 1 [[unit]] Code = '[foz_br]' @@ -2389,10 +2389,10 @@ class = 'brit-volumes' names = ['fluid ounce'] property = 'volume' - [unit.value] - Unit = '[gil_br]/5' - UNIT = '[GIL_BR]/5' - value = 1 +[unit.value] +Unit = '[gil_br]/5' +UNIT = '[GIL_BR]/5' +value = 1 [[unit]] Code = '[fdr_br]' @@ -2402,10 +2402,10 @@ class = 'brit-volumes' names = ['fluid dram'] property = 'volume' - [unit.value] - Unit = '[foz_br]/8' - UNIT = '[FOZ_BR]/8' - value = 1 +[unit.value] +Unit = '[foz_br]/8' +UNIT = '[FOZ_BR]/8' +value = 1 [[unit]] Code = '[min_br]' @@ -2415,10 +2415,10 @@ class = 'brit-volumes' names = ['minim'] property = 'volume' - [unit.value] - Unit = '[fdr_br]/60' - UNIT = '[FDR_BR]/60' - value = 1 +[unit.value] +Unit = '[fdr_br]/60' +UNIT = '[FDR_BR]/60' +value = 1 [[unit]] Code = '[gr]' @@ -2428,10 +2428,10 @@ class = 'avoirdupois' names = ['grain'] property = 'mass' - [unit.value] - Unit = 'mg' - UNIT = 'MG' - value = 64.79891 +[unit.value] +Unit = 'mg' +UNIT = 'MG' +value = 64.79891 [[unit]] Code = '[lb_av]' @@ -2442,10 +2442,10 @@ names = ['pound'] printSymbol = 'lb' property = 'mass' - [unit.value] - Unit = '[gr]' - UNIT = '[GR]' - value = 7000 +[unit.value] +Unit = '[gr]' +UNIT = '[GR]' +value = 7000 [[unit]] Code = '[oz_av]' @@ -2456,10 +2456,10 @@ names = ['ounce'] printSymbol = 'oz' property = 'mass' - [unit.value] - Unit = '[lb_av]/16' - UNIT = '[LB_AV]/16' - value = 1 +[unit.value] +Unit = '[lb_av]/16' +UNIT = '[LB_AV]/16' +value = 1 [[unit]] Code = '[dr_av]' @@ -2469,10 +2469,10 @@ class = 'avoirdupois' names = ['dram'] property = 'mass' - [unit.value] - Unit = '[oz_av]/16' - UNIT = '[OZ_AV]/16' - value = 1 +[unit.value] +Unit = '[oz_av]/16' +UNIT = '[OZ_AV]/16' +value = 1 [[unit]] Code = '[scwt_av]' @@ -2482,10 +2482,10 @@ class = 'avoirdupois' names = ['short hundredweight', 'U.S. hundredweight'] property = 'mass' - [unit.value] - Unit = '[lb_av]' - UNIT = '[LB_AV]' - value = 100 +[unit.value] +Unit = '[lb_av]' +UNIT = '[LB_AV]' +value = 100 [[unit]] Code = '[lcwt_av]' @@ -2495,10 +2495,10 @@ class = 'avoirdupois' names = ['long hunderdweight', 'British hundredweight'] property = 'mass' - [unit.value] - Unit = '[lb_av]' - UNIT = '[LB_AV]' - value = 112 +[unit.value] +Unit = '[lb_av]' +UNIT = '[LB_AV]' +value = 112 [[unit]] Code = '[ston_av]' @@ -2508,10 +2508,10 @@ class = 'avoirdupois' names = ['short ton', 'U.S. ton'] property = 'mass' - [unit.value] - Unit = '[scwt_av]' - UNIT = '[SCWT_AV]' - value = 20 +[unit.value] +Unit = '[scwt_av]' +UNIT = '[SCWT_AV]' +value = 20 [[unit]] Code = '[lton_av]' @@ -2521,10 +2521,10 @@ class = 'avoirdupois' names = ['long ton', 'British ton'] property = 'mass' - [unit.value] - Unit = '[lcwt_av]' - UNIT = '[LCWT_AV]' - value = 20 +[unit.value] +Unit = '[lcwt_av]' +UNIT = '[LCWT_AV]' +value = 20 [[unit]] Code = '[stone_av]' @@ -2534,10 +2534,10 @@ class = 'avoirdupois' names = ['stone', 'British stone'] property = 'mass' - [unit.value] - Unit = '[lb_av]' - UNIT = '[LB_AV]' - value = 14 +[unit.value] +Unit = '[lb_av]' +UNIT = '[LB_AV]' +value = 14 [[unit]] Code = '[pwt_tr]' @@ -2547,10 +2547,10 @@ class = 'troy' names = ['pennyweight'] property = 'mass' - [unit.value] - Unit = '[gr]' - UNIT = '[GR]' - value = 24 +[unit.value] +Unit = '[gr]' +UNIT = '[GR]' +value = 24 [[unit]] Code = '[oz_tr]' @@ -2560,10 +2560,10 @@ class = 'troy' names = ['ounce'] property = 'mass' - [unit.value] - Unit = '[pwt_tr]' - UNIT = '[PWT_TR]' - value = 20 +[unit.value] +Unit = '[pwt_tr]' +UNIT = '[PWT_TR]' +value = 20 [[unit]] Code = '[lb_tr]' @@ -2573,10 +2573,10 @@ class = 'troy' names = ['pound'] property = 'mass' - [unit.value] - Unit = '[oz_tr]' - UNIT = '[OZ_TR]' - value = 12 +[unit.value] +Unit = '[oz_tr]' +UNIT = '[OZ_TR]' +value = 12 [[unit]] Code = '[sc_ap]' @@ -2586,10 +2586,10 @@ class = 'apoth' names = ['scruple'] property = 'mass' - [unit.value] - Unit = '[gr]' - UNIT = '[GR]' - value = 20 +[unit.value] +Unit = '[gr]' +UNIT = '[GR]' +value = 20 [[unit]] Code = '[dr_ap]' @@ -2599,10 +2599,10 @@ class = 'apoth' names = ['dram', 'drachm'] property = 'mass' - [unit.value] - Unit = '[sc_ap]' - UNIT = '[SC_AP]' - value = 3 +[unit.value] +Unit = '[sc_ap]' +UNIT = '[SC_AP]' +value = 3 [[unit]] Code = '[oz_ap]' @@ -2612,10 +2612,10 @@ class = 'apoth' names = ['ounce'] property = 'mass' - [unit.value] - Unit = '[dr_ap]' - UNIT = '[DR_AP]' - value = 8 +[unit.value] +Unit = '[dr_ap]' +UNIT = '[DR_AP]' +value = 8 [[unit]] Code = '[lb_ap]' @@ -2625,10 +2625,10 @@ class = 'apoth' names = ['pound'] property = 'mass' - [unit.value] - Unit = '[oz_ap]' - UNIT = '[OZ_AP]' - value = 12 +[unit.value] +Unit = '[oz_ap]' +UNIT = '[OZ_AP]' +value = 12 [[unit]] Code = '[oz_m]' @@ -2638,10 +2638,10 @@ class = 'apoth' names = ['metric ounce'] property = 'mass' - [unit.value] - Unit = 'g' - UNIT = 'g' - value = 28 +[unit.value] +Unit = 'g' +UNIT = 'g' +value = 28 [[unit]] Code = '[lne]' @@ -2651,10 +2651,10 @@ class = 'typeset' names = ['line'] property = 'length' - [unit.value] - Unit = '[in_i]/12' - UNIT = '[IN_I]/12' - value = 1 +[unit.value] +Unit = '[in_i]/12' +UNIT = '[IN_I]/12' +value = 1 [[unit]] Code = '[pnt]' @@ -2664,10 +2664,10 @@ class = 'typeset' names = ['point'] property = 'length' - [unit.value] - Unit = '[lne]/6' - UNIT = '[LNE]/6' - value = 1 +[unit.value] +Unit = '[lne]/6' +UNIT = '[LNE]/6' +value = 1 [[unit]] Code = '[pca]' @@ -2677,10 +2677,10 @@ class = 'typeset' names = ['pica'] property = 'length' - [unit.value] - Unit = '[pnt]' - UNIT = '[PNT]' - value = 12 +[unit.value] +Unit = '[pnt]' +UNIT = '[PNT]' +value = 12 [[unit]] Code = '[pnt_pr]' @@ -2690,10 +2690,10 @@ class = 'typeset' names = ["Printer's point"] property = 'length' - [unit.value] - Unit = '[in_i]' - UNIT = '[IN_I]' - value = 0.013837 +[unit.value] +Unit = '[in_i]' +UNIT = '[IN_I]' +value = 0.013837 [[unit]] Code = '[pca_pr]' @@ -2703,10 +2703,10 @@ class = 'typeset' names = ["Printer's pica"] property = 'length' - [unit.value] - Unit = '[pnt_pr]' - UNIT = '[PNT_PR]' - value = 12 +[unit.value] +Unit = '[pnt_pr]' +UNIT = '[PNT_PR]' +value = 12 [[unit]] Code = '[pied]' @@ -2716,10 +2716,10 @@ class = 'typeset' names = ['pied', 'French foot'] property = 'length' - [unit.value] - Unit = 'cm' - UNIT = 'CM' - value = 32.48 +[unit.value] +Unit = 'cm' +UNIT = 'CM' +value = 32.48 [[unit]] Code = '[pouce]' @@ -2729,10 +2729,10 @@ class = 'typeset' names = ['pouce', 'French inch'] property = 'length' - [unit.value] - Unit = '[pied]/12' - UNIT = '[PIED]/12' - value = 1 +[unit.value] +Unit = '[pied]/12' +UNIT = '[PIED]/12' +value = 1 [[unit]] Code = '[ligne]' @@ -2742,10 +2742,10 @@ class = 'typeset' names = ['ligne', 'French line'] property = 'length' - [unit.value] - Unit = '[pouce]/12' - UNIT = '[POUCE]/12' - value = 1 +[unit.value] +Unit = '[pouce]/12' +UNIT = '[POUCE]/12' +value = 1 [[unit]] Code = '[didot]' @@ -2755,10 +2755,10 @@ class = 'typeset' names = ['didot', "Didot's point"] property = 'length' - [unit.value] - Unit = '[ligne]/6' - UNIT = '[LIGNE]/6' - value = 1 +[unit.value] +Unit = '[ligne]/6' +UNIT = '[LIGNE]/6' +value = 1 [[unit]] Code = '[cicero]' @@ -2768,10 +2768,10 @@ class = 'typeset' names = ['cicero', "Didot's pica"] property = 'length' - [unit.value] - Unit = '[didot]' - UNIT = '[DIDOT]' - value = 12 +[unit.value] +Unit = '[didot]' +UNIT = '[DIDOT]' +value = 12 [[unit]] Code = '[degF]' @@ -2783,14 +2783,14 @@ names = ['degree Fahrenheit'] printSymbol = '°F' property = 'temperature' - [unit.value] - Unit = 'degf(5 K/9)' - UNIT = 'DEGF(5 K/9)' +[unit.value] +Unit = 'degf(5 K/9)' +UNIT = 'DEGF(5 K/9)' - [unit.value.function] - name = 'degF' - value = 5 - Unit = 'K/9' +[unit.value.function] +name = 'degF' +value = 5 +Unit = 'K/9' [[unit]] Code = '[degR]' @@ -2801,10 +2801,10 @@ names = ['degree Rankine'] printSymbol = '°R' property = 'temperature' - [unit.value] - value = 5 - Unit = 'K/9' - UNIT = 'K/9' +[unit.value] +value = 5 +Unit = 'K/9' +UNIT = 'K/9' [[unit]] Code = '[degRe]' @@ -2816,14 +2816,14 @@ names = ['degree Réaumur'] printSymbol = '°Ré' property = 'temperature' - [unit.value] - Unit = 'degre(5 K/4)' - UNIT = 'DEGRE(5 K/4)' +[unit.value] +Unit = 'degre(5 K/4)' +UNIT = 'DEGRE(5 K/4)' - [unit.value.function] - name = 'degRe' - value = 5 - Unit = 'K/4' +[unit.value.function] +name = 'degRe' +value = 5 +Unit = 'K/4' [[unit]] Code = 'cal_[15]' @@ -2834,10 +2834,10 @@ names = ['calorie at 15 °C'] printSymbol = 'cal15°C' property = 'energy' - [unit.value] - Unit = 'J' - UNIT = 'J' - value = 4.18580 +[unit.value] +Unit = 'J' +UNIT = 'J' +value = 4.18580 [[unit]] Code = 'cal_[20]' @@ -2848,10 +2848,10 @@ names = ['calorie at 20 °C'] printSymbol = 'cal20°C' property = 'energy' - [unit.value] - Unit = 'J' - UNIT = 'J' - value = 4.18190 +[unit.value] +Unit = 'J' +UNIT = 'J' +value = 4.18190 [[unit]] Code = 'cal_m' @@ -2862,10 +2862,10 @@ names = ['mean calorie'] printSymbol = 'calm' property = 'energy' - [unit.value] - Unit = 'J' - UNIT = 'J' - value = 4.19002 +[unit.value] +Unit = 'J' +UNIT = 'J' +value = 4.19002 [[unit]] Code = 'cal_IT' @@ -2876,10 +2876,10 @@ names = ['international table calorie'] printSymbol = 'calIT' property = 'energy' - [unit.value] - Unit = 'J' - UNIT = 'J' - value = 4.1868 +[unit.value] +Unit = 'J' +UNIT = 'J' +value = 4.1868 [[unit]] Code = 'cal_th' @@ -2890,10 +2890,10 @@ names = ['thermochemical calorie'] printSymbol = 'calth' property = 'energy' - [unit.value] - Unit = 'J' - UNIT = 'J' - value = 4.184 +[unit.value] +Unit = 'J' +UNIT = 'J' +value = 4.184 [[unit]] Code = 'cal' @@ -2904,10 +2904,10 @@ names = ['calorie'] printSymbol = 'cal' property = 'energy' - [unit.value] - Unit = 'cal_th' - UNIT = 'CAL_TH' - value = 1 +[unit.value] +Unit = 'cal_th' +UNIT = 'CAL_TH' +value = 1 [[unit]] Code = '[Cal]' @@ -2918,10 +2918,10 @@ names = ['nutrition label Calories'] printSymbol = 'Cal' property = 'energy' - [unit.value] - Unit = 'kcal_th' - UNIT = 'KCAL_TH' - value = 1 +[unit.value] +Unit = 'kcal_th' +UNIT = 'KCAL_TH' +value = 1 [[unit]] Code = '[Btu_39]' @@ -2932,10 +2932,10 @@ names = ['British thermal unit at 39 °F'] printSymbol = 'Btu39°F' property = 'energy' - [unit.value] - Unit = 'kJ' - UNIT = 'kJ' - value = 1.05967 +[unit.value] +Unit = 'kJ' +UNIT = 'kJ' +value = 1.05967 [[unit]] Code = '[Btu_59]' @@ -2946,10 +2946,10 @@ names = ['British thermal unit at 59 °F'] printSymbol = 'Btu59°F' property = 'energy' - [unit.value] - Unit = 'kJ' - UNIT = 'kJ' - value = 1.05480 +[unit.value] +Unit = 'kJ' +UNIT = 'kJ' +value = 1.05480 [[unit]] Code = '[Btu_60]' @@ -2960,10 +2960,10 @@ names = ['British thermal unit at 60 °F'] printSymbol = 'Btu60°F' property = 'energy' - [unit.value] - Unit = 'kJ' - UNIT = 'kJ' - value = 1.05468 +[unit.value] +Unit = 'kJ' +UNIT = 'kJ' +value = 1.05468 [[unit]] Code = '[Btu_m]' @@ -2974,10 +2974,10 @@ names = ['mean British thermal unit'] printSymbol = 'Btum' property = 'energy' - [unit.value] - Unit = 'kJ' - UNIT = 'kJ' - value = 1.05587 +[unit.value] +Unit = 'kJ' +UNIT = 'kJ' +value = 1.05587 [[unit]] Code = '[Btu_IT]' @@ -2988,10 +2988,10 @@ names = ['international table British thermal unit'] printSymbol = 'BtuIT' property = 'energy' - [unit.value] - Unit = 'kJ' - UNIT = 'kJ' - value = 1.05505585262 +[unit.value] +Unit = 'kJ' +UNIT = 'kJ' +value = 1.05505585262 [[unit]] Code = '[Btu_th]' @@ -3002,10 +3002,10 @@ names = ['thermochemical British thermal unit'] printSymbol = 'Btuth' property = 'energy' - [unit.value] - Unit = 'kJ' - UNIT = 'kJ' - value = 1.054350 +[unit.value] +Unit = 'kJ' +UNIT = 'kJ' +value = 1.054350 [[unit]] Code = '[Btu]' @@ -3016,10 +3016,10 @@ names = ['British thermal unit'] printSymbol = 'btu' property = 'energy' - [unit.value] - Unit = '[Btu_th]' - UNIT = '[BTU_TH]' - value = 1 +[unit.value] +Unit = '[Btu_th]' +UNIT = '[BTU_TH]' +value = 1 [[unit]] Code = '[HP]' @@ -3029,10 +3029,10 @@ class = 'heat' names = ['horsepower'] property = 'power' - [unit.value] - Unit = '[ft_i].[lbf_av]/s' - UNIT = '[FT_I].[LBF_AV]/S' - value = 550 +[unit.value] +Unit = '[ft_i].[lbf_av]/s' +UNIT = '[FT_I].[LBF_AV]/S' +value = 550 [[unit]] Code = 'tex' @@ -3043,10 +3043,10 @@ names = ['tex'] printSymbol = 'tex' property = 'linear mass density (of textile thread)' - [unit.value] - value = 1 - Unit = 'g/km' - UNIT = 'G/KM' +[unit.value] +value = 1 +Unit = 'g/km' +UNIT = 'G/KM' [[unit]] Code = '[den]' @@ -3057,10 +3057,10 @@ names = ['Denier'] printSymbol = 'den' property = 'linear mass density (of textile thread)' - [unit.value] - value = 1 - Unit = 'g/9/km' - UNIT = 'G/9/KM' +[unit.value] +value = 1 +Unit = 'g/9/km' +UNIT = 'G/9/KM' [[unit]] Code = 'm[H2O]' @@ -3071,10 +3071,10 @@ names = ['meter of water column'] printSymbol = 'm H2O' property = 'pressure' - [unit.value] - Unit = 'kPa' - UNIT = 'KPAL' - value = 980665e-5 +[unit.value] +Unit = 'kPa' +UNIT = 'KPAL' +value = 980665e-5 [[unit]] Code = 'm[Hg]' @@ -3085,10 +3085,10 @@ names = ['meter of mercury column'] printSymbol = 'm Hg' property = 'pressure' - [unit.value] - Unit = 'kPa' - UNIT = 'KPAL' - value = 133.3220 +[unit.value] +Unit = 'kPa' +UNIT = 'KPAL' +value = 133.3220 [[unit]] Code = "[in_i'H2O]" @@ -3099,10 +3099,10 @@ names = ['inch of water column'] printSymbol = 'in H2O' property = 'pressure' - [unit.value] - Unit = 'm[H2O].[in_i]/m' - UNIT = 'M[H2O].[IN_I]/M' - value = 1 +[unit.value] +Unit = 'm[H2O].[in_i]/m' +UNIT = 'M[H2O].[IN_I]/M' +value = 1 [[unit]] Code = "[in_i'Hg]" @@ -3113,10 +3113,10 @@ names = ['inch of mercury column'] printSymbol = 'in Hg' property = 'pressure' - [unit.value] - Unit = 'm[Hg].[in_i]/m' - UNIT = 'M[HG].[IN_I]/M' - value = 1 +[unit.value] +Unit = 'm[Hg].[in_i]/m' +UNIT = 'M[HG].[IN_I]/M' +value = 1 [[unit]] Code = '[PRU]' @@ -3127,10 +3127,10 @@ names = ['peripheral vascular resistance unit'] printSymbol = 'P.R.U.' property = 'fluid resistance' - [unit.value] - Unit = 'mm[Hg].s/ml' - UNIT = 'MM[HG].S/ML' - value = 1 +[unit.value] +Unit = 'mm[Hg].s/ml' +UNIT = 'MM[HG].S/ML' +value = 1 [[unit]] Code = "[wood'U]" @@ -3141,10 +3141,10 @@ names = ['Wood unit'] printSymbol = 'Wood U.' property = 'fluid resistance' - [unit.value] - Unit = 'mm[Hg].min/L' - UNIT = 'MM[HG].MIN/L' - value = 1 +[unit.value] +Unit = 'mm[Hg].min/L' +UNIT = 'MM[HG].MIN/L' +value = 1 [[unit]] Code = '[diop]' @@ -3155,10 +3155,10 @@ names = ['diopter'] printSymbol = 'dpt' property = 'refraction of a lens' - [unit.value] - Unit = '/m' - UNIT = '/M' - value = 1 +[unit.value] +Unit = '/m' +UNIT = '/M' +value = 1 [[unit]] Code = "[p'diop]" @@ -3170,14 +3170,14 @@ names = ['prism diopter'] printSymbol = 'PD' property = 'refraction of a prism' - [unit.value] - Unit = '100tan(1 rad)' - UNIT = '100TAN(1 RAD)' +[unit.value] +Unit = '100tan(1 rad)' +UNIT = '100TAN(1 RAD)' - [unit.value.function] - name = 'tanTimes100' - value = 1 - Unit = 'rad' +[unit.value.function] +name = 'tanTimes100' +value = 1 +Unit = 'rad' [[unit]] Code = '%[slope]' @@ -3189,14 +3189,14 @@ names = ['percent of slope'] printSymbol = '%' property = 'slope' - [unit.value] - Unit = '100tan(1 rad)' - UNIT = '100TAN(1 RAD)' +[unit.value] +Unit = '100tan(1 rad)' +UNIT = '100TAN(1 RAD)' - [unit.value.function] - name = '100tan' - value = 1 - Unit = 'deg' +[unit.value.function] +name = '100tan' +value = 1 +Unit = 'deg' [[unit]] Code = '[mesh_i]' @@ -3206,10 +3206,10 @@ class = 'clinical' names = ['mesh'] property = 'lineic number' - [unit.value] - Unit = '/[in_i]' - UNIT = '/[IN_I]' - value = 1 +[unit.value] +Unit = '/[in_i]' +UNIT = '/[IN_I]' +value = 1 [[unit]] Code = '[Ch]' @@ -3220,10 +3220,10 @@ names = ['Charrière', 'french'] printSymbol = 'Ch' property = 'gauge of catheters' - [unit.value] - Unit = 'mm/3' - UNIT = 'MM/3' - value = 1 +[unit.value] +Unit = 'mm/3' +UNIT = 'MM/3' +value = 1 [[unit]] Code = '[drp]' @@ -3234,10 +3234,10 @@ names = ['drop'] printSymbol = 'drp' property = 'volume' - [unit.value] - Unit = 'ml/20' - UNIT = 'ML/20' - value = 1 +[unit.value] +Unit = 'ml/20' +UNIT = 'ML/20' +value = 1 [[unit]] Code = "[hnsf'U]" @@ -3248,10 +3248,10 @@ names = ['Hounsfield unit'] printSymbol = 'HF' property = 'x-ray attenuation' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[MET]' @@ -3262,10 +3262,10 @@ names = ['metabolic equivalent'] printSymbol = 'MET' property = 'metabolic cost of physical activity' - [unit.value] - Unit = 'mL/min/kg' - UNIT = 'ML/MIN/KG' - value = 3.5 +[unit.value] +Unit = 'mL/min/kg' +UNIT = 'ML/MIN/KG' +value = 3.5 [[unit]] Code = "[hp'_X]" @@ -3277,14 +3277,14 @@ names = ['homeopathic potency of decimal series (retired)'] printSymbol = 'X' property = 'homeopathic potency (retired)' - [unit.value] - Unit = 'hpX(1 1)' - UNIT = 'HPX(1 1)' +[unit.value] +Unit = 'hpX(1 1)' +UNIT = 'HPX(1 1)' - [unit.value.function] - name = 'hpX' - value = 1 - Unit = '1' +[unit.value.function] +name = 'hpX' +value = 1 +Unit = '1' [[unit]] Code = "[hp'_C]" @@ -3296,14 +3296,14 @@ names = ['homeopathic potency of centesimal series (retired)'] printSymbol = 'C' property = 'homeopathic potency (retired)' - [unit.value] - Unit = 'hpC(1 1)' - UNIT = 'HPC(1 1)' +[unit.value] +Unit = 'hpC(1 1)' +UNIT = 'HPC(1 1)' - [unit.value.function] - name = 'hpC' - value = 1 - Unit = '1' +[unit.value.function] +name = 'hpC' +value = 1 +Unit = '1' [[unit]] Code = "[hp'_M]" @@ -3315,14 +3315,14 @@ names = ['homeopathic potency of millesimal series (retired)'] printSymbol = 'M' property = 'homeopathic potency (retired)' - [unit.value] - Unit = 'hpM(1 1)' - UNIT = 'HPM(1 1)' +[unit.value] +Unit = 'hpM(1 1)' +UNIT = 'HPM(1 1)' - [unit.value.function] - name = 'hpM' - value = 1 - Unit = '1' +[unit.value.function] +name = 'hpM' +value = 1 +Unit = '1' [[unit]] Code = "[hp'_Q]" @@ -3334,14 +3334,14 @@ names = ['homeopathic potency of quintamillesimal series (retired)'] printSymbol = 'Q' property = 'homeopathic potency (retired)' - [unit.value] - Unit = 'hpQ(1 1)' - UNIT = 'HPQ(1 1)' +[unit.value] +Unit = 'hpQ(1 1)' +UNIT = 'HPQ(1 1)' - [unit.value.function] - name = 'hpQ' - value = 1 - Unit = '1' +[unit.value.function] +name = 'hpQ' +value = 1 +Unit = '1' [[unit]] Code = '[hp_X]' @@ -3353,10 +3353,10 @@ names = ['homeopathic potency of decimal hahnemannian series'] printSymbol = 'X' property = 'homeopathic potency (Hahnemann)' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[hp_C]' @@ -3368,10 +3368,10 @@ names = ['homeopathic potency of centesimal hahnemannian series'] printSymbol = 'C' property = 'homeopathic potency (Hahnemann)' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[hp_M]' @@ -3383,10 +3383,10 @@ names = ['homeopathic potency of millesimal hahnemannian series'] printSymbol = 'M' property = 'homeopathic potency (Hahnemann)' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[hp_Q]' @@ -3398,10 +3398,10 @@ names = ['homeopathic potency of quintamillesimal hahnemannian series'] printSymbol = 'Q' property = 'homeopathic potency (Hahnemann)' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[kp_X]' @@ -3413,10 +3413,10 @@ names = ['homeopathic potency of decimal korsakovian series'] printSymbol = 'X' property = 'homeopathic potency (Korsakov)' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[kp_C]' @@ -3428,10 +3428,10 @@ names = ['homeopathic potency of centesimal korsakovian series'] printSymbol = 'C' property = 'homeopathic potency (Korsakov)' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[kp_M]' @@ -3443,10 +3443,10 @@ names = ['homeopathic potency of millesimal korsakovian series'] printSymbol = 'M' property = 'homeopathic potency (Korsakov)' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[kp_Q]' @@ -3458,10 +3458,10 @@ names = ['homeopathic potency of quintamillesimal korsakovian series'] printSymbol = 'Q' property = 'homeopathic potency (Korsakov)' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = 'eq' @@ -3472,10 +3472,10 @@ names = ['equivalents'] printSymbol = 'eq' property = 'amount of substance' - [unit.value] - Unit = 'mol' - UNIT = 'MOL' - value = 1 +[unit.value] +Unit = 'mol' +UNIT = 'MOL' +value = 1 [[unit]] Code = 'osm' @@ -3486,10 +3486,10 @@ names = ['osmole'] printSymbol = 'osm' property = 'amount of substance (dissolved particles)' - [unit.value] - Unit = 'mol' - UNIT = 'MOL' - value = 1 +[unit.value] +Unit = 'mol' +UNIT = 'MOL' +value = 1 [[unit]] Code = '[pH]' @@ -3501,14 +3501,14 @@ names = ['pH'] printSymbol = 'pH' property = 'acidity' - [unit.value] - Unit = 'pH(1 mol/l)' - UNIT = 'PH(1 MOL/L)' +[unit.value] +Unit = 'pH(1 mol/l)' +UNIT = 'PH(1 MOL/L)' - [unit.value.function] - name = 'pH' - value = 1 - Unit = 'mol/l' +[unit.value.function] +name = 'pH' +value = 1 +Unit = 'mol/l' [[unit]] Code = 'g%' @@ -3519,10 +3519,10 @@ names = ['gram percent'] printSymbol = 'g%' property = 'mass concentration' - [unit.value] - Unit = 'g/dl' - UNIT = 'G/DL' - value = 1 +[unit.value] +Unit = 'g/dl' +UNIT = 'G/DL' +value = 1 [[unit]] Code = '[S]' @@ -3533,10 +3533,10 @@ names = ['Svedberg unit'] printSymbol = 'S' property = 'sedimentation coefficient' - [unit.value] - Unit = '10*-13.s' - UNIT = '10*-13.S' - value = 1 +[unit.value] +Unit = '10*-13.s' +UNIT = '10*-13.S' +value = 1 [[unit]] Code = '[HPF]' @@ -3547,10 +3547,10 @@ names = ['high power field'] printSymbol = 'HPF' property = 'view area in microscope' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[LPF]' @@ -3561,10 +3561,10 @@ names = ['low power field'] printSymbol = 'LPF' property = 'view area in microscope' - [unit.value] - Unit = '1' - UNIT = '1' - value = 100 +[unit.value] +Unit = '1' +UNIT = '1' +value = 100 [[unit]] Code = 'kat' @@ -3575,10 +3575,10 @@ names = ['katal'] printSymbol = 'kat' property = 'catalytic activity' - [unit.value] - Unit = 'mol/s' - UNIT = 'MOL/S' - value = 1 +[unit.value] +Unit = 'mol/s' +UNIT = 'MOL/S' +value = 1 [[unit]] Code = 'U' @@ -3589,10 +3589,10 @@ names = ['Unit'] printSymbol = 'U' property = 'catalytic activity' - [unit.value] - Unit = 'umol/min' - UNIT = 'UMOL/MIN' - value = 1 +[unit.value] +Unit = 'umol/min' +UNIT = 'UMOL/MIN' +value = 1 [[unit]] Code = '[iU]' @@ -3604,10 +3604,10 @@ names = ['international unit'] printSymbol = 'IU' property = 'arbitrary' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[IU]' @@ -3619,10 +3619,10 @@ names = ['international unit'] printSymbol = 'i.U.' property = 'arbitrary' - [unit.value] - Unit = '[iU]' - UNIT = '[IU]' - value = 1 +[unit.value] +Unit = '[iU]' +UNIT = '[IU]' +value = 1 [[unit]] Code = "[arb'U]" @@ -3634,10 +3634,10 @@ names = ['arbitrary unit'] printSymbol = 'arb. U' property = 'arbitrary' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[USP'U]" @@ -3649,10 +3649,10 @@ names = ['United States Pharmacopeia unit'] printSymbol = 'U.S.P.' property = 'arbitrary' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[GPL'U]" @@ -3663,10 +3663,10 @@ class = 'chemical' names = ['GPL unit'] property = 'biologic activity of anticardiolipin IgG' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[MPL'U]" @@ -3677,10 +3677,10 @@ class = 'chemical' names = ['MPL unit'] property = 'biologic activity of anticardiolipin IgM' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[APL'U]" @@ -3691,10 +3691,10 @@ class = 'chemical' names = ['APL unit'] property = 'biologic activity of anticardiolipin IgA' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[beth'U]" @@ -3705,10 +3705,10 @@ class = 'chemical' names = ['Bethesda unit'] property = 'biologic activity of factor VIII inhibitor' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[anti'Xa'U]" @@ -3719,10 +3719,10 @@ class = 'chemical' names = ['anti factor Xa unit'] property = 'biologic activity of factor Xa inhibitor (heparin)' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[todd'U]" @@ -3733,10 +3733,10 @@ class = 'chemical' names = ['Todd unit'] property = 'biologic activity antistreptolysin O' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[dye'U]" @@ -3747,10 +3747,10 @@ class = 'chemical' names = ['Dye unit'] property = 'biologic activity of amylase' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[smgy'U]" @@ -3761,10 +3761,10 @@ class = 'chemical' names = ['Somogyi unit'] property = 'biologic activity of amylase' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[bdsk'U]" @@ -3775,10 +3775,10 @@ class = 'chemical' names = ['Bodansky unit'] property = 'biologic activity of phosphatase' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[ka'U]" @@ -3789,10 +3789,10 @@ class = 'chemical' names = ['King-Armstrong unit'] property = 'biologic activity of phosphatase' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[knk'U]" @@ -3803,10 +3803,10 @@ class = 'chemical' names = ['Kunkel unit'] property = 'arbitrary biologic activity' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[mclg'U]" @@ -3817,10 +3817,10 @@ class = 'chemical' names = ['Mac Lagan unit'] property = 'arbitrary biologic activity' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[tb'U]" @@ -3831,10 +3831,10 @@ class = 'chemical' names = ['tuberculin unit'] property = 'biologic activity of tuberculin' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[CCID_50]' @@ -3846,10 +3846,10 @@ names = ['50% cell culture infectious dose'] printSymbol = 'CCID50' property = 'biologic activity (infectivity) of an infectious agent preparation' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[TCID_50]' @@ -3861,10 +3861,10 @@ names = ['50% tissue culture infectious dose'] printSymbol = 'TCID50' property = 'biologic activity (infectivity) of an infectious agent preparation' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[EID_50]' @@ -3876,10 +3876,10 @@ names = ['50% embryo infectious dose'] printSymbol = 'EID50' property = 'biologic activity (infectivity) of an infectious agent preparation' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[PFU]' @@ -3891,10 +3891,10 @@ names = ['plaque forming units'] printSymbol = 'PFU' property = 'amount of an infectious agent' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[FFU]' @@ -3906,10 +3906,10 @@ names = ['focus forming units'] printSymbol = 'FFU' property = 'amount of an infectious agent' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[CFU]' @@ -3921,10 +3921,10 @@ names = ['colony forming units'] printSymbol = 'CFU' property = 'amount of a proliferating organism' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[IR]' @@ -3934,12 +3934,12 @@ isArbitrary = 'yes' class = 'chemical' names = ['index of reactivity'] printSymbol = 'IR' -property = 'amount of an allergen callibrated through in-vivo testing using the Stallergenes® method.' +property = 'amount of an allergen calibrated through in-vivo testing using the Stallergenes® method.' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[BAU]' @@ -3949,12 +3949,12 @@ isArbitrary = 'yes' class = 'chemical' names = ['bioequivalent allergen unit'] printSymbol = 'BAU' -property = 'amount of an allergen callibrated through in-vivo testing based on the ID50EAL method of (intradermal dilution for 50mm sum of erythema diameters' +property = 'amount of an allergen calibrated through in-vivo testing based on the ID50EAL method of (intradermal dilution for 50mm sum of erythema diameters' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[AU]' @@ -3966,10 +3966,10 @@ names = ['allergen unit'] printSymbol = 'AU' property = 'procedure defined amount of an allergen using some reference standard' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[Amb'a'1'U]" @@ -3981,10 +3981,10 @@ names = ['allergen unit for Ambrosia artemisiifolia'] printSymbol = 'Amb a 1 U' property = 'procedure defined amount of the major allergen of ragweed.' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[PNU]' @@ -3996,10 +3996,10 @@ names = ['protein nitrogen unit'] printSymbol = 'PNU' property = 'procedure defined amount of a protein substance' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[Lf]' @@ -4011,10 +4011,10 @@ names = ['Limit of flocculation'] printSymbol = 'Lf' property = 'procedure defined amount of an antigen substance' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = "[D'ag'U]" @@ -4025,10 +4025,10 @@ class = 'chemical' names = ['D-antigen unit'] property = 'procedure defined amount of a poliomyelitis d-antigen substance' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[FEU]' @@ -4039,10 +4039,10 @@ class = 'chemical' names = ['fibrinogen equivalent unit'] property = 'amount of fibrinogen broken down into the measured d-dimers' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[ELU]' @@ -4053,10 +4053,10 @@ class = 'chemical' names = ['ELISA unit'] property = 'arbitrary ELISA unit' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = '[EU]' @@ -4067,10 +4067,10 @@ class = 'chemical' names = ['Ehrlich unit'] property = 'Ehrlich unit' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = 'Np' @@ -4082,14 +4082,14 @@ names = ['neper'] printSymbol = 'Np' property = 'level' - [unit.value] - Unit = 'ln(1 1)' - UNIT = 'LN(1 1)' +[unit.value] +Unit = 'ln(1 1)' +UNIT = 'LN(1 1)' - [unit.value.function] - name = 'ln' - value = 1 - Unit = '1' +[unit.value.function] +name = 'ln' +value = 1 +Unit = '1' [[unit]] Code = 'B' @@ -4101,14 +4101,14 @@ names = ['bel'] printSymbol = 'B' property = 'level' - [unit.value] - Unit = 'lg(1 1)' - UNIT = 'LG(1 1)' +[unit.value] +Unit = 'lg(1 1)' +UNIT = 'LG(1 1)' - [unit.value.function] - name = 'lg' - value = 1 - Unit = '1' +[unit.value.function] +name = 'lg' +value = 1 +Unit = '1' [[unit]] Code = 'B[SPL]' @@ -4120,14 +4120,14 @@ names = ['bel sound pressure'] printSymbol = 'B(SPL)' property = 'pressure level' - [unit.value] - Unit = '2lg(2 10*-5.Pa)' - UNIT = '2LG(2 10*-5.PAL)' +[unit.value] +Unit = '2lg(2 10*-5.Pa)' +UNIT = '2LG(2 10*-5.PAL)' - [unit.value.function] - name = 'lgTimes2' - value = 2 - Unit = '10*-5.Pa' +[unit.value.function] +name = 'lgTimes2' +value = 2 +Unit = '10*-5.Pa' [[unit]] Code = 'B[V]' @@ -4139,14 +4139,14 @@ names = ['bel volt'] printSymbol = 'B(V)' property = 'electric potential level' - [unit.value] - Unit = '2lg(1 V)' - UNIT = '2LG(1 V)' +[unit.value] +Unit = '2lg(1 V)' +UNIT = '2LG(1 V)' - [unit.value.function] - name = 'lgTimes2' - value = 1 - Unit = 'V' +[unit.value.function] +name = 'lgTimes2' +value = 1 +Unit = 'V' [[unit]] Code = 'B[mV]' @@ -4158,14 +4158,14 @@ names = ['bel millivolt'] printSymbol = 'B(mV)' property = 'electric potential level' - [unit.value] - Unit = '2lg(1 mV)' - UNIT = '2LG(1 MV)' +[unit.value] +Unit = '2lg(1 mV)' +UNIT = '2LG(1 MV)' - [unit.value.function] - name = 'lgTimes2' - value = 1 - Unit = 'mV' +[unit.value.function] +name = 'lgTimes2' +value = 1 +Unit = 'mV' [[unit]] Code = 'B[uV]' @@ -4177,14 +4177,14 @@ names = ['bel microvolt'] printSymbol = 'B(μV)' property = 'electric potential level' - [unit.value] - Unit = '2lg(1 uV)' - UNIT = '2LG(1 UV)' +[unit.value] +Unit = '2lg(1 uV)' +UNIT = '2LG(1 UV)' - [unit.value.function] - name = 'lgTimes2' - value = 1 - Unit = 'uV' +[unit.value.function] +name = 'lgTimes2' +value = 1 +Unit = 'uV' [[unit]] Code = 'B[10.nV]' @@ -4196,14 +4196,14 @@ names = ['bel 10 nanovolt'] printSymbol = 'B(10 nV)' property = 'electric potential level' - [unit.value] - Unit = '2lg(10 nV)' - UNIT = '2LG(10 NV)' +[unit.value] +Unit = '2lg(10 nV)' +UNIT = '2LG(10 NV)' - [unit.value.function] - name = 'lgTimes2' - value = 10 - Unit = 'nV' +[unit.value.function] +name = 'lgTimes2' +value = 10 +Unit = 'nV' [[unit]] Code = 'B[W]' @@ -4215,14 +4215,14 @@ names = ['bel watt'] printSymbol = 'B(W)' property = 'power level' - [unit.value] - Unit = 'lg(1 W)' - UNIT = 'LG(1 W)' +[unit.value] +Unit = 'lg(1 W)' +UNIT = 'LG(1 W)' - [unit.value.function] - name = 'lg' - value = 1 - Unit = 'W' +[unit.value.function] +name = 'lg' +value = 1 +Unit = 'W' [[unit]] Code = 'B[kW]' @@ -4234,14 +4234,14 @@ names = ['bel kilowatt'] printSymbol = 'B(kW)' property = 'power level' - [unit.value] - Unit = 'lg(1 kW)' - UNIT = 'LG(1 KW)' +[unit.value] +Unit = 'lg(1 kW)' +UNIT = 'LG(1 KW)' - [unit.value.function] - name = 'lg' - value = 1 - Unit = 'kW' +[unit.value.function] +name = 'lg' +value = 1 +Unit = 'kW' [[unit]] Code = 'st' @@ -4252,10 +4252,10 @@ names = ['stere'] printSymbol = 'st' property = 'volume' - [unit.value] - Unit = 'm3' - UNIT = 'M3' - value = 1 +[unit.value] +Unit = 'm3' +UNIT = 'M3' +value = 1 [[unit]] Code = 'Ao' @@ -4266,10 +4266,10 @@ names = ['Ångström'] printSymbol = 'Å' property = 'length' - [unit.value] - Unit = 'nm' - UNIT = 'NM' - value = 0.1 +[unit.value] +Unit = 'nm' +UNIT = 'NM' +value = 0.1 [[unit]] Code = 'b' @@ -4280,10 +4280,10 @@ names = ['barn'] printSymbol = 'b' property = 'action area' - [unit.value] - Unit = 'fm2' - UNIT = 'FM2' - value = 100 +[unit.value] +Unit = 'fm2' +UNIT = 'FM2' +value = 100 [[unit]] Code = 'att' @@ -4294,10 +4294,10 @@ names = ['technical atmosphere'] printSymbol = 'at' property = 'pressure' - [unit.value] - Unit = 'kgf/cm2' - UNIT = 'KGF/CM2' - value = 1 +[unit.value] +Unit = 'kgf/cm2' +UNIT = 'KGF/CM2' +value = 1 [[unit]] Code = 'mho' @@ -4308,24 +4308,24 @@ names = ['mho'] printSymbol = 'mho' property = 'electric conductance' - [unit.value] - Unit = 'S' - UNIT = 'S' - value = 1 +[unit.value] +Unit = 'S' +UNIT = 'S' +value = 1 [[unit]] Code = '[psi]' CODE = '[PSI]' isMetric = 'no' class = 'misc' -names = ['pound per sqare inch'] +names = ['pound per square inch'] printSymbol = 'psi' property = 'pressure' - [unit.value] - Unit = '[lbf_av]/[in_i]2' - UNIT = '[LBF_AV]/[IN_I]2' - value = 1 +[unit.value] +Unit = '[lbf_av]/[in_i]2' +UNIT = '[LBF_AV]/[IN_I]2' +value = 1 [[unit]] Code = 'circ' @@ -4336,10 +4336,10 @@ names = ['circle'] printSymbol = 'circ' property = 'plane angle' - [unit.value] - Unit = '[pi].rad' - UNIT = '[PI].RAD' - value = 2 +[unit.value] +Unit = '[pi].rad' +UNIT = '[PI].RAD' +value = 2 [[unit]] Code = 'sph' @@ -4350,10 +4350,10 @@ names = ['spere'] printSymbol = 'sph' property = 'solid angle' - [unit.value] - Unit = '[pi].sr' - UNIT = '[PI].SR' - value = 4 +[unit.value] +Unit = '[pi].sr' +UNIT = '[PI].SR' +value = 4 [[unit]] Code = '[car_m]' @@ -4364,10 +4364,10 @@ names = ['metric carat'] printSymbol = 'ctm' property = 'mass' - [unit.value] - Unit = 'g' - UNIT = 'G' - value = 2e-1 +[unit.value] +Unit = 'g' +UNIT = 'G' +value = 2e-1 [[unit]] Code = '[car_Au]' @@ -4378,10 +4378,10 @@ names = ['carat of gold alloys'] printSymbol = 'ctAu' property = 'mass fraction' - [unit.value] - Unit = '/24' - UNIT = '/24' - value = 1 +[unit.value] +Unit = '/24' +UNIT = '/24' +value = 1 [[unit]] Code = '[smoot]' @@ -4391,10 +4391,10 @@ class = 'misc' names = ['Smoot'] property = 'length' - [unit.value] - Unit = '[in_i]' - UNIT = '[IN_I]' - value = 67 +[unit.value] +Unit = '[in_i]' +UNIT = '[IN_I]' +value = 67 [[unit]] Code = '[m/s2/Hz^(1/2)]' @@ -4405,14 +4405,14 @@ class = 'misc' names = ['meter per square seconds per square root of hertz'] property = 'amplitude spectral density' - [unit.value] - Unit = 'sqrt(1 m2/s4/Hz)' - UNIT = 'SQRT(1 M2/S4/HZ)' +[unit.value] +Unit = 'sqrt(1 m2/s4/Hz)' +UNIT = 'SQRT(1 M2/S4/HZ)' - [unit.value.function] - name = 'sqrt' - value = 1 - Unit = 'm2/s4/Hz' +[unit.value.function] +name = 'sqrt' +value = 1 +Unit = 'm2/s4/Hz' [[unit]] Code = 'bit_s' @@ -4424,14 +4424,14 @@ names = ['bit'] printSymbol = 'bits' property = 'amount of information' - [unit.value] - Unit = 'ld(1 1)' - UNIT = 'ld(1 1)' +[unit.value] +Unit = 'ld(1 1)' +UNIT = 'ld(1 1)' - [unit.value.function] - name = 'ld' - value = 1 - Unit = '1' +[unit.value.function] +name = 'ld' +value = 1 +Unit = '1' [[unit]] Code = 'bit' @@ -4442,10 +4442,10 @@ names = ['bit'] printSymbol = 'bit' property = 'amount of information' - [unit.value] - Unit = '1' - UNIT = '1' - value = 1 +[unit.value] +Unit = '1' +UNIT = '1' +value = 1 [[unit]] Code = 'By' @@ -4456,10 +4456,10 @@ names = ['byte'] printSymbol = 'B' property = 'amount of information' - [unit.value] - Unit = 'bit' - UNIT = 'bit' - value = 8 +[unit.value] +Unit = 'bit' +UNIT = 'bit' +value = 8 [[unit]] Code = 'Bd' @@ -4470,10 +4470,10 @@ names = ['baud'] printSymbol = 'Bd' property = 'signal transmission rate' - [unit.value] - Unit = '/s' - UNIT = '/s' - value = 1 +[unit.value] +Unit = '/s' +UNIT = '/s' +value = 1 [[prefix]] Code = 'Ki' From 2768c2d92b63630f47afb536fb320c49e3f6a1d7 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Thu, 30 May 2024 10:39:31 -0700 Subject: [PATCH 79/80] NAUM-61 Fix composition::ENEGERY typo --- crates/api/CHANGELOG.md | 2 ++ crates/api/src/composition.rs | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index a5243e78..1da20efe 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -71,6 +71,8 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - _BREAKING_ NAUM-8 (Internal): Refactored `convert::ToReduced` to simplify and speed up. The potentially breaking part here is that where units of opposing dimensions (ex. `[acr_us]/m2/har`) used to reduce to the first remainder unit (ex. `[acr_us]`), they now reduce to the last. +- _BREAKING_ NAUM-57: Fixed typos in `Atom` and `Property` enum variant names. +- _BREAKING_ NAUM-61: Fixed typo in `composition::ENEGERY` constant. ### Deprecated diff --git a/crates/api/src/composition.rs b/crates/api/src/composition.rs index c1e138fe..97f6f9bc 100644 --- a/crates/api/src/composition.rs +++ b/crates/api/src/composition.rs @@ -38,7 +38,7 @@ pub const PRESSURE: Composition = Composition::new_any(None, Some(-1), None, Some(1), None, None, Some(-2)); // M.L2.T-2 -pub const ENEGERY: Composition = +pub const ENERGY: Composition = Composition::new_any(None, Some(2), None, Some(1), None, None, Some(-2)); // M.L2.T-3 From b728126a73585521d7fa814dcec097b46e23cce9 Mon Sep 17 00:00:00 2001 From: Steve Loveless Date: Thu, 30 May 2024 11:02:33 -0700 Subject: [PATCH 80/80] Bump to 0.23.0 --- crates/api/CHANGELOG.md | 2 +- crates/api/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/api/CHANGELOG.md b/crates/api/CHANGELOG.md index 1da20efe..348a04fb 100644 --- a/crates/api/CHANGELOG.md +++ b/crates/api/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [unreleased] +## [0.23.0] — 2024-05-30 ### Added diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index a2aacbd4..45b4aa4c 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wise_units" -version = "0.22.0" +version = "0.23.0" description = "Measure things using UCUM units" repository = "https://github.com/agrian-inc/wise_units" license = "MIT"