diff options
| author | Thierry Berger <contact@thierryberger.com> | 2024-07-15 14:39:56 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-15 14:39:56 +0200 |
| commit | 6a295d3e8e372390174cc5b3e286631eb47495c1 (patch) | |
| tree | 73c42fa0f5fa79589dfa2f4494e24d3d65336e4c /src | |
| parent | 685dc1729d066af1b1a71a6536d9c35af9503d00 (diff) | |
| download | rapier-6a295d3e8e372390174cc5b3e286631eb47495c1.tar.gz rapier-6a295d3e8e372390174cc5b3e286631eb47495c1.tar.bz2 rapier-6a295d3e8e372390174cc5b3e286631eb47495c1.zip | |
Fix string serialization for broadphase multisap (#675)
Diffstat (limited to 'src')
| -rw-r--r-- | src/geometry/broad_phase_multi_sap/broad_phase_multi_sap.rs | 7 | ||||
| -rw-r--r-- | src/utils.rs | 72 |
2 files changed, 79 insertions, 0 deletions
diff --git a/src/geometry/broad_phase_multi_sap/broad_phase_multi_sap.rs b/src/geometry/broad_phase_multi_sap/broad_phase_multi_sap.rs index 87b2269..1d0f2a4 100644 --- a/src/geometry/broad_phase_multi_sap/broad_phase_multi_sap.rs +++ b/src/geometry/broad_phase_multi_sap/broad_phase_multi_sap.rs @@ -90,6 +90,13 @@ pub struct BroadPhaseMultiSap { // Another alternative would be to remove ColliderProxyId and // just use a Coarena. But this seems like it could use too // much memory. + #[cfg_attr( + feature = "serde-serialize", + serde( + serialize_with = "crate::utils::serde::serialize_to_vec_tuple", + deserialize_with = "crate::utils::serde::deserialize_from_vec_tuple" + ) + )] colliders_proxy_ids: HashMap<ColliderHandle, BroadPhaseProxyIndex>, #[cfg_attr(feature = "serde-serialize", serde(skip))] region_pool: SAPRegionPool, // To avoid repeated allocations. diff --git a/src/utils.rs b/src/utils.rs index 102c85f..84acb21 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -667,3 +667,75 @@ pub fn smallest_abs_diff_between_angles<N: SimdRealCopy>(a: N, b: N) -> N { let s_err_is_smallest = s_err.simd_abs().simd_lt(s_err_complement.simd_abs()); s_err.select(s_err_is_smallest, s_err_complement) } + +/// Helpers around serialization. +#[cfg(feature = "serde-serialize")] +pub mod serde { + use serde::{Deserialize, Serialize}; + use std::iter::FromIterator; + + /// Serializes to a `Vec<(K, V)>`. + /// + /// Useful for [`std::collections::HashMap`] with a non-string key, + /// which is unsupported by [`serde_json`]. + pub fn serialize_to_vec_tuple< + 'a, + S: serde::Serializer, + T: IntoIterator<Item = (&'a K, &'a V)>, + K: Serialize + 'a, + V: Serialize + 'a, + >( + target: T, + s: S, + ) -> Result<S::Ok, S::Error> { + let container: Vec<_> = target.into_iter().collect(); + serde::Serialize::serialize(&container, s) + } + + /// Deserializes from a `Vec<(K, V)>`. + /// + /// Useful for [`std::collections::HashMap`] with a non-string key, + /// which is unsupported by [`serde_json`]. + pub fn deserialize_from_vec_tuple< + 'de, + D: serde::Deserializer<'de>, + T: FromIterator<(K, V)>, + K: Deserialize<'de>, + V: Deserialize<'de>, + >( + d: D, + ) -> Result<T, D::Error> { + let hashmap_as_vec: Vec<(K, V)> = Deserialize::deserialize(d)?; + Ok(T::from_iter(hashmap_as_vec)) + } + + #[cfg(test)] + mod test { + use std::collections::HashMap; + + /// This test uses serde_json because json doesn't support non string + /// keys in hashmaps, which requires a custom serialization. + #[test] + fn serde_json_hashmap() { + #[derive(Serialize, Deserialize, PartialEq, Eq, Debug)] + struct Test { + #[cfg_attr( + feature = "serde-serialize", + serde( + serialize_with = "crate::utils::serde::serialize_to_vec_tuple", + deserialize_with = "crate::utils::serde::deserialize_from_vec_tuple" + ) + )] + pub map: HashMap<usize, String>, + } + + let s = Test { + map: [(42, "Forty-Two".to_string())].into(), + }; + let j = serde_json::to_string(&s).unwrap(); + assert_eq!(&j, "{\"map\":[[42,\"Forty-Two\"]]}"); + let p: Test = serde_json::from_str(&j).unwrap(); + assert_eq!(&p, &s); + } + } +} |
