diff --git a/editoast/.dockerignore b/editoast/.dockerignore deleted file mode 100644 index 7b388420334..00000000000 --- a/editoast/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -target -Dockerfile -.env diff --git a/editoast/Cargo.lock b/editoast/Cargo.lock index 1887495cb71..3a9449c10f9 100644 --- a/editoast/Cargo.lock +++ b/editoast/Cargo.lock @@ -798,7 +798,6 @@ dependencies = [ "tracing", "tracing-opentelemetry", "tracing-subscriber", - "uom", "url", "utoipa", ] @@ -928,6 +927,7 @@ dependencies = [ "tokio-stream", "tracing", "tracing-opentelemetry", + "unit_system", "url", "utoipa", "uuid", @@ -955,7 +955,7 @@ dependencies = [ "tokio", "tokio-stream", "tracing", - "uom", + "unit_system", "zstd 0.14.0", ] @@ -1493,7 +1493,7 @@ dependencies = [ "tower-http 0.7.1", "tracing", "tracing-subscriber", - "uom", + "unit_system", "url", "utoipa", "uuid", @@ -3085,7 +3085,7 @@ dependencies = [ "tokio", "tokio-postgres", "tracing", - "uom", + "unit_system", "url", "utoipa", "uuid", @@ -4574,7 +4574,7 @@ dependencies = [ "serde_with", "strum", "thiserror 2.0.20", - "uom", + "unit_system", "utoipa", "uuid", ] @@ -5587,6 +5587,15 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "unit_system" +version = "0.1.0" +dependencies = [ + "common", + "serde", + "uom", +] + [[package]] name = "unsafe-libyaml-norway" version = "0.2.15" diff --git a/editoast/Cargo.toml b/editoast/Cargo.toml index b1121598490..fd79050f0a4 100644 --- a/editoast/Cargo.toml +++ b/editoast/Cargo.toml @@ -150,7 +150,7 @@ tracing-opentelemetry = { version = "0.33.0", default-features = false, features "tracing-log", ] } tracing-subscriber = { version = "0.3.23", features = ["env-filter"] } -uom = { version = "0.38.0", default-features = false, features = ["f64", "si"] } +unit_system = { path = "./unit_system" } url = { version = "2.5.8", features = ["serde"] } urlencoding = "2.1.3" utoipa = { git = "https://github.com/osrd-project/utoipa.git", rev = "5103a24a6d6", features = [ @@ -250,7 +250,7 @@ tower-http = { version = "0.7", features = [ ] } tracing.workspace = true tracing-subscriber.workspace = true -uom.workspace = true +unit_system.workspace = true url.workspace = true utoipa.workspace = true uuid.workspace = true diff --git a/editoast/common/Cargo.toml b/editoast/common/Cargo.toml index 67bd758bb52..110242e31bd 100644 --- a/editoast/common/Cargo.toml +++ b/editoast/common/Cargo.toml @@ -16,7 +16,6 @@ serde_json.workspace = true tracing.workspace = true tracing-opentelemetry.workspace = true tracing-subscriber.workspace = true -uom.workspace = true url.workspace = true utoipa.workspace = true diff --git a/editoast/common/src/lib.rs b/editoast/common/src/lib.rs index 106ff7f0280..72e8e2a324f 100644 --- a/editoast/common/src/lib.rs +++ b/editoast/common/src/lib.rs @@ -2,7 +2,6 @@ pub mod geometry; mod hash_rounded_float; pub mod rangemap_utils; pub mod tracing; -pub mod units; use std::collections::HashSet; use std::hash::Hash; @@ -35,10 +34,7 @@ pub struct Version { /// Allows implementing Eq for floats considering all NaN values to be equal /// /// Tip: provide this to Educe. -pub fn float_eq(a: &V, b: &V) -> bool -where - V: uom::num_traits::Num + uom::num_traits::float::TotalOrder + uom::Conversion, -{ +pub fn float_eq(a: &f64, b: &f64) -> bool { matches!(a.total_cmp(b), std::cmp::Ordering::Equal) } diff --git a/editoast/core_client/Cargo.toml b/editoast/core_client/Cargo.toml index d7efcc650e1..81c06aab77a 100644 --- a/editoast/core_client/Cargo.toml +++ b/editoast/core_client/Cargo.toml @@ -28,6 +28,7 @@ tokio.workspace = true tokio-stream = "0.1.18" tracing.workspace = true tracing-opentelemetry.workspace = true +unit_system.workspace = true url.workspace = true utoipa.workspace = true uuid.workspace = true diff --git a/editoast/core_client/src/conflict_detection.rs b/editoast/core_client/src/conflict_detection.rs index a2fdcc976c1..3a21389bb42 100644 --- a/editoast/core_client/src/conflict_detection.rs +++ b/editoast/core_client/src/conflict_detection.rs @@ -1,7 +1,7 @@ -use common::units::quantities::Offset; use serde::Deserialize; use serde::Serialize; use std::collections::HashMap; +use unit_system::quantities::Offset; use utoipa::ToSchema; use uuid::Uuid; @@ -65,7 +65,7 @@ pub struct Conflict { /// (`trains_requirements` and `work_schedules`) and response. /// Example: `1970-01-01T00:00:00Z` for calendar timetables; the timetable start for hourly /// timetables. - #[serde(with = "common::units::millisecond::i64")] + #[serde(with = "unit_system::units::millisecond::i64")] pub start_time: Offset, /// Duration of the conflict in ms. pub duration: u64, @@ -90,7 +90,7 @@ pub struct ConflictRequirement { /// (`trains_requirements` and `work_schedules`) and response. /// Example: `1970-01-01T00:00:00Z` for calendar timetables; the timetable start for hourly /// timetables. - #[serde(with = "common::units::millisecond::i64")] + #[serde(with = "unit_system::units::millisecond::i64")] #[schema(value_type = i64)] pub start_time: Offset, /// Duration of the time range in ms (difference between the latest end time and the earliest start_time for any zone use in this conflict). diff --git a/editoast/core_client/src/simulation.rs b/editoast/core_client/src/simulation.rs index bf42bbc88c9..3f905ff9a4d 100644 --- a/editoast/core_client/src/simulation.rs +++ b/editoast/core_client/src/simulation.rs @@ -2,13 +2,6 @@ use std::collections::BTreeMap; use std::collections::HashMap; use std::hash::Hash; -use common::units; -use common::units::quantities::Acceleration; -use common::units::quantities::Deceleration; -use common::units::quantities::Length; -use common::units::quantities::Mass; -use common::units::quantities::Time; -use common::units::quantities::Velocity; use educe::Educe; use schemas::rolling_stock::EffortCurves; use schemas::rolling_stock::EtcsBrakeParams; @@ -20,6 +13,13 @@ use schemas::train_schedule::ReceptionSignal; use schemas::train_schedule::TrainScheduleOptions; use serde::Deserialize; use serde::Serialize; +use unit_system::quantities::Acceleration; +use unit_system::quantities::Deceleration; +use unit_system::quantities::Length; +use unit_system::quantities::Mass; +use unit_system::quantities::Time; +use unit_system::quantities::Velocity; +use unit_system::units; use utoipa::ToSchema; use super::RawError; diff --git a/editoast/core_task/Cargo.toml b/editoast/core_task/Cargo.toml index 5ca11f1944e..d55883c22b0 100644 --- a/editoast/core_task/Cargo.toml +++ b/editoast/core_task/Cargo.toml @@ -21,7 +21,7 @@ serde_json.workspace = true tokio.workspace = true tokio-stream.workspace = true tracing.workspace = true -uom.workspace = true +unit_system.workspace = true [dev-dependencies] cache = { workspace = true, features = ["mock"] } diff --git a/editoast/core_task/src/envs/simulation/inputs.rs b/editoast/core_task/src/envs/simulation/inputs.rs index cfb7987c786..e7691df8cb6 100644 --- a/editoast/core_task/src/envs/simulation/inputs.rs +++ b/editoast/core_task/src/envs/simulation/inputs.rs @@ -47,9 +47,9 @@ pub struct SimulationTrainParameters { power_restrictions: rangemap::RangeMap, margins: rangemap::RangeMap, - #[educe(Hash(method(common::units::meter_per_second::hash)))] - #[educe(PartialEq(method(common::units::meter_per_second::eq)))] - initial_speed: uom::si::f64::Velocity, + #[educe(Hash(method(unit_system::units::meter_per_second::hash)))] + #[educe(PartialEq(method(unit_system::units::meter_per_second::eq)))] + initial_speed: unit_system::quantities::Velocity, constraint_distribution: Distribution, comfort: Comfort, speed_limit_tag: Option, @@ -73,7 +73,7 @@ impl ScheduleItem { impl SimulationTrainParameters { pub fn new( - initial_speed: uom::si::f64::Velocity, + initial_speed: unit_system::quantities::Velocity, constraint_distribution: Distribution, comfort: Comfort, speed_limit_tag: Option, @@ -103,7 +103,7 @@ impl SimulationTrainParameters { &self.margins } - pub fn initial_speed(&self) -> uom::si::f64::Velocity { + pub fn initial_speed(&self) -> unit_system::quantities::Velocity { self.initial_speed } diff --git a/editoast/core_task/src/envs/simulation/request.rs b/editoast/core_task/src/envs/simulation/request.rs index 84bc2f39802..13c9709c9ca 100644 --- a/editoast/core_task/src/envs/simulation/request.rs +++ b/editoast/core_task/src/envs/simulation/request.rs @@ -114,9 +114,7 @@ pub(super) fn build_request( values: margin_values, }, power_restrictions, - initial_speed: params - .initial_speed() - .get::(), + initial_speed: unit_system::units::meter_per_second::from(params.initial_speed()), comfort: params.comfort(), constraint_distribution: params.constraint_distribution(), speed_limit_tag: params.speed_limit_tag().map(|s| s.to_owned()), diff --git a/editoast/editoast_derive/src/annotate_units.rs b/editoast/editoast_derive/src/annotate_units.rs index 20be746d99d..61688624cdd 100644 --- a/editoast/editoast_derive/src/annotate_units.rs +++ b/editoast/editoast_derive/src/annotate_units.rs @@ -34,13 +34,28 @@ fn get_abbreviation(value: &str) -> Option<&'static str> { "meter" => Some("Length in m"), "millimeter" => Some("Length in mm"), "meter_per_second" => Some("Velocity in m·s⁻¹"), + "kilometer_per_hour" => Some("Velocity in km·h⁻¹"), "meter_per_second_squared" => Some("Acceleration in m·s⁻²"), + "newton_per_kg" => Some("Acceleration in N·kg⁻¹"), + "newton_per_ton" => Some("Acceleration in N·t⁻¹"), "kilogram" => Some("Mass in kg"), + "ton" => Some("Mass in t"), "newton" => Some("Solid Friction in N"), + "kilonewton" => Some("Solid Friction in kN"), + "kilogram_per_second" => Some("Viscosity friction in kg·s⁻¹"), + "newton_per_meter_per_second" => Some("Viscosity friction in N·(m/s)⁻¹"), + "newton_per_kilometer_per_hour" => Some("Viscosity friction in N·(km/h)⁻¹"), "hertz" => Some("Viscosity friction per weight in s⁻¹"), + "newton_per_meter_per_second_per_kilogram" => { + Some("Viscosity friction per weight in N·(m/s)⁻¹·kg⁻¹") + } "kilogram_per_meter" => Some("Aerodynamic drag in kg·m⁻¹"), - "kilogram_per_second" => Some("Viscosity friction in kg·s⁻¹"), + "newton_per_meter_per_second_squared" => Some("Aerodynamic drag in N·(m/s)⁻²"), + "kilonewton_per_kilometer_per_hour_squared" => Some("Aerodynamic drag in kN·(km/h)⁻²"), "per_meter" => Some("Aerodynamic drag per kg in m⁻¹"), + "newton_per_meter_per_second_squared_per_kilogram" => { + Some("Aerodynamic drag per kg in N·(m/s)⁻²·kg⁻¹") + } _ => None, } } diff --git a/editoast/editoast_derive/src/lib.rs b/editoast/editoast_derive/src/lib.rs index 838c22e7c25..dcf9f06ff5b 100644 --- a/editoast/editoast_derive/src/lib.rs +++ b/editoast/editoast_derive/src/lib.rs @@ -226,7 +226,7 @@ pub fn search_config_store(input: proc_macro::TokenStream) -> proc_macro::TokenS /// * `#[model(to_string)]`: calls `to_string()` before writing the field to the database and calls `String::from` after reading (diesel column type: String) /// * `#[model(to_enum)]`: is converted as `u8` before writing the field to the database and calls `FromRepr::from_repr` after reading (diesel column type: TinyInt) /// * `#[model(remote = "T")]`: calls `Into::::into` before writing the field to the database and calls `T::from` after reading (diesel column type: T) -/// * `#[model(uom_unit = "path::to::unit")]`: the value is the path to an unit defined in common, e.g. `"common::units::meter"` +/// * `#[model(uom_unit = "path::to::unit")]`: the value is the path to an unit defined in common, e.g. `"unit_system::units::meter"` /// * `#[model(geo)]` **TODO**: TBD /// * `#[model(non_null_array = "T")]`: wraps type `T` into an `Option` when interfacing with diesel to satisfy the nullable property of postgres arrays /// diff --git a/editoast/models/Cargo.toml b/editoast/models/Cargo.toml index 7f700794982..ca567b3eddf 100644 --- a/editoast/models/Cargo.toml +++ b/editoast/models/Cargo.toml @@ -38,7 +38,7 @@ thiserror.workspace = true tokio.workspace = true tokio-postgres.workspace = true tracing.workspace = true -uom.workspace = true +unit_system.workspace = true url.workspace = true utoipa.workspace = true uuid.workspace = true diff --git a/editoast/models/src/rolling_stock.rs b/editoast/models/src/rolling_stock.rs index 18aa0316167..d4cfbf05046 100644 --- a/editoast/models/src/rolling_stock.rs +++ b/editoast/models/src/rolling_stock.rs @@ -3,13 +3,6 @@ mod power_restrictions; use std::collections::HashMap; use std::collections::HashSet; -use common::units; -use common::units::quantities::Acceleration; -use common::units::quantities::Deceleration; -use common::units::quantities::Length; -use common::units::quantities::Mass; -use common::units::quantities::Time; -use common::units::quantities::Velocity; use editoast_derive::Model; use schemas::rolling_stock::EffortCurves; use schemas::rolling_stock::EnergySource; @@ -20,6 +13,13 @@ use schemas::rolling_stock::RollingStockMetadata; use schemas::rolling_stock::SupportedSignalingSystem; use serde::Deserialize; use serde::Serialize; +use unit_system::quantities::Acceleration; +use unit_system::quantities::Deceleration; +use unit_system::quantities::Length; +use unit_system::quantities::Mass; +use unit_system::quantities::Time; +use unit_system::quantities::Velocity; +use unit_system::units; use utoipa::ToSchema; use crate::prelude::*; diff --git a/editoast/models/src/timetable.rs b/editoast/models/src/timetable.rs index 0d8d475ba61..2debf64ecd3 100644 --- a/editoast/models/src/timetable.rs +++ b/editoast/models/src/timetable.rs @@ -1,5 +1,3 @@ -use common::units::millisecond; -use common::units::quantities::Offset; use database::DatabaseError; use database::tables::sql_types; use diesel::prelude::*; @@ -15,6 +13,8 @@ use editoast_derive::Model; use itertools::Itertools as _; use std::collections::HashSet; use std::ops::DerefMut as _; +use unit_system::quantities::Offset; +use unit_system::units::millisecond; use database::DbConnection; diff --git a/editoast/models/src/towed_rolling_stock.rs b/editoast/models/src/towed_rolling_stock.rs index 5e1692ff193..8157710957a 100644 --- a/editoast/models/src/towed_rolling_stock.rs +++ b/editoast/models/src/towed_rolling_stock.rs @@ -1,13 +1,13 @@ -use common::units; -use common::units::quantities::Acceleration; -use common::units::quantities::Deceleration; -use common::units::quantities::Length; -use common::units::quantities::Mass; -use common::units::quantities::Velocity; use editoast_derive::Model; use schemas::rolling_stock::RollingResistancePerWeight; use serde::Deserialize; use serde::Serialize; +use unit_system::quantities::Acceleration; +use unit_system::quantities::Deceleration; +use unit_system::quantities::Length; +use unit_system::quantities::Mass; +use unit_system::quantities::Velocity; +use unit_system::units; use crate::prelude::*; diff --git a/editoast/models/src/train_schedule.rs b/editoast/models/src/train_schedule.rs index ee611744e5e..5c36bebedbc 100644 --- a/editoast/models/src/train_schedule.rs +++ b/editoast/models/src/train_schedule.rs @@ -2,8 +2,6 @@ use crate::prelude::*; use crate::rolling_stock::TrainMainCategory; use crate::tags::Tags; use chrono::Duration as ChronoDuration; -use common::units::millisecond; -use common::units::quantities::Offset; use derive_more::Display; use editoast_derive::Model; use itertools::Itertools as _; @@ -24,6 +22,8 @@ use schemas::train_schedule::TrainScheduleOptions; use serde::Deserialize; use serde::Serialize; use std::fmt::Display; +use unit_system::quantities::Offset; +use unit_system::units::millisecond; use utoipa::ToSchema; #[derive(Debug, Clone, Model)] @@ -37,7 +37,7 @@ pub struct TrainSchedule { pub labels: Tags, pub rolling_stock_name: String, pub train_schedule_set_id: i64, - #[model(uom_unit = "common::units::millisecond::i64")] + #[model(uom_unit = "unit_system::units::millisecond::i64")] /// For calendar timetables: elapsed ms since 1970-01-01T00:00:00Z. /// For hourly timetables: elapsed ms since the timetable start. pub start_time: Offset, @@ -504,7 +504,6 @@ mod tests { use super::OccurrenceId; use super::TrainSchedule; - use common::units::quantities::Offset; use database::DbConnectionPoolV2; use pretty_assertions::assert_eq; use rstest::rstest; @@ -512,6 +511,7 @@ mod tests { use schemas::fixtures::ms_since_epoch; use schemas::paced_train::RollingStockCategoryChangeGroup; use schemas::paced_train::StartTimeChangeGroup; + use unit_system::quantities::Offset; use crate::prelude::*; use schemas::train_schedule::Comfort; diff --git a/editoast/schemas/Cargo.toml b/editoast/schemas/Cargo.toml index 1b14468d323..92b7d05d4a4 100644 --- a/editoast/schemas/Cargo.toml +++ b/editoast/schemas/Cargo.toml @@ -23,7 +23,7 @@ serde_json.workspace = true serde_with.workspace = true strum.workspace = true thiserror.workspace = true -uom.workspace = true +unit_system.workspace = true utoipa.workspace = true uuid.workspace = true diff --git a/editoast/schemas/src/fixtures.rs b/editoast/schemas/src/fixtures.rs index c7caaca6bc3..ca70aab4293 100644 --- a/editoast/schemas/src/fixtures.rs +++ b/editoast/schemas/src/fixtures.rs @@ -4,7 +4,8 @@ use std::str::FromStr as _; use chrono::DateTime; use chrono::Utc; -use common::units; +use unit_system; +use unit_system::units; use crate::RollingStock; use crate::rolling_stock::EffortCurves; @@ -95,6 +96,6 @@ pub fn small_infra() -> crate::infra::RailJson { .expect("Unable to parse small infra RailJson") } -pub fn ms_since_epoch(s: &str) -> units::quantities::Time { +pub fn ms_since_epoch(s: &str) -> unit_system::quantities::Time { units::millisecond::i64::new(DateTime::::from_str(s).unwrap().timestamp_millis()) } diff --git a/editoast/schemas/src/paced_train.rs b/editoast/schemas/src/paced_train.rs index 4f02fc57cf7..af0735c2340 100644 --- a/editoast/schemas/src/paced_train.rs +++ b/editoast/schemas/src/paced_train.rs @@ -11,13 +11,13 @@ use crate::train_schedule::ScheduleItem; use crate::train_schedule::TrainOccurrence; use crate::train_schedule::TrainScheduleOptions; use chrono::Duration; -use common::units::quantities::Offset; use serde::Deserialize; use serde::Deserializer; use serde::Serialize; use serde_with::DefaultOnNull; use serde_with::serde_as; use serde_with::skip_serializing_none; +use unit_system::quantities::Offset; use utoipa::ToSchema; use utoipa::openapi::ObjectBuilder; use utoipa::openapi::RefOr; @@ -176,7 +176,7 @@ pub struct SpeedLimitTagChangeGroup { pub struct StartTimeChangeGroup { /// For calendar timetables: elapsed ms since 1970-01-01T00:00:00Z. /// For hourly timetables: elapsed ms since the timetable start. - #[serde(with = "common::units::millisecond::i64")] + #[serde(with = "unit_system::units::millisecond::i64")] #[schema(value_type = i64)] pub value: Offset, } diff --git a/editoast/schemas/src/primitives/time_window.rs b/editoast/schemas/src/primitives/time_window.rs index 19b0c12312d..ee30b532d4a 100644 --- a/editoast/schemas/src/primitives/time_window.rs +++ b/editoast/schemas/src/primitives/time_window.rs @@ -1,12 +1,12 @@ use super::PositiveDuration; -use common::units::quantities::Offset; use serde::Deserialize; use serde::Serialize; +use unit_system::quantities::Offset; use utoipa::ToSchema; #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, ToSchema)] pub struct TimeWindow { - #[serde(with = "common::units::millisecond::i64")] + #[serde(with = "unit_system::units::millisecond::i64")] #[schema(value_type = i64)] pub time_begin: Offset, #[schema(value_type = chrono::Duration, example = "PT5M")] diff --git a/editoast/schemas/src/rolling_stock.rs b/editoast/schemas/src/rolling_stock.rs index f4beabb7c71..c1c688e7944 100644 --- a/editoast/schemas/src/rolling_stock.rs +++ b/editoast/schemas/src/rolling_stock.rs @@ -46,15 +46,6 @@ pub use sub_category::SubCategory; pub use sub_category::SubCategoryColor; mod train_category; -pub use train_category::TrainCategory; - -use common::units; -use common::units::quantities::Acceleration; -use common::units::quantities::Deceleration; -use common::units::quantities::Length; -use common::units::quantities::Mass; -use common::units::quantities::Time; -use common::units::quantities::Velocity; use itertools::Itertools as _; use serde::Deserialize; use serde::Deserializer; @@ -62,6 +53,14 @@ use serde::Serialize; use serde::Serializer; use std::collections::HashMap; use std::collections::HashSet; +pub use train_category::TrainCategory; +use unit_system::quantities::Acceleration; +use unit_system::quantities::Deceleration; +use unit_system::quantities::Length; +use unit_system::quantities::Mass; +use unit_system::quantities::Time; +use unit_system::quantities::Velocity; +use unit_system::units; use utoipa::ToSchema; pub const ROLLING_STOCK_RAILJSON_VERSION: &str = "3.4"; @@ -194,7 +193,7 @@ impl From> for RollingStock Deserialize<'de> {} diff --git a/editoast/schemas/src/rolling_stock/towed_rolling_stock.rs b/editoast/schemas/src/rolling_stock/towed_rolling_stock.rs index 6785e7ea4b2..e925f9ee754 100644 --- a/editoast/schemas/src/rolling_stock/towed_rolling_stock.rs +++ b/editoast/schemas/src/rolling_stock/towed_rolling_stock.rs @@ -1,12 +1,12 @@ use crate::rolling_stock::default_rolling_stock_railjson_version; use super::RollingResistancePerWeight; -use common::units; -use common::units::quantities::Acceleration; -use common::units::quantities::Deceleration; -use common::units::quantities::Length; -use common::units::quantities::Mass; -use common::units::quantities::Velocity; +use unit_system::quantities::Acceleration; +use unit_system::quantities::Deceleration; +use unit_system::quantities::Length; +use unit_system::quantities::Mass; +use unit_system::quantities::Velocity; +use unit_system::units; #[editoast_derive::annotate_units] #[derive(Debug, Clone, PartialEq, serde::Deserialize, serde::Serialize, utoipa::ToSchema)] diff --git a/editoast/schemas/src/train_schedule.rs b/editoast/schemas/src/train_schedule.rs index 90822464c51..dd6c1e0367b 100644 --- a/editoast/schemas/src/train_schedule.rs +++ b/editoast/schemas/src/train_schedule.rs @@ -38,12 +38,12 @@ pub use rjs_power_restriction_range::RjsPowerRestrictionRange; use std::collections::HashMap; use std::collections::HashSet; -use common::units::quantities::Offset; use serde::Deserialize; use serde::Serialize; use serde::de::Error as SerdeError; use serde_with::DefaultOnNull; use serde_with::serde_as; +use unit_system::quantities::Offset; use utoipa::ToSchema; use crate::primitives::NonBlankString; @@ -60,7 +60,7 @@ pub struct TrainOccurrence { pub rolling_stock_name: String, /// For calendar timetables: elapsed ms since 1970-01-01T00:00:00Z. /// For hourly timetables: elapsed ms since the timetable start. - #[serde(with = "common::units::millisecond::i64")] + #[serde(with = "unit_system::units::millisecond::i64")] #[schema(value_type = i64)] pub start_time: Offset, pub path: Vec, diff --git a/editoast/src/client/import_rolling_stock.rs b/editoast/src/client/import_rolling_stock.rs index aefd221ee32..30d24649053 100644 --- a/editoast/src/client/import_rolling_stock.rs +++ b/editoast/src/client/import_rolling_stock.rs @@ -123,8 +123,8 @@ mod tests { use crate::client::generate_temp_file; - use common::units; use database::DbConnectionPoolV2; + use unit_system::units; fn get_fast_rolling_stock_schema( name: &str, diff --git a/editoast/src/client/stdcm_search_env_commands.rs b/editoast/src/client/stdcm_search_env_commands.rs index 63149653eaa..c09ac91693d 100644 --- a/editoast/src/client/stdcm_search_env_commands.rs +++ b/editoast/src/client/stdcm_search_env_commands.rs @@ -3,7 +3,6 @@ use chrono::Duration; use chrono::Utc; use clap::Args; use clap::Subcommand; -use common::units::millisecond; use database::DbConnection; use database::DbConnectionPoolV2; use models::ElectricalProfileSet; @@ -18,6 +17,7 @@ use std::collections::HashSet; use std::fs::File; use std::io::BufReader; use std::path::PathBuf; +use unit_system::units::millisecond; #[derive(Subcommand, Debug)] pub enum StdcmSearchEnvCommands { @@ -322,12 +322,12 @@ mod tests { use super::*; use chrono::DateTime; use chrono::Utc; - use common::units::quantities::Offset; use database::DbConnection; use database::DbConnectionPoolV2; use rstest::rstest; use schemas::fixtures::ms_since_epoch; use serde_json::json; + use unit_system::quantities::Offset; fn make_datetime(s: &str) -> DateTime { DateTime::parse_from_rfc3339(s).unwrap().to_utc() diff --git a/editoast/src/views/level_crossing_occupancy.rs b/editoast/src/views/level_crossing_occupancy.rs index 06ba403d13e..d866871bfd3 100644 --- a/editoast/src/views/level_crossing_occupancy.rs +++ b/editoast/src/views/level_crossing_occupancy.rs @@ -21,8 +21,6 @@ use axum::Extension; use axum::extract::Json; use axum::extract::State; use chrono::Duration; -use common::units::millisecond; -use common::units::quantities::Offset; use core_client::pathfinding::TrackRange; use core_client::simulation::ReportTrain; use editoast_derive::EditoastError; @@ -41,6 +39,8 @@ use serde::Serialize; use std::collections::HashMap; use std::collections::HashSet; use thiserror::Error; +use unit_system::quantities::Offset; +use unit_system::units::millisecond; use utoipa::ToSchema; #[derive(Debug, Error, EditoastError)] @@ -209,7 +209,12 @@ pub(in crate::views) async fn occupancy( let rolling_stock_lengths: HashMap<_, _> = rolling_stocks .into_iter() - .map(|rs| (rs.name, common::units::millimeter::from(rs.length) as u64)) + .map(|rs| { + ( + rs.name, + unit_system::units::millimeter::from(rs.length) as u64, + ) + }) .collect(); // For each occurrence + simulation result, compute level crossing occupancy and group by level crossing id diff --git a/editoast/src/views/path/pathfinding.rs b/editoast/src/views/path/pathfinding.rs index 9a7cd26b641..eaa63412e23 100644 --- a/editoast/src/views/path/pathfinding.rs +++ b/editoast/src/views/path/pathfinding.rs @@ -12,7 +12,6 @@ use axum::Extension; use axum::extract::Json; use axum::extract::Path; use axum::extract::State; -use common::units; use core_client::AsCoreRequest as _; use core_client::CoreClient; use core_client::pathfinding::PathfindingCoreResult; @@ -33,6 +32,7 @@ use serde::Deserialize; use serde::Serialize; use tracing::debug; use tracing::info; +use unit_system::units; use utoipa::ToSchema; use crate::AppState; diff --git a/editoast/src/views/rolling_stock/light.rs b/editoast/src/views/rolling_stock/light.rs index f3b6dc1da41..64cf0cbbc54 100644 --- a/editoast/src/views/rolling_stock/light.rs +++ b/editoast/src/views/rolling_stock/light.rs @@ -6,8 +6,6 @@ use axum::extract::Json; use axum::extract::Path; use axum::extract::Query; use axum::extract::State; -use common::units; -use common::units::quantities::Length; use database::DbConnection; use itertools::Itertools as _; use models::prelude::*; @@ -22,8 +20,10 @@ use schemas::rolling_stock::SupportedSignalingSystem; use serde::Serialize; use std::collections::HashMap; use std::collections::HashSet; -use uom::si::f64::Mass; -use uom::si::f64::Velocity; +use unit_system::quantities::Length; +use unit_system::quantities::Mass; +use unit_system::quantities::Velocity; +use unit_system::units; use utoipa::ToSchema; use super::RollingStockError; diff --git a/editoast/src/views/rolling_stock/towed.rs b/editoast/src/views/rolling_stock/towed.rs index ca3e50ba756..0822e9e4dff 100644 --- a/editoast/src/views/rolling_stock/towed.rs +++ b/editoast/src/views/rolling_stock/towed.rs @@ -233,8 +233,8 @@ mod tests { use super::TowedRollingStockCountList; use crate::views::test_app; use crate::views::test_app::TestApp; - use common::units; use models::TowedRollingStock; + use unit_system::units; use serde_json::json; use uuid::Uuid; diff --git a/editoast/src/views/search_journeys.rs b/editoast/src/views/search_journeys.rs index 00e4e0298d0..c6beb9b3d3e 100644 --- a/editoast/src/views/search_journeys.rs +++ b/editoast/src/views/search_journeys.rs @@ -265,7 +265,8 @@ pub(in crate::views) async fn search_journeys( .enumerate() .flat_map(|(train_schedule_index, train_schedule)| { // Timetables are only Calendar so we can use the raw start_time - let offset_ms = common::units::millisecond::i64::from(train_schedule.start_time); + let offset_ms = + unit_system::units::millisecond::i64::from(train_schedule.start_time); // avoid moving them into the filter_map closure let op_index_by_id = &op_index_by_id; diff --git a/editoast/src/views/timetable.rs b/editoast/src/views/timetable.rs index 6445bf13483..fe22a02210b 100644 --- a/editoast/src/views/timetable.rs +++ b/editoast/src/views/timetable.rs @@ -22,12 +22,6 @@ use axum::extract::Query; use axum::extract::State; use axum::http::StatusCode; use axum::response::IntoResponse; -use common::units::millisecond; -use common::units::quantities::Acceleration; -use common::units::quantities::Length; -use common::units::quantities::Mass; -use common::units::quantities::Offset; -use common::units::quantities::Velocity; use core_client::conflict_detection::TrainRequirements; use core_client::conflict_detection::TrainRequirementsById; use core_client::simulation::CompleteReportTrain; @@ -57,6 +51,12 @@ use simulation::train_simulation_ordered_batch; use thiserror::Error; use tokio::time::timeout; use train_schedule::TrainScheduleResponse; +use unit_system::quantities::Acceleration; +use unit_system::quantities::Length; +use unit_system::quantities::Mass; +use unit_system::quantities::Offset; +use unit_system::quantities::Velocity; +use unit_system::units::millisecond; use utoipa::IntoParams; use utoipa::ToSchema; @@ -744,7 +744,7 @@ impl PhysicsConsistParameters { let traction_engine_inertia = self.traction_engine.mass * self.traction_engine.inertia_coefficient; let towed_inertia = towed_mass * towed_rolling_stock.inertia_coefficient; - ((traction_engine_inertia + towed_inertia) / total_mass).into() + ((traction_engine_inertia + towed_inertia) / total_mass).value } else { self.traction_engine.inertia_coefficient } @@ -988,7 +988,6 @@ mod tests { use axum::http::StatusCode; use chrono::Duration; - use common::units; use core_client::simulation::RoutingZoneRequirement; use models::train_schedule::TrainScheduleChangeset; use pretty_assertions::assert_eq; @@ -998,6 +997,7 @@ mod tests { use schemas::train_schedule::OperationalPointPartReference; use schemas::train_schedule::PathItem; use schemas::train_schedule::ScheduleItem; + use unit_system::units; use super::*; use crate::error::InternalError; diff --git a/editoast/src/views/timetable/conflicts.rs b/editoast/src/views/timetable/conflicts.rs index 8196238e44a..54cc70ba075 100644 --- a/editoast/src/views/timetable/conflicts.rs +++ b/editoast/src/views/timetable/conflicts.rs @@ -12,14 +12,14 @@ use axum::extract::Path; use axum::extract::Query; use axum::extract::State; use chrono::Duration; -use common::units::millisecond; -use common::units::quantities::Offset; use itertools::Itertools as _; use itertools::izip; use models::prelude::*; use schemas::timetable_type::TimetableType; use serde::Deserialize; use serde::Serialize; +use unit_system::quantities::Offset; +use unit_system::units::millisecond; use utoipa::ToSchema; use crate::AppState; @@ -62,7 +62,7 @@ pub struct Conflict { /// frame in this timetable. /// Example: `1970-01-01T00:00:00Z` for calendar timetables; the timetable start for hourly /// timetables. - #[serde(with = "common::units::millisecond::i64")] + #[serde(with = "unit_system::units::millisecond::i64")] #[schema(value_type = i64)] pub start_time: Offset, /// Duration of the conflict in ms. @@ -705,8 +705,8 @@ fn get_linking_requirements( .times .last() .expect("times should not be empty"); - let target_start_time = (target_occurrence.start_time() - source_occurrence.start_time()) - .get::() as u64; + let target_start_time = + millisecond::from(target_occurrence.start_time() - source_occurrence.start_time()) as u64; let final_spacing_requirements = spacing_requirements .into_iter() @@ -771,7 +771,6 @@ mod tests { use crate::views::path::pathfinding::PathfindingResult; use authz::InfraGrant; use authz::RollingStockGrant; - use common::units; use core_client::conflict_detection::ConflictDetectionResponse; use core_client::mocking::MockingClient; use core_client::pathfinding::PathfindingResultSuccess; @@ -792,6 +791,7 @@ mod tests { use schemas::train_schedule::Comfort; use schemas::train_schedule::Margins; use schemas::train_schedule::PathItem; + use unit_system::units; fn spacing(zone: &str, begin_time: u64, end_time: u64) -> SpacingRequirement { SpacingRequirement { diff --git a/editoast/src/views/timetable/simulation.rs b/editoast/src/views/timetable/simulation.rs index af9241c4790..5ec1e5ae5a5 100644 --- a/editoast/src/views/timetable/simulation.rs +++ b/editoast/src/views/timetable/simulation.rs @@ -40,7 +40,7 @@ use std::iter; use std::sync::Arc; use tracing::Instrument as _; use tracing::info; -use uom::si::f64::Velocity; +use unit_system::units; use utoipa::ToSchema; use crate::error::InternalError; @@ -649,15 +649,10 @@ pub fn build_pathfinding_consist( .iter() .map_into() .collect(), - maximum_speed: OrderedFloat( - physics_consist_parameters - .compute_max_speed() - .get::(), - ), - length: physics_consist_parameters - .compute_length() - .get::() - .round() as u64, + maximum_speed: OrderedFloat(units::meter_per_second::from( + physics_consist_parameters.compute_max_speed(), + )), + length: units::millimeter::from(physics_consist_parameters.compute_length()).round() as u64, speed_limit_tag, } } @@ -692,7 +687,7 @@ pub fn build_simulation_train( let simulation_consist = SimulationConsist(PhysicsConsist::from(physics_consist_parameters.clone())); let simulation_train_parameters = SimulationTrainParameters::new( - Velocity::new::(*initial_speed), + units::meter_per_second::new(*initial_speed), *constraint_distribution, *comfort, speed_limit_tag diff --git a/editoast/src/views/timetable/stdcm.rs b/editoast/src/views/timetable/stdcm.rs index 9f848c7773c..5a978466431 100644 --- a/editoast/src/views/timetable/stdcm.rs +++ b/editoast/src/views/timetable/stdcm.rs @@ -28,7 +28,6 @@ use chrono::DateTime; use chrono::Duration; use chrono::Utc; use common::geometry::GeoJsonPoint; -use common::units::millisecond; use core_client::AsCoreStreaming as _; use core_client::CoreClient; use core_client::Progress; @@ -71,6 +70,7 @@ use std::sync::Arc; use thiserror::Error; use tokio::sync::mpsc; use tracing::Instrument as _; +use unit_system::units::millisecond; use utoipa::IntoParams; use utoipa::ToSchema; @@ -734,7 +734,6 @@ mod tests { use authz::RollingStockGrant; use axum::http::StatusCode; use chrono::DateTime; - use common::units; use core_client; use core_client::mocking::MockingClient; use core_client::pathfinding::TrainPath; @@ -751,16 +750,8 @@ mod tests { use schemas::train_schedule::OperationalPointReference; use schemas::train_schedule::PathItemLocation; use std::str::FromStr as _; - use uom::si::SI; - use uom::si::acceleration::meter_per_second_squared; - use uom::si::length::Length; - use uom::si::length::meter; - use uom::si::length::millimeter; - use uom::si::mass::Mass; - use uom::si::mass::kilogram; - use uom::si::velocity::Velocity; - use uom::si::velocity::kilometer_per_hour; - use uom::si::velocity::meter_per_second; + use unit_system::units; + use unit_system::units::*; use uuid::Uuid; use crate::error::InternalError; @@ -856,9 +847,9 @@ mod tests { request::ConsistConfiguration { rolling_stock_id, towed_rolling_stock_id, - total_mass: total_mass.map(Mass::new::), - total_length: total_length.map(Length::new::), - max_speed: max_speed.map(Velocity::new::), + total_mass: total_mass.map(kilogram::new), + total_length: total_length.map(meter::new), + max_speed: max_speed.map(kilometer_per_hour::new), speed_limit_tag: Some("AR120".to_string()), loading_gauge_type, } @@ -1186,28 +1177,28 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn stdcm_return_success() { - let mass = Mass::, f64>::new::(1000000.0); - let length = Length::, f64>::new::(400.0); - let maximum_speed = Velocity::, f64>::new::(30.0); + let mass = kilogram::new(1000000.0); + let length = meter::new(400.0); + let maximum_speed = kilometer_per_hour::new(30.0); let core = { let mut core = MockingClient::new(); core.stub("/pathfinding/blocks") .on_body("/rolling_stock_loading_gauge", "GLOTT") .on_body( "/rolling_stock_maximum_speed", - maximum_speed.get::(), + meter_per_second::from(maximum_speed), ) - .on_body("/rolling_stock_length", length.get::() as u64) + .on_body("/rolling_stock_length", millimeter::from(length) as u64) .response(StatusCode::OK) .json(PathfindingResult::Success(pathfinding_result_success())) .finish(); core.stub("/standalone_simulation") - .on_body("/physics_consist/length", length.get::() as u64) + .on_body("/physics_consist/length", millimeter::from(length) as u64) .on_body( "/physics_consist/max_speed", - maximum_speed.get::(), + meter_per_second::from(maximum_speed), ) - .on_body("/physics_consist/mass", mass.get::() as u64) + .on_body("/physics_consist/mass", kilogram::from(mass) as u64) .response(StatusCode::OK) .json(simulation_empty_response()) .finish(); @@ -1215,15 +1206,15 @@ mod tests { .on_body("/consist_schedule/values/0/loading_gauge_type", "GLOTT") .on_body( "/consist_schedule/values/0/physics_consist/length", - length.get::() as u64, + millimeter::from(length) as u64, ) .on_body( "/consist_schedule/values/0/physics_consist/max_speed", - maximum_speed.get::(), + meter_per_second::from(maximum_speed), ) .on_body( "/consist_schedule/values/0/physics_consist/mass", - mass.get::() as u64, + kilogram::from(mass) as u64, ) .response(StatusCode::OK) .json(core_client::stdcm::FinalEvent { @@ -1253,9 +1244,9 @@ mod tests { .await; let consist_schedule = build_single_consist(build_consist_config( rolling_stock.id, - Some(mass.get::()), - Some(length.get::()), - Some(maximum_speed.get::()), + Some(kilogram::from(mass)), + Some(meter::from(length)), + Some(kilometer_per_hour::from(maximum_speed)), Some(LoadingGaugeType::Glott), None, )); @@ -1982,39 +1973,39 @@ mod tests { async fn stdcm_with_towed_rolling_stock() { let mut core: MockingClient = MockingClient::new(); // Added masses of both the rolling stock and the towed rolling stock - let mass = Mass::, f64>::new::(950000.0); + let mass = kilogram::new(950000.0); // Added lengths of both the rolling stock and the towed rolling stock - let length = Length::, f64>::new::(430.0); + let length = meter::new(430.0); // Minimum of both the rolling stock and the towed rolling stock maximum speeds - let maximum_speed = Velocity::, f64>::new::(35.0); + let maximum_speed = meter_per_second::new(35.0); // The maximum startup acceleration of both the rolling stock and the towed rolling stock let startup_acceleration = units::meter_per_second_squared::new(0.06); // The minimum comfort acceleration of both the rolling stock and the towed rolling stock let comfort_acceleration = units::meter_per_second_squared::new(0.2); core.stub("/pathfinding/blocks") .on_body("/rolling_stock_loading_gauge", "G1") - .on_body("/rolling_stock_length", length.get::() as u64) + .on_body("/rolling_stock_length", millimeter::from(length) as u64) .on_body( "/rolling_stock_maximum_speed", - maximum_speed.get::(), + meter_per_second::from(maximum_speed), ) .response(StatusCode::OK) .json(PathfindingResult::Success(pathfinding_result_success())) .finish(); core.stub("/standalone_simulation") - .on_body("/physics_consist/length", length.get::() as u64) + .on_body("/physics_consist/length", millimeter::from(length) as u64) .on_body( "/physics_consist/max_speed", - maximum_speed.get::(), + meter_per_second::from(maximum_speed), ) - .on_body("/physics_consist/mass", mass.get::() as u64) + .on_body("/physics_consist/mass", kilogram::from(mass) as u64) .on_body( "/physics_consist/startup_acceleration", - startup_acceleration.get::(), + meter_per_second_squared::from(startup_acceleration), ) .on_body( "/physics_consist/comfort_acceleration", - comfort_acceleration.get::(), + meter_per_second_squared::from(comfort_acceleration), ) .response(StatusCode::OK) .json(simulation_empty_response()) @@ -2022,23 +2013,23 @@ mod tests { core.stub("/stdcm") .on_body( "/consist_schedule/values/0/physics_consist/length", - length.get::() as u64, + millimeter::from(length) as u64, ) .on_body( "/consist_schedule/values/0/physics_consist/max_speed", - maximum_speed.get::(), + meter_per_second::from(maximum_speed), ) .on_body( "/consist_schedule/values/0/physics_consist/mass", - mass.get::() as u64, + kilogram::from(mass) as u64, ) .on_body( "/consist_schedule/values/0/physics_consist/startup_acceleration", - startup_acceleration.get::(), + meter_per_second_squared::from(startup_acceleration), ) .on_body( "/consist_schedule/values/0/physics_consist/comfort_acceleration", - comfort_acceleration.get::(), + meter_per_second_squared::from(comfort_acceleration), ) .response(StatusCode::OK) .json(core_client::stdcm::FinalEvent { @@ -2096,9 +2087,9 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn user_with_no_grant_is_forbidden() { - let mass = Mass::, f64>::new::(1000000.0); - let length = Length::, f64>::new::(400.0); - let maximum_speed = Velocity::, f64>::new::(30.0); + let mass = kilogram::new(1000000.0); + let length = meter::new(400.0); + let maximum_speed = kilometer_per_hour::new(30.0); let app = test_app!().build(); let db_pool = app.db_pool(); let small_infra = create_small_infra(&mut db_pool.get_ok()).await; @@ -2112,9 +2103,9 @@ mod tests { .await; let consist_schedule = build_single_consist(build_consist_config( rolling_stock.id, - Some(mass.get::()), - Some(length.get::()), - Some(maximum_speed.get::()), + Some(kilogram::from(mass)), + Some(meter::from(length)), + Some(kilometer_per_hour::from(maximum_speed)), Some(LoadingGaugeType::Glott), None, )); @@ -2128,9 +2119,9 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn user_without_stdcm_role_is_forbidden() { - let mass = Mass::, f64>::new::(1000000.0); - let length = Length::, f64>::new::(400.0); - let maximum_speed = Velocity::, f64>::new::(30.0); + let mass = kilogram::new(1000000.0); + let length = meter::new(400.0); + let maximum_speed = kilometer_per_hour::new(30.0); let app = test_app!().build(); let db_pool = app.db_pool(); let small_infra = create_small_infra(&mut db_pool.get_ok()).await; @@ -2145,9 +2136,9 @@ mod tests { .await; let consist_schedule = build_single_consist(build_consist_config( rolling_stock.id, - Some(mass.get::()), - Some(length.get::()), - Some(maximum_speed.get::()), + Some(kilogram::from(mass)), + Some(meter::from(length)), + Some(kilometer_per_hour::from(maximum_speed)), Some(LoadingGaugeType::Glott), None, )); @@ -2161,9 +2152,9 @@ mod tests { #[tokio::test(flavor = "multi_thread", worker_threads = 1)] async fn user_without_infra_grant_is_forbidden() { - let mass = Mass::, f64>::new::(1000000.0); - let length = Length::, f64>::new::(400.0); - let maximum_speed = Velocity::, f64>::new::(30.0); + let mass = kilogram::new(1000000.0); + let length = meter::new(400.0); + let maximum_speed = kilometer_per_hour::new(30.0); let app = test_app!().build(); let db_pool = app.db_pool(); let small_infra = create_small_infra(&mut db_pool.get_ok()).await; @@ -2178,9 +2169,9 @@ mod tests { .await; let consist_schedule = build_single_consist(build_consist_config( rolling_stock.id, - Some(mass.get::()), - Some(length.get::()), - Some(maximum_speed.get::()), + Some(kilogram::from(mass)), + Some(meter::from(length)), + Some(kilometer_per_hour::from(maximum_speed)), Some(LoadingGaugeType::Glott), None, )); diff --git a/editoast/src/views/timetable/stdcm/request.rs b/editoast/src/views/timetable/stdcm/request.rs index 03f1155be6b..5737fd24f64 100644 --- a/editoast/src/views/timetable/stdcm/request.rs +++ b/editoast/src/views/timetable/stdcm/request.rs @@ -3,7 +3,6 @@ use std::collections::HashSet; use chrono::DateTime; use chrono::Duration; use chrono::Utc; -use common::units; use core_client::pathfinding::PathfindingInputError; use database::DbConnection; @@ -17,10 +16,8 @@ use serde::Deserialize; use serde::Deserializer; use serde::Serialize; use serde::Serializer; -use units::quantities; -use uom::si::length::meter; -use uom::si::mass::kilogram; -use uom::si::velocity::meter_per_second; +use unit_system::quantities; +use unit_system::units; use utoipa::ToSchema; use crate::error::Result; @@ -351,7 +348,7 @@ impl ConsistConfiguration { .as_ref() .map(|t| t.mass) .unwrap_or_default(); - let consist_mass = consist_mass.floor::(); + let consist_mass = consist_mass.floor::(); if let Some(request_total_mass) = self.total_mass && request_total_mass < consist_mass @@ -373,14 +370,14 @@ impl ConsistConfiguration { ) -> Result<()> { let consist_length = traction_engine.length + towed_rolling_stock.map(|t| t.length).unwrap_or_default(); - let consist_length = consist_length.floor::(); + let consist_length = consist_length.floor::(); if let Some(request_total_length) = self.total_length && request_total_length < consist_length { return Err(StdcmError::InvalidConsistLength { - expected_min: consist_length.value, - provided_consist_length: request_total_length.value, + expected_min: units::meter::from(consist_length), + provided_consist_length: units::meter::from(request_total_length), } .into()); } @@ -397,12 +394,12 @@ impl ConsistConfiguration { traction_engine.max_speed, towed_rolling_stock .and_then(|t| t.max_speed) - .unwrap_or(quantities::Velocity::new::(f64::INFINITY)), + .unwrap_or(units::meter_per_second::new(f64::INFINITY)), ); - let consist_max_speed = consist_max_speed.ceil::(); + let consist_max_speed = consist_max_speed.ceil::(); if let Some(request_max_speed) = self.max_speed - && (request_max_speed < quantities::Velocity::new::(0.0) + && (request_max_speed < units::meter_per_second::new(0.0) || request_max_speed > consist_max_speed) { return Err(StdcmError::InvalidConsistMaxSpeed { diff --git a/editoast/src/views/timetable/track_occupancy.rs b/editoast/src/views/timetable/track_occupancy.rs index 3610fff675d..982653b7778 100644 --- a/editoast/src/views/timetable/track_occupancy.rs +++ b/editoast/src/views/timetable/track_occupancy.rs @@ -1,4 +1,3 @@ -use common::units::millisecond; use core_client::pathfinding::PathfindingResultSuccess; use core_client::simulation::ReportTrain; use schemas::infra::TrackOffset; @@ -9,6 +8,7 @@ use schemas::train_schedule::PathItemLocation; use schemas::train_schedule::ScheduleItem; use serde::Deserialize; use serde::Serialize; +use unit_system::units::millisecond; use utoipa::ToSchema; use crate::views::path::operational_point_cache::OperationalPointCache; @@ -323,7 +323,6 @@ pub mod tests { use crate::views::path::pathfinding::PathfindingFailure; use crate::views::timetable::simulation::SimulationResponseSuccess; use chrono::Duration; - use common::units::millisecond; use core_client::pathfinding::PathfindingNotFound; use core_client::pathfinding::TrackRange; use core_client::simulation::CompleteReportTrain; @@ -341,6 +340,7 @@ pub mod tests { use schemas::train_schedule::OperationalPointReference; use schemas::train_schedule::ReceptionSignal; use std::collections::HashMap; + use unit_system::units::millisecond; use super::*; diff --git a/editoast/src/views/timetable/train_schedule.rs b/editoast/src/views/timetable/train_schedule.rs index 232d854b225..3d98e99c07e 100644 --- a/editoast/src/views/timetable/train_schedule.rs +++ b/editoast/src/views/timetable/train_schedule.rs @@ -16,7 +16,6 @@ use axum::extract::Path; use axum::extract::Query; use axum::extract::State; use axum::response::IntoResponse; -use common::units::millisecond; use core_client::AsCoreRequest as _; use core_client::CoreClient; use core_client::pathfinding::PathfindingInputError; @@ -55,6 +54,7 @@ use schemas::train_schedule::TrainScheduleLike as _; use serde::Deserialize; use serde::Serialize; use thiserror::Error; +use unit_system::units::millisecond; use utoipa::IntoParams; use utoipa::ToSchema; diff --git a/editoast/src/views/timetable/train_schedule_exceptions.rs b/editoast/src/views/timetable/train_schedule_exceptions.rs index 4da1ae6612e..4237efa1713 100644 --- a/editoast/src/views/timetable/train_schedule_exceptions.rs +++ b/editoast/src/views/timetable/train_schedule_exceptions.rs @@ -273,7 +273,6 @@ pub(in crate::views) async fn update( #[cfg(test)] mod tests { - use common::units::millisecond; use models; use models::TrainScheduleException; use models::prelude::Retrieve as _; @@ -283,6 +282,7 @@ mod tests { use schemas::paced_train::StartTimeChangeGroup; use schemas::paced_train::TrainNameChangeGroup; use serde_json::json; + use unit_system::units::millisecond; use crate::error::InternalError; use crate::fixtures::create_timetable_with_simple_paced_train; diff --git a/editoast/src/views/train_schedule_set.rs b/editoast/src/views/train_schedule_set.rs index 393ad95530c..19559a75143 100644 --- a/editoast/src/views/train_schedule_set.rs +++ b/editoast/src/views/train_schedule_set.rs @@ -360,12 +360,12 @@ mod tests { use crate::views::train_schedule_set::TrainScheduleSetResponse; use crate::views::train_schedule_set::TrainScheduleSetUpdateForm; use chrono::Duration; - use common::units::second; use database::DbConnection; use models::CatalogEntry; use models::TrainScheduleSet; use models::prelude::*; use reqwest::StatusCode; + use unit_system::units::second; async fn create_train_schedule_set_linked_to_catalog_entry( conn: &mut DbConnection, diff --git a/editoast/unit_system/Cargo.toml b/editoast/unit_system/Cargo.toml new file mode 100644 index 00000000000..bb499f67cdb --- /dev/null +++ b/editoast/unit_system/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "unit_system" +license.workspace = true +version.workspace = true +edition.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +common.workspace = true +serde = { workspace = true, features = ["derive"] } +uom = { version = "0.38.0", default-features = false, features = ["f64"] } + + +[lints] +workspace = true diff --git a/editoast/unit_system/src/lib.rs b/editoast/unit_system/src/lib.rs new file mode 100644 index 00000000000..9a322459b4c --- /dev/null +++ b/editoast/unit_system/src/lib.rs @@ -0,0 +1,5 @@ +#[macro_use] +extern crate uom; + +pub mod quantities; +pub mod units; diff --git a/editoast/unit_system/src/quantities.rs b/editoast/unit_system/src/quantities.rs new file mode 100644 index 00000000000..fc8cb8ab2ec --- /dev/null +++ b/editoast/unit_system/src/quantities.rs @@ -0,0 +1,66 @@ +//! Editoast System of Quantities (ESQ). Subset of the International System of Quantities (ISQ) +//! that, for now, uses the same base units (meter, kilogram, second) and only defines the +//! quantities used in Editoast. It will later allow us to change the base units in order to +//! represent any quantity that we might treat using integers instead of floats. + +// There are other base quantities defined in the ISQ, such as electric current, luminous +// intensity, thermodynamic temperature and amount of substance, but we don’t need them. +// Future quantities might need them and we will need to expand ESQ with them as required. +pub mod acceleration; +pub mod force; +pub mod frequency; +pub mod length; +pub mod linear_mass_density; +pub mod linear_number_density; +pub mod mass; +pub mod mass_rate; +pub mod time; +pub mod velocity; + +system! { + /// [Editoast System of Quantities](https://jcgm.bipm.org/vim/en/1.6.html) (ESQ). + /// + /// It only defines a subset of the quantities of the International System of Quantities + /// (ISQ) provided by uom. + /// + /// ## Generic Parameters + /// * `L`: Length dimension. + /// * `M`: Mass dimension. + /// * `T`: Time dimension. + quantities: ESQ { + /// Length, one of the base quantities in the ESQ, denoted by the symbol L. The base unit + /// for length is meter. + length: meter, L; + /// Mass, one of the base quantities in the ESQ, denoted by the symbol M. The base unit + /// for mass is kilogram. + mass: kilogram, M; + /// Time, one of the base quantities in the ESQ, denoted by the symbol T. The base unit + /// for time is the second. + time: second, T; + } + units: U { + // Base units + mod length::Length, + mod mass::Mass, + mod time::Time, + // Composed units + mod velocity::Velocity, + mod acceleration::Acceleration, + mod force::Force, + mod mass_rate::MassRate, + mod frequency::Frequency, + mod linear_mass_density::LinearMassDensity, + mod linear_number_density::LinearNumberDensity, + } +} + +ESQ!(self, f64); +// Editoast aliases for existing units +pub type Offset = Time; +pub type SolidFriction = Force; +pub type SolidFrictionPerWeight = Acceleration; +pub type Deceleration = Acceleration; +pub type ViscosityFriction = MassRate; +pub type ViscosityFrictionPerWeight = Frequency; +pub type AerodynamicDrag = LinearMassDensity; +pub type AerodynamicDragPerWeight = LinearNumberDensity; diff --git a/editoast/unit_system/src/quantities/acceleration.rs b/editoast/unit_system/src/quantities/acceleration.rs new file mode 100644 index 00000000000..40aef4495d1 --- /dev/null +++ b/editoast/unit_system/src/quantities/acceleration.rs @@ -0,0 +1,19 @@ +//! Acceleration (base unit meter per second squared, m · s⁻²). +//! +//! It has the same dimension as solid friction per weight. +//! A typical value is 0.05 m/s² for acceleration and 1 daN/t for solid friction per weight. +quantity! { + /// Acceleration (base unit meter per second squared, m · s⁻²). + quantity: Acceleration; "acceleration"; + /// Dimension of acceleration, LT⁻² (base unit meter per second squared, m · s⁻²). + dimension: ESQ< + P1, // length + Z0, // mass + N2>; // time + + units { + @meter_per_second_squared: 1.0; "m·s⁻²", "meter per second squared", "meters per second squared"; + @newton_per_kg: 1.0; "N·kg⁻¹", "newton per kilogram", "newtons per kilogram"; + @newton_per_ton: 1.0E-3; "N·t⁻¹", "newton per ton", "newtons per ton"; + } +} diff --git a/editoast/unit_system/src/quantities/force.rs b/editoast/unit_system/src/quantities/force.rs new file mode 100644 index 00000000000..8c55d8388e2 --- /dev/null +++ b/editoast/unit_system/src/quantities/force.rs @@ -0,0 +1,19 @@ +//! Force (base unit newton, kg · m · s⁻²). +//! +//! It represents the traction force of a train. +//! It has the same dimensions as solid friction (resistance to movement) also known as coefficient A. +//! A typical value is 100 kN. +quantity! { + /// Force (base unit newton, kg · m · s⁻²). + quantity: Force; "force"; + /// Dimension of force, LMT⁻² (base unit newton, kg · m · s⁻²). + dimension: ESQ< + P1, // length + P1, // mass + N2>; // time + + units { + @newton: 1.0; "N", "newton", "newtons"; + @kilonewton: 1.0E3; "kN", "kilonewton", "kilonewtons"; + } +} diff --git a/editoast/unit_system/src/quantities/frequency.rs b/editoast/unit_system/src/quantities/frequency.rs new file mode 100644 index 00000000000..9757ef12c2a --- /dev/null +++ b/editoast/unit_system/src/quantities/frequency.rs @@ -0,0 +1,18 @@ +//! Frequency (base unit hertz, s⁻¹). +//! +//! It has the same dimension as viscosity friction per weight. +//! A typical value is 0.01 daN/km/h/t or 100 mN/km/h/t. +quantity! { + /// Frequency (base unit hertz, s⁻¹). + quantity: Frequency; "frequency"; + /// Dimension of frequency, T⁻¹ (base unit hertz, s⁻¹). + dimension: ESQ< + Z0, // length + Z0, // mass + N1>; // time + + units { + @hertz: 1.0; "Hz", "hertz", "hertz"; + @newton_per_meter_per_second_per_kilogram: 1.0; "N·(m/s)⁻¹·kg⁻¹", "newton per meter per second per kilogram", "newtons per meter per second per kilogram"; + } +} diff --git a/editoast/unit_system/src/quantities/length.rs b/editoast/unit_system/src/quantities/length.rs new file mode 100644 index 00000000000..f79fb8a3126 --- /dev/null +++ b/editoast/unit_system/src/quantities/length.rs @@ -0,0 +1,15 @@ +//! Length (base unit meter, m). +quantity! { + /// Length (base unit meter, m). + quantity: Length; "length"; + /// Dimension of length, L (base unit meter, m). + dimension: ESQ< + P1, // length + Z0, // mass + Z0>; // time + + units { + @meter: 1.0; "m", "meter", "meters"; + @millimeter: 1.0E-3; "mm", "millimeter", "millimeters"; + } +} diff --git a/editoast/unit_system/src/quantities/linear_mass_density.rs b/editoast/unit_system/src/quantities/linear_mass_density.rs new file mode 100644 index 00000000000..2bd604cb1fd --- /dev/null +++ b/editoast/unit_system/src/quantities/linear_mass_density.rs @@ -0,0 +1,19 @@ +//! Linear mass density (base unit kilogram per meter, kg·m⁻¹). +//! +//! It has the same dimension as aerodynamic drag, also known as coefficient C. +//! A typical value is 0.036 daN/(km/h)². +quantity! { + /// Linear mass density (base unit kilogram per meter, kg·m⁻¹). + quantity: LinearMassDensity; "linear mass density"; + /// Dimension of linear mass density, L⁻¹M (base unit kilogram per meter, kg·m⁻¹). + dimension: ESQ< + N1, // length + P1, // mass + Z0>; // time + + units { + @kilogram_per_meter: 1.0; "kg·m⁻¹", "kilogram per meter", "kilograms per meter"; + @newton_per_meter_per_second_squared: 1.0; "N·(m/s)⁻²", "newton per meter per second squared", "newtons per meter per second squared"; + @kilonewton_per_kilometer_per_hour_squared: 12960.0; "kN·(km/h)⁻²", "kilonewton per kilometer per hour squared", "kilonewtons per kilometer per hour squared"; + } +} diff --git a/editoast/unit_system/src/quantities/linear_number_density.rs b/editoast/unit_system/src/quantities/linear_number_density.rs new file mode 100644 index 00000000000..3eb3d918a06 --- /dev/null +++ b/editoast/unit_system/src/quantities/linear_number_density.rs @@ -0,0 +1,18 @@ +//! Linear number density (base unit 1 per meter, m⁻¹). +//! +//! It has the same dimension as aerodynamic drag per weight. +//! A typical value is 0.1 N/(km/h)²/t. +quantity! { + /// Linear number density (base unit 1 per meter, m⁻¹). + quantity: LinearNumberDensity; "linear number density"; + /// Dimension of linear number density, L⁻¹ (base unit per meter, m⁻¹). + dimension: ESQ< + N1, // length + Z0, // mass + Z0>; // time + + units { + @per_meter: 1.0; "m⁻¹", "per meter", "per meter"; + @newton_per_meter_per_second_squared_per_kilogram: 1.0; "N·(m/s)⁻²·kg⁻¹", "newton per meter per second squared per kilogram", "newtons per meter per second squared per kilogram"; + } +} diff --git a/editoast/unit_system/src/quantities/mass.rs b/editoast/unit_system/src/quantities/mass.rs new file mode 100644 index 00000000000..12d83754e71 --- /dev/null +++ b/editoast/unit_system/src/quantities/mass.rs @@ -0,0 +1,15 @@ +//! Mass (base unit kilogram, kg). +quantity! { + /// Mass (base unit kilogram, kg). + quantity: Mass; "mass"; + /// Dimension of mass, M (base unit kilogram, kg). + dimension: ESQ< + Z0, // length + P1, // mass + Z0>; // time + + units { + @ton: 1.0E3; "t", "ton", "tons"; + @kilogram: 1.0; "kg", "kilogram", "kilograms"; + } +} diff --git a/editoast/unit_system/src/quantities/mass_rate.rs b/editoast/unit_system/src/quantities/mass_rate.rs new file mode 100644 index 00000000000..c0a881ccb77 --- /dev/null +++ b/editoast/unit_system/src/quantities/mass_rate.rs @@ -0,0 +1,19 @@ +//! Mass rate (base unit kilogram per second, kg · s⁻¹). +//! +//! It has the same dimension as viscosity friction. +//! A typical value is 1.6 daN/(km/h), or 5.76 daN/(m/s). +quantity! { + /// Mass rate (base unit kilogram per second, kg · s⁻¹). + quantity: MassRate; "mass rate"; + /// Dimension of mass rate, MT⁻¹ (base unit kilogram per second, kg · s⁻¹). + dimension: ESQ< + Z0, // length + P1, // mass + N1>; // time + + units { + @kilogram_per_second: 1.0; "kg·s⁻¹", "kilogram per second", "kilograms per second"; + @newton_per_meter_per_second: 1.0; "N·(m/s)⁻¹", "newton per meter per second", "newtons per meter per second"; + @newton_per_kilometer_per_hour: 3.6; "N·(km/h)⁻¹", "newton per kilometer per hour", "newtons per kilometer per hour"; + } +} diff --git a/editoast/unit_system/src/quantities/time.rs b/editoast/unit_system/src/quantities/time.rs new file mode 100644 index 00000000000..f8df906dde4 --- /dev/null +++ b/editoast/unit_system/src/quantities/time.rs @@ -0,0 +1,15 @@ +//! Time (base unit second, s). +quantity! { + /// Time (base unit second, s). + quantity: Time; "time"; + /// Dimension of time, T (base unit second, s). + dimension: ESQ< + Z0, // length + Z0, // mass + P1>; // time + + units { + @second: 1.0; "s", "second", "seconds"; + @millisecond: 1.0E-3; "ms", "millisecond", "milliseconds"; + } +} diff --git a/editoast/unit_system/src/quantities/velocity.rs b/editoast/unit_system/src/quantities/velocity.rs new file mode 100644 index 00000000000..6bb67cf79d5 --- /dev/null +++ b/editoast/unit_system/src/quantities/velocity.rs @@ -0,0 +1,15 @@ +//! Velocity (base unit meter per second, m · s⁻¹). +quantity! { + /// Velocity (base unit meter per second, m · s⁻¹). + quantity: Velocity; "velocity"; + /// Dimension of velocity, LT⁻¹ (base unit meter per second, m · s⁻¹). + dimension: ESQ< + P1, // length + Z0, // mass + N1>; // time + + units { + @kilometer_per_hour: 1000.0 / 3600.0; "km·h⁻¹", "kilometer per hour", "kilometers per hour"; + @meter_per_second: 1.0; "m·s⁻¹", "meter per second", "meters per second"; + } +} diff --git a/editoast/common/src/units.rs b/editoast/unit_system/src/units.rs similarity index 67% rename from editoast/common/src/units.rs rename to editoast/unit_system/src/units.rs index 19e88567069..80a4c05273a 100644 --- a/editoast/common/src/units.rs +++ b/editoast/unit_system/src/units.rs @@ -34,108 +34,79 @@ //! } //! ``` -/// Re-export the Quantities that are used in OSRD -pub mod quantities { - pub use uom::si::f64::Acceleration; - pub use uom::si::f64::Length; - pub use uom::si::f64::Mass; - pub use uom::si::f64::Time; - pub use uom::si::f64::Velocity; - pub type SolidFriction = uom::si::f64::Force; - pub type SolidFrictionPerWeight = uom::si::f64::Acceleration; - pub type ViscosityFriction = uom::si::f64::MassRate; - pub type ViscosityFrictionPerWeight = uom::si::f64::Frequency; - pub type AerodynamicDrag = uom::si::f64::LinearMassDensity; - pub type AerodynamicDragPerWeight = uom::si::f64::LinearNumberDensity; - pub type Deceleration = uom::si::f64::Acceleration; - pub type Offset = uom::si::f64::Time; - - pub fn quantity_eq( - a: &uom::si::Quantity, - b: &uom::si::Quantity, - ) -> bool - where - D: uom::si::Dimension + ?Sized, - U: uom::si::Units + ?Sized, - V: uom::num_traits::Num + uom::num_traits::float::TotalOrder + uom::Conversion, - { - crate::float_eq(&a.value, &b.value) - } -} - macro_rules! quantity_to_path { (Length, $unit:ident) => { - uom::si::length::$unit + crate::quantities::length::$unit }; (Velocity, $unit:ident) => { - uom::si::velocity::$unit + crate::quantities::velocity::$unit }; (Acceleration, $unit:ident) => { - uom::si::acceleration::$unit + crate::quantities::acceleration::$unit }; (Mass, $unit:ident) => { - uom::si::mass::$unit + crate::quantities::mass::$unit }; (SolidFriction, $unit:ident) => { - uom::si::force::$unit + crate::quantities::force::$unit }; (ViscosityFriction, $unit:ident) => { - uom::si::mass_rate::$unit + crate::quantities::mass_rate::$unit }; (ViscosityFrictionPerWeight, $unit:ident) => { - uom::si::frequency::$unit + crate::quantities::frequency::$unit }; (AerodynamicDrag, $unit:ident) => { - uom::si::linear_mass_density::$unit + crate::quantities::linear_mass_density::$unit }; (AerodynamicDragPerWeight, $unit:ident) => { - uom::si::linear_number_density::$unit + crate::quantities::linear_number_density::$unit }; (Time, $unit:ident) => { - uom::si::time::$unit + crate::quantities::time::$unit }; } macro_rules! define_unit { ($unit:ident, $quantity:ident) => { pub mod $unit { - use super::*; use serde::Deserialize; use serde::Deserializer; use serde::Serialize; use serde::Serializer; + pub type Quantity = $crate::quantities::$quantity; type Unit = quantity_to_path!($quantity, $unit); pub type ReprType = f64; - pub fn serialize(value: &$quantity, serializer: S) -> Result + pub fn serialize(value: &Quantity, serializer: S) -> Result where S: Serializer, { value.get::().serialize(serializer) } - pub fn deserialize<'de, D>(deserializer: D) -> Result<$quantity, D::Error> + pub fn deserialize<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { let value = ReprType::deserialize(deserializer)?; - Ok($quantity::new::(value)) + Ok(Quantity::new::(value)) } - pub fn new(value: ReprType) -> $quantity { - $quantity::new::(value) + pub fn new(value: ReprType) -> Quantity { + Quantity::new::(value) } - pub fn from(qty: $quantity) -> ReprType { + pub fn from(qty: Quantity) -> ReprType { qty.get::() } - pub fn hash(value: &$quantity, state: &mut H) { - crate::hash_float::<5, H>(&from(*value), state); + pub fn hash(value: &Quantity, state: &mut H) { + common::hash_float::<5, H>(&from(*value), state); } - pub fn eq(a: &$quantity, b: &$quantity) -> bool { - $crate::float_eq(&a.get::(), &b.get::()) + pub fn eq(a: &Quantity, b: &Quantity) -> bool { + common::float_eq(&a.get::(), &b.get::()) } pub mod option { @@ -143,7 +114,7 @@ macro_rules! define_unit { pub type ReprType = Option; pub fn serialize( - value: &Option<$quantity>, + value: &Option, serializer: S, ) -> Result where @@ -152,29 +123,29 @@ macro_rules! define_unit { value.map(|value| value.get::()).serialize(serializer) } - pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> + pub fn deserialize<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { let value = Option::deserialize(deserializer)?; - Ok(value.map(|value| $quantity::new::(value))) + Ok(value.map(|value| Quantity::new::(value))) } - pub fn new(value: ReprType) -> Option<$quantity> { - value.map(|v| $quantity::new::(v)) + pub fn new(value: ReprType) -> Option { + value.map(|v| Quantity::new::(v)) } - pub fn from(qty: Option<$quantity>) -> ReprType { + pub fn from(qty: Option) -> ReprType { qty.map(|q| q.get::()) } - pub fn hash(value: &Option<$quantity>, state: &mut H) { + pub fn hash(value: &Option, state: &mut H) { super::hash(&value.unwrap_or_default(), state); } - pub fn eq(a: &Option<$quantity>, b: &Option<$quantity>) -> bool { + pub fn eq(a: &Option, b: &Option) -> bool { match (a, b) { - (Some(a), Some(b)) => $crate::float_eq(&a.get::(), &b.get::()), + (Some(a), Some(b)) => a == b, (None, None) => true, _ => false, } @@ -184,14 +155,14 @@ macro_rules! define_unit { pub mod u64 { use super::*; - pub fn serialize(value: &$quantity, serializer: S) -> Result + pub fn serialize(value: &Quantity, serializer: S) -> Result where S: Serializer, { (value.get::() as u64).serialize(serializer) } - pub fn deserialize<'de, D>(deserializer: D) -> Result<$quantity, D::Error> + pub fn deserialize<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { @@ -203,7 +174,7 @@ macro_rules! define_unit { pub type ReprType = Option; pub fn serialize( - value: &Option<$quantity>, + value: &Option, serializer: S, ) -> Result where @@ -216,7 +187,7 @@ macro_rules! define_unit { pub fn deserialize<'de, D>( deserializer: D, - ) -> Result, D::Error> + ) -> Result, D::Error> where D: Deserializer<'de>, { @@ -229,25 +200,25 @@ macro_rules! define_unit { use super::*; pub type ReprType = i64; - pub fn serialize(value: &$quantity, serializer: S) -> Result + pub fn serialize(value: &Quantity, serializer: S) -> Result where S: Serializer, { (value.get::() as i64).serialize(serializer) } - pub fn deserialize<'de, D>(deserializer: D) -> Result<$quantity, D::Error> + pub fn deserialize<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { super::deserialize(deserializer) } - pub fn new(value: ReprType) -> $quantity { - $quantity::new::(value as f64) + pub fn new(value: ReprType) -> Quantity { + Quantity::new::(value as f64) } - pub fn from(qty: $quantity) -> ReprType { + pub fn from(qty: Quantity) -> ReprType { qty.get::() as i64 } @@ -256,7 +227,7 @@ macro_rules! define_unit { pub type ReprType = Option; pub fn serialize( - value: &Option<$quantity>, + value: &Option, serializer: S, ) -> Result where @@ -269,7 +240,7 @@ macro_rules! define_unit { pub fn deserialize<'de, D>( deserializer: D, - ) -> Result, D::Error> + ) -> Result, D::Error> where D: Deserializer<'de>, { @@ -282,16 +253,32 @@ macro_rules! define_unit { } // Any new value here must also be added in editoast_derive/src/annotate_units.rs -use quantities::*; define_unit!(meter, Length); define_unit!(millimeter, Length); define_unit!(meter_per_second, Velocity); +define_unit!(kilometer_per_hour, Velocity); define_unit!(meter_per_second_squared, Acceleration); +define_unit!(newton_per_kg, Acceleration); +define_unit!(newton_per_ton, Acceleration); define_unit!(kilogram, Mass); +define_unit!(ton, Mass); define_unit!(newton, SolidFriction); +define_unit!(kilonewton, SolidFriction); define_unit!(kilogram_per_second, ViscosityFriction); +define_unit!(newton_per_meter_per_second, ViscosityFriction); +define_unit!(newton_per_kilometer_per_hour, ViscosityFriction); define_unit!(hertz, ViscosityFrictionPerWeight); +define_unit!( + newton_per_meter_per_second_per_kilogram, + ViscosityFrictionPerWeight +); define_unit!(kilogram_per_meter, AerodynamicDrag); +define_unit!(newton_per_meter_per_second_squared, AerodynamicDrag); +define_unit!(kilonewton_per_kilometer_per_hour_squared, AerodynamicDrag); define_unit!(per_meter, AerodynamicDragPerWeight); +define_unit!( + newton_per_meter_per_second_squared_per_kilogram, + AerodynamicDragPerWeight +); define_unit!(second, Time); define_unit!(millisecond, Time);