Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix string serialization for broadphase multisap #675

Merged
merged 6 commits into from
Jul 15, 2024

Conversation

Vrixyz
Copy link
Contributor

@Vrixyz Vrixyz commented Jul 9, 2024

Without that, serialization to string fails. Interesting to note bincode works without that.

error log:

thread 'main' panicked at bevy_rapier3d/examples/serialization.rs:30:51:
Unable to serialize `RapierContext`: Error("key must be a string", line: 0, column: 0)
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic in system `serialization::print_physics`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!

After more testing, I realize this crash doesn't happen every time 😮 ; around once in 10 runs 🤔.

The solution for this issue is more involved than I thought, serde json doesn't support non-string keys for Hashmap: serde-rs/json#887 ; I'm not sure what's the path forward.

Comment on lines 93 to 100
#[cfg_attr(
feature = "serde-serialize",
serde(
serialize_with = "parry::utils::hashmap::serialize_hashmap_capacity",
deserialize_with = "parry::utils::hashmap::deserialize_hashmap_capacity"
)
)]
colliders_proxy_ids: HashMap<ColliderHandle, BroadPhaseProxyIndex>,
Copy link
Member

Choose a reason for hiding this comment

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

This doesn’t look correct. serialize_hashmap_capacity serializes the hashmap as a single value (its capacity) but doesn’t actually serialize its content. So deserialization will result in an emptied collidiers_proxy_id which is invalid.

I’m surprised this breaks string serialization though. Is it failing to serialize ColliderHandle or BroadPhaseProxyIndex?

Copy link
Contributor Author

@Vrixyz Vrixyz Jul 10, 2024

Choose a reason for hiding this comment

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

It was failing on the key ; I'll dig more ; I updated the PR description

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe that's the root issue: serde-rs/json#887. I'm surprised there is not a workaround provided in the issue :(

I imagine we could serialize to Vec, and deserialize to HashMap ? But I'm not sure how that would get implemented. And where, because we should keep the same hashmap serialization logic for bincode.

Copy link
Member

@sebcrozet sebcrozet Jul 11, 2024

Choose a reason for hiding this comment

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

Mmh, yeah, I’m surprised no alternative was suggested in the serde issue.

I imagine we could serialize to Vec, and deserialize to HashMap ?

That sounds reasonable. Implementing this would be somewhat similar to de/serialize_hashmap_capacity. The serialization functions would look something like that:

/// Serializes a hash-map as a `Vec<(K, V)>`.
#[cfg(feature = "serde-serialize")]
pub fn serialize_hashmap_as_vec<S: serde::Serializer, K, V, H: std::hash::BuildHasher>(
    map: &StdHashMap<K, V, H>,
    s: S,
) -> Result<S::Ok, S::Error> {
    let hashmap_as_vec = /* convert the hashmap to a vec */;
    hashmap_as_vec.serialize(s);
}

/// Deserializes a hash-map from a `Vec<(K, V)>`.
#[cfg(feature = "serde-serialize")]
pub fn deserialize_hashmap_from_vec<
    'de,
    D: serde::Deserializer<'de>,
    K,
    V,
    H: std::hash::BuildHasher + Default,
>(
    d: D,
) -> Result<StdHashMap<K, V, H>, D::Error> {
    let hashmap_as_vec: Vec<(K, V)> = Deserialize::deserialize(deserializer)?;
    /* Convert the hashmap_as_vec to a hashmap */
}

because we should keep the same hashmap serialization logic for bincode

It’s fine if we don’t keep the same logic for bincode.

@Vrixyz Vrixyz marked this pull request as draft July 11, 2024 07:52
@Vrixyz Vrixyz marked this pull request as ready for review July 12, 2024 09:01
@Vrixyz Vrixyz requested a review from sebcrozet July 12, 2024 09:18
Copy link
Member

@sebcrozet sebcrozet left a comment

Choose a reason for hiding this comment

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

Looking good, thanks!

src/utils.rs Outdated
///
/// Useful for [`std::collections::HashMap`] with a non-string key,
/// which is unsupported by [`serde_json`].
#[cfg(feature = "serde-serialize")]
Copy link
Member

Choose a reason for hiding this comment

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

Not needed since the pub mod serde is already feature-gated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was conflicted between gating the whole mod or each functions ; gating the whole mod might give users a bit of a pain for their "use" statements, but it's not a huge annoyance, and it feels cleaner to gate the whole mod

@Vrixyz Vrixyz merged commit 6a295d3 into dimforge:master Jul 15, 2024
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants