feat(graph): make indices serializable

This commit is contained in:
Alain Emilia Anna Zscheile 2024-12-31 00:57:12 +01:00
parent 53b964b865
commit d88ba19e2b
4 changed files with 63 additions and 14 deletions

View File

@ -7,14 +7,16 @@ members = [".", "crates/*", "crates/*/fuzz"]
resolver = "2" resolver = "2"
[workspace.dependencies] [workspace.dependencies]
bimap = "0.6.3"
derive-getters = "0.5" derive-getters = "0.5"
petgraph = { git = "https://codeberg.org/topola/petgraph.git" }
rstar = "0.12" rstar = "0.12"
serde_json = "1.0" serde_json = "1.0"
spade = "2.12" spade = "2.12"
thiserror = "2.0" thiserror = "2.0"
[workspace.dependencies.bimap]
version = "0.6.3"
features = ["serde"]
[workspace.dependencies.geo-types] [workspace.dependencies.geo-types]
version = "0.7" version = "0.7"
default-features = false default-features = false
@ -25,6 +27,10 @@ version = "0.29"
default-features = false default-features = false
features = ["spade", "use-serde"] features = ["spade", "use-serde"]
[workspace.dependencies.petgraph]
git = "https://codeberg.org/topola/petgraph.git"
features = ["serde-1"]
[workspace.dependencies.serde] [workspace.dependencies.serde]
version = "1" version = "1"
features = ["derive"] features = ["derive"]

View File

@ -3,7 +3,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
use enum_dispatch::enum_dispatch; use enum_dispatch::enum_dispatch;
use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::NodeIndex;
use crate::{drawing::Drawing, graph::GetPetgraphIndex}; use crate::{drawing::Drawing, graph::GetPetgraphIndex};
@ -90,7 +89,7 @@ macro_rules! impl_loose_weight {
// TODO: This enum shouldn't exist: we shouldn't be carrying the tag around like this. Instead we // TODO: This enum shouldn't exist: we shouldn't be carrying the tag around like this. Instead we
// should be getting it from the graph when it's needed. // should be getting it from the graph when it's needed.
#[enum_dispatch(GetPetgraphIndex, MakePrimitive)] #[enum_dispatch(GetPetgraphIndex, MakePrimitive)]
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum PrimitiveIndex { pub enum PrimitiveIndex {
FixedDot(FixedDotIndex), FixedDot(FixedDotIndex),
LooseDot(LooseDotIndex), LooseDot(LooseDotIndex),

View File

@ -12,6 +12,7 @@ use petgraph::{
visit::EdgeRef, visit::EdgeRef,
Direction::{self, Incoming}, Direction::{self, Incoming},
}; };
use serde::{Deserialize, Serialize};
use crate::{ use crate::{
drawing::{ drawing::{
@ -63,7 +64,7 @@ pub enum GeometryLabel {
Compound, Compound,
} }
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)]
pub enum GenericNode<P, C> { pub enum GenericNode<P, C> {
Primitive(P), Primitive(P),
Compound(C), Compound(C),

View File

@ -9,6 +9,7 @@ use std::{
use enum_dispatch::enum_dispatch; use enum_dispatch::enum_dispatch;
use petgraph::stable_graph::NodeIndex; use petgraph::stable_graph::NodeIndex;
use serde::{Deserialize, Serialize};
pub trait MakeRef<'a, R: 'a, C> { pub trait MakeRef<'a, R: 'a, C> {
fn ref_(&self, context: &'a C) -> R; fn ref_(&self, context: &'a C) -> R;
@ -19,9 +20,14 @@ pub trait GetPetgraphIndex {
fn petgraph_index(&self) -> NodeIndex<usize>; fn petgraph_index(&self) -> NodeIndex<usize>;
} }
#[derive(Debug, Clone, Copy)] // unfortunately, as we don't want any restrictions on `W`,
// we have to implement many traits ourselves, instead of using derive macros.
#[derive(Deserialize, Serialize)]
#[serde(bound = "")]
#[serde(transparent)]
pub struct GenericIndex<W> { pub struct GenericIndex<W> {
node_index: NodeIndex<usize>, node_index: NodeIndex<usize>,
#[serde(skip)]
marker: PhantomData<W>, marker: PhantomData<W>,
} }
@ -34,22 +40,59 @@ impl<W> GenericIndex<W> {
} }
} }
impl<W> core::clone::Clone for GenericIndex<W> {
#[inline]
fn clone(&self) -> Self {
Self {
node_index: self.node_index,
marker: PhantomData,
}
}
}
impl<W> core::fmt::Debug for GenericIndex<W> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_tuple("GenericIndex")
.field(&self.node_index.index())
.finish()
}
}
impl<W> PartialEq for GenericIndex<W> {
#[inline]
fn eq(&self, oth: &Self) -> bool {
self.node_index == oth.node_index
}
}
impl<W> core::marker::Copy for GenericIndex<W> {}
impl<W> Eq for GenericIndex<W> {}
impl<W> Hash for GenericIndex<W> { impl<W> Hash for GenericIndex<W> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.node_index.hash(state) self.node_index.hash(state)
} }
} }
impl<W> PartialEq for GenericIndex<W> {
fn eq(&self, other: &Self) -> bool {
self.node_index == other.node_index
}
}
impl<W> Eq for GenericIndex<W> {}
impl<W> GetPetgraphIndex for GenericIndex<W> { impl<W> GetPetgraphIndex for GenericIndex<W> {
fn petgraph_index(&self) -> NodeIndex<usize> { fn petgraph_index(&self) -> NodeIndex<usize> {
self.node_index self.node_index
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn serializable_index() {
assert_eq!(
serde_json::to_string(&GenericIndex::<()>::new(NodeIndex::new(0))).unwrap(),
"0"
);
assert_eq!(
serde_json::from_str::<GenericIndex<()>>("0").unwrap(),
GenericIndex::new(NodeIndex::new(0))
);
}
}