From 86e9ef74158645d5b24d1a0a4b864cf1be873abb Mon Sep 17 00:00:00 2001 From: Joona Aalto Date: Tue, 22 Sep 2026 17:58:56 +0300 Subject: [PATCH] Serialize custom workspaces using a placeholder --- CHANGELOG.md | 9 ++++ .../contact_manifolds_workspace.rs | 48 +++++++++++++------ src/query/contact_manifolds/mod.rs | 2 +- src/query/mod.rs | 3 +- 4 files changed, 46 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87f1f4f4..ec4c721d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## Unreleased + +### Modified + +- Deserializing a `ContactManifoldsWorkspace` that was serialized by a custom contact-manifolds + algorithm no longer fails with `"Cannot deserialize custom shape."`. It now yields the new + `UnknownContactManifoldsWorkspace`, which the relevant algorithm can replace with a workspace + of the correct type at its next execution. + ## 0.31.1 ### Modified diff --git a/src/query/contact_manifolds/contact_manifolds_workspace.rs b/src/query/contact_manifolds/contact_manifolds_workspace.rs index 4a558a94..2aff8b25 100644 --- a/src/query/contact_manifolds/contact_manifolds_workspace.rs +++ b/src/query/contact_manifolds/contact_manifolds_workspace.rs @@ -60,37 +60,59 @@ enum DeserializableWorkspaceData { #[cfg(feature = "serde-serialize")] impl DeserializableWorkspaceData { - pub fn into_contact_manifold_workspace(self) -> Option { + pub fn into_contact_manifold_workspace(self) -> ContactManifoldsWorkspace { match self { DeserializableWorkspaceData::TriMeshShapeContactManifoldsWorkspace(w) => { - Some(ContactManifoldsWorkspace(Box::new(w))) + ContactManifoldsWorkspace(Box::new(w)) } DeserializableWorkspaceData::HeightfieldShapeContactManifoldsWorkspace(w) => { - Some(ContactManifoldsWorkspace(Box::new(w))) + ContactManifoldsWorkspace(Box::new(w)) } DeserializableWorkspaceData::HeightfieldCompositeShapeContactManifoldsWorkspace(w) => { - Some(ContactManifoldsWorkspace(Box::new(w))) + ContactManifoldsWorkspace(Box::new(w)) } DeserializableWorkspaceData::CompositeShapeCompositeShapeContactManifoldsWorkspace( w, - ) => Some(ContactManifoldsWorkspace(Box::new(w))), + ) => ContactManifoldsWorkspace(Box::new(w)), DeserializableWorkspaceData::CompositeShapeShapeContactManifoldsWorkspace(w) => { - Some(ContactManifoldsWorkspace(Box::new(w))) + ContactManifoldsWorkspace(Box::new(w)) } DeserializableWorkspaceData::VoxelsShapeContactManifoldsWorkspace(w) => { - Some(ContactManifoldsWorkspace(Box::new(w))) + ContactManifoldsWorkspace(Box::new(w)) } DeserializableWorkspaceData::VoxelsCompositeShapeContactManifoldsWorkspace(w) => { - Some(ContactManifoldsWorkspace(Box::new(w))) + ContactManifoldsWorkspace(Box::new(w)) } DeserializableWorkspaceData::VoxelsVoxelsContactManifoldsWorkspace(w) => { - Some(ContactManifoldsWorkspace(Box::new(w))) + ContactManifoldsWorkspace(Box::new(w)) + } + // The data of a custom workspace is unknown to parry, so we fall back to a placeholder. + // This can later be overwritten by algorithms that need the workspace and know its type. + DeserializableWorkspaceData::Custom => { + ContactManifoldsWorkspace(Box::new(UnknownContactManifoldsWorkspace)) } - DeserializableWorkspaceData::Custom => None, } } } +/// A placeholder workspace used for custom workspace types unknown to parry. +/// +/// This is yielded when deserializing a custom [`ContactManifoldsWorkspace`], +/// as its data is lost during serialization. Algorithms that access the workspace +/// can replace the placeholder with the correct workspace type on their next call. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] +pub struct UnknownContactManifoldsWorkspace; + +impl WorkspaceData for UnknownContactManifoldsWorkspace { + fn as_typed_workspace_data(&self) -> TypedWorkspaceData<'_> { + TypedWorkspaceData::Custom + } + + fn clone_dyn(&self) -> Box { + Box::new(*self) + } +} + /// Data from a [`ContactManifoldsWorkspace`]. pub trait WorkspaceData: DowncastSync { /// Gets the underlying workspace as an enum. @@ -134,9 +156,7 @@ impl<'de> serde::Deserialize<'de> for ContactManifoldsWorkspace { where D: serde::Deserializer<'de>, { - use crate::serde::de::Error; - DeserializableWorkspaceData::deserialize(deserializer)? - .into_contact_manifold_workspace() - .ok_or(D::Error::custom("Cannot deserialize custom shape.")) + Ok(DeserializableWorkspaceData::deserialize(deserializer)? + .into_contact_manifold_workspace()) } } diff --git a/src/query/contact_manifolds/mod.rs b/src/query/contact_manifolds/mod.rs index 7fe44fb2..1ab300a2 100644 --- a/src/query/contact_manifolds/mod.rs +++ b/src/query/contact_manifolds/mod.rs @@ -178,7 +178,7 @@ pub use self::contact_manifolds_voxels_voxels::{ contact_manifolds_voxels_voxels, contact_manifolds_voxels_voxels_shapes, }; pub use self::contact_manifolds_workspace::{ - ContactManifoldsWorkspace, TypedWorkspaceData, WorkspaceData, + ContactManifoldsWorkspace, TypedWorkspaceData, UnknownContactManifoldsWorkspace, WorkspaceData, }; pub use self::normals_constraint::{NormalConstraints, NormalConstraintsPair}; diff --git a/src/query/mod.rs b/src/query/mod.rs index 48bd33f8..f0b3b6e8 100644 --- a/src/query/mod.rs +++ b/src/query/mod.rs @@ -29,7 +29,8 @@ pub use self::closest_points::{closest_points, ClosestPoints}; pub use self::contact::{contact, Contact}; #[cfg(feature = "alloc")] pub use self::contact_manifolds::{ - ContactManifold, ContactManifoldsWorkspace, TrackedContact, TypedWorkspaceData, WorkspaceData, + ContactManifold, ContactManifoldsWorkspace, TrackedContact, TypedWorkspaceData, + UnknownContactManifoldsWorkspace, WorkspaceData, }; pub use self::default_query_dispatcher::DefaultQueryDispatcher; pub use self::distance::{distance, ShapeDistance};