use std::borrow::Cow;
#[cfg(feature = "serde")]
use serde::{ser::{Serialize, Serializer}, de::{Deserialize, Deserializer}};
use crate::{EdgeID, NodeID};
#[derive(Clone, Debug, PartialEq)]
pub struct Edge<EData>
where
EData: Clone + 'static,
{
pub id: EdgeID,
pub source: NodeID,
pub target: NodeID,
pub data: Cow<'static, EData>,
}
impl<EData> Edge<EData>
where
EData: Clone + 'static,
{
pub fn new(id: EdgeID, source: NodeID, target: NodeID, data: EData) -> Self {
Edge {
id,
source,
target,
data: Cow::Owned(data),
}
}
pub fn setting_data(&self, data: EData) -> Self {
Edge {
id: self.id.clone(),
source: self.source.clone(),
target: self.target.clone(),
data: Cow::Owned(data),
}
}
}
#[cfg(feature = "serde")]
impl<EData> Serialize for Edge<EData>
where
EData: Clone + Serialize + 'static,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
if std::mem::size_of::<EData>() == 0 {
(&self.id, &self.source, &self.target).serialize(serializer)
} else {
(&self.id, &self.source, &self.target, &self.data).serialize(serializer)
}
}
}
#[cfg(feature = "serde")]
impl<'de, EData> Deserialize<'de> for Edge<EData>
where
EData: Clone + Deserialize<'de> + 'static + Default,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
if std::mem::size_of::<EData>() == 0 {
let (id, source, target) = <(EdgeID, NodeID, NodeID)>::deserialize(deserializer)?;
Ok(Edge::new(id, source, target, EData::default()))
} else {
let (id, source, target, data) = <(EdgeID, NodeID, NodeID, EData)>::deserialize(deserializer)?;
Ok(Edge::new(id, source, target, data))
}
}
}
#[cfg(all(test, feature = "serde", feature = "serde_json"))]
mod tests {
use crate::{eid, nid};
use super::*;
use serde_test::{assert_tokens, Token};
use std::borrow::Cow;
#[test]
fn edge_with_data_round_trip() {
let edge: Edge<i32> = Edge::<i32> {
id: eid!("EdgeID"),
source: nid!("Source"),
target: nid!("Target"),
data: Cow::Owned(42),
};
assert_tokens(
&edge,
&[
Token::Tuple { len: 4 },
Token::Str("EdgeID"),
Token::Str("Source"),
Token::Str("Target"),
Token::I32(42),
Token::TupleEnd,
],
);
let json = serde_json::to_string(&edge).unwrap();
assert_eq!(json, r#"["EdgeID","Source","Target",42]"#);
let deserialized_edge: Edge<i32> = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized_edge, edge);
}
#[test]
fn edge_with_unit_data_round_trip() {
let edge: Edge<()> = Edge {
id: eid!("EdgeID"),
source: nid!("Source"),
target: nid!("Target"),
data: Cow::Owned(()),
};
assert_tokens(
&edge,
&[
Token::Tuple { len: 3 },
Token::Str("EdgeID"),
Token::Str("Source"),
Token::Str("Target"),
Token::TupleEnd,
],
);
let json = serde_json::to_string(&edge).unwrap();
assert_eq!(json, r#"["EdgeID","Source","Target"]"#);
let deserialized_edge: Edge<()> = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized_edge, edge);
}
}