Skip to content

editoast: use type SupportedSignalingSystem everywhere#16982

Open
woshilapin wants to merge 2 commits into
devfrom
wsl/editoast-use-type-SupportedSignalingSystem-everywhere
Open

editoast: use type SupportedSignalingSystem everywhere#16982
woshilapin wants to merge 2 commits into
devfrom
wsl/editoast-use-type-SupportedSignalingSystem-everywhere

Conversation

@woshilapin
Copy link
Copy Markdown
Contributor

In some places, we were converting to String with no real added value. Let’s keep HashSet<SupportedSignalingSystem> everywhere, avoiding conversions.

One of the inconvenient is the implementation of Hash for some of the struct that contains it (HashSet doesn’t implement Hash). With the help of educe, we can plug a custom function to hash such a HashSet. And we consider create a bitmask of all the present variant, using the discriminant of the variant’s enum. This should be unique, even if the order of the iteration is different.

@woshilapin woshilapin requested review from hhirtz and leovalais May 29, 2026 14:21
@github-actions github-actions Bot added the area:editoast Work on Editoast Service label May 29, 2026
Comment thread editoast/schemas/Cargo.toml
Comment thread editoast/schemas/src/rolling_stock/supported_signaling_system.rs Outdated
Comment thread editoast/schemas/src/rolling_stock/supported_signaling_system.rs Outdated
@woshilapin woshilapin force-pushed the wsl/editoast-use-type-SupportedSignalingSystem-everywhere branch 2 times, most recently from c2c82f0 to 4eac28f Compare May 29, 2026 22:22
Comment on lines +40 to +44
.map(SupportedSignalingSystem::discriminant)
.map(u32::from)
// Each discriminant correspond to one specific bit of a `u64`
.map(|discriminant| 1u64.wrapping_shl(discriminant))
// Create a unique bitmask
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we really pulling a lib for 2 lines

Suggested change
.map(SupportedSignalingSystem::discriminant)
.map(u32::from)
// Each discriminant correspond to one specific bit of a `u64`
.map(|discriminant| 1u64.wrapping_shl(discriminant))
// Create a unique bitmask
.map(|system| match system {
SupportedSignalingSystem::BAL => 1 << 0,
SupportedSignalingSystem::BAPR => 1 << 1,
SupportedSignalingSystem::TVM300 => 1 << 2,
SupportedSignalingSystem::TVM430 => 1 << 3,
SupportedSignalingSystem::EtcsLevel2 { .. } => 1 << 4,
})

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not use the match expr directly like above? the discriminant only seems like an implementation detail of the hashing functions, not some property we want on supported signaling systems.

also on the variant enum you could add #[repr(u32)] then implement discriminant with self as u32

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't mind using strum for this, its already in our dep tree and used throughout the codebase. I'm not too worried about compilation times of the schema crate: it sits on top of all others and compiles almost instantly (and in parallel of other crates).

I'm fine with matching directly as well though 🤷

@woshilapin woshilapin force-pushed the wsl/editoast-use-type-SupportedSignalingSystem-everywhere branch from 20656d0 to dc89962 Compare June 2, 2026 07:55
@github-actions github-actions Bot added area:front Work on Standard OSRD Interface modules kind:api-change labels Jun 2, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Jun 2, 2026

⚠️ API changes

This Pull Request introduces some changes in the API:

  • please own it: notify or even prepare dedicated PR(s) to consumer projects

Changes in Schemas

Dear @woshilapin, please ensure the following:

@woshilapin woshilapin marked this pull request as ready for review June 2, 2026 08:04
@woshilapin woshilapin requested a review from a team as a code owner June 2, 2026 08:04
Also, on all the pathfinding API, we don’t need a full-fledge
`SupportedSignalingSystem`, but only the variant is enough (for
example, we don’t need the braking curves of ETCS). So we derive a
`SignalingSystemVariant` for those API, with the help of `strum`. It
will be used in a future commit.

Also provides hashing function that will be useful for hashing
`HashSet<SupportedSignalingSystem>` (and the corresponding `*Variant`).
We create a bitmask of all the present variants, using the discriminant
of the variant’s enum. This should be unique, even if the order of the
iteration is different.


The function that hashes a `HashSet<SupportedSignalingSystemVariant>`
is not trivial, and is supposed to respect a few properties. `proptest`
is a library that basically do controlled fuzzing, which can help assert
those properties.

Signed-off-by: Jean SIMARD <woshilapin@tuziwo.info>
In some places, we were converting to `String` with no real added value.
Let’s keep `HashSet<SupportedSignalingSystem>` everywhere, avoiding
conversions.

One of the inconvenient is the implementation of `Hash` for some of
the `struct` that contains it (`HashSet` doesn’t implement `Hash`).
With the help of `educe`, we can plug a custom function to hash such a
`HashSet`.

Signed-off-by: Jean SIMARD <woshilapin@tuziwo.info>
@woshilapin woshilapin force-pushed the wsl/editoast-use-type-SupportedSignalingSystem-everywhere branch from dc89962 to 204cb54 Compare June 2, 2026 08:40
Copy link
Copy Markdown
Member

@hhirtz hhirtz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure adding more macro is a good step towards lower compilation times though... 🤔

Comment on lines +39 to +40
#[strum_discriminants(strum(to_string = "ETCS_LEVEL2"))]
#[strum_discriminants(serde(rename = "ETCS_LEVEL2"))]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just a comment but im not a fan of these kind of attribute macros, since it slows down compilation and linting and doesn't really make the code easier to read than plainly writing the into::<str>() functions.

Comment on lines +40 to +44
.map(SupportedSignalingSystem::discriminant)
.map(u32::from)
// Each discriminant correspond to one specific bit of a `u64`
.map(|discriminant| 1u64.wrapping_shl(discriminant))
// Create a unique bitmask
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not use the match expr directly like above? the discriminant only seems like an implementation detail of the hashing functions, not some property we want on supported signaling systems.

also on the variant enum you could add #[repr(u32)] then implement discriminant with self as u32

Copy link
Copy Markdown
Contributor

@leovalais leovalais left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Comment on lines +178 to +184
let same_signaling_system= a == b;
let hash_a = hash(&HashSet::from([a]));
let hash_b = hash(&HashSet::from([b]));
if same_signaling_system {
assert_eq!(hash_a, hash_b);
} else {
assert_ne!(hash_a , hash_b);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let same_signaling_system= a == b;
let hash_a = hash(&HashSet::from([a]));
let hash_b = hash(&HashSet::from([b]));
if same_signaling_system {
assert_eq!(hash_a, hash_b);
} else {
assert_ne!(hash_a , hash_b);
let same_signaling_system = a == b;
let hash_a = hash(&HashSet::from([a]));
let hash_b = hash(&HashSet::from([b]));
if same_signaling_system {
assert_eq!(hash_a, hash_b);
} else {
assert_ne!(hash_a, hash_b);

I guess rustfmt doesn't work well here... :/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:editoast Work on Editoast Service area:front Work on Standard OSRD Interface modules kind:api-change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants