wolf_graph/details/
node.rs1use std::{borrow::Cow, sync::{Arc, RwLock}};
2
3#[cfg(feature = "serde")]
4use serde::{ser::{Serialize, Serializer}, de::{Deserialize, Deserializer}};
5
6use crate::{EdgeID, Edges, NodeID};
7
8#[derive(Debug, Clone)]
9pub struct Node<NData>
10where
11 NData: Clone + 'static,
12{
13 pub id: NodeID,
14 pub in_edges: Arc<RwLock<Edges>>,
15 pub out_edges: Arc<RwLock<Edges>>,
16 pub data: Cow<'static, NData>,
17}
18
19impl<NData> Node<NData>
20where
21 NData: Clone + 'static,
22{
23 pub fn new(id: NodeID, data: NData) -> Self {
24 Node {
25 id,
26 in_edges: Arc::new(RwLock::new(Edges::new())),
27 out_edges: Arc::new(RwLock::new(Edges::new())),
28 data: Cow::Owned(data),
29 }
30 }
31
32 pub fn setting_data(&self, data: NData) -> Self {
33 Node {
34 id: self.id.clone(),
35 in_edges: self.in_edges.clone(),
36 out_edges: self.out_edges.clone(),
37 data: Cow::Owned(data),
38 }
39 }
40
41 fn _update_in_edges(&mut self, f: impl FnOnce(&mut Edges)) {
42 let mut in_edges = self.in_edges.write().unwrap().clone();
43 f(&mut in_edges);
44 self.in_edges = Arc::new(RwLock::new(in_edges));
45 }
46
47 fn _update_out_edges(&mut self, f: impl FnOnce(&mut Edges)) {
48 let mut out_edges = self.out_edges.write().unwrap().clone();
49 f(&mut out_edges);
50 self.out_edges = Arc::new(RwLock::new(out_edges));
51 }
52
53 pub fn inserting_in_edge(&self, edge_id: EdgeID) -> Self {
54 let mut new_self = self.clone();
55 new_self._update_in_edges(|in_edges| {
56 in_edges.insert(edge_id);
57 });
58 new_self
59 }
60
61 pub fn removing_in_edge(&self, edge_id: &EdgeID) -> Self {
62 let mut new_self = self.clone();
63 new_self._update_in_edges(|in_edges| {
64 in_edges.remove(edge_id);
65 });
66 new_self
67 }
68
69 pub fn inserting_out_edge(&self, edge_id: EdgeID) -> Self {
70 let mut new_self = self.clone();
71 new_self._update_out_edges(|out_edges| {
72 out_edges.insert(edge_id);
73 });
74 new_self
75 }
76
77 pub fn removing_out_edge(&self, edge_id: &EdgeID) -> Self {
78 let mut new_self = self.clone();
79 new_self._update_out_edges(|out_edges| {
80 out_edges.remove(edge_id);
81 });
82 new_self
83 }
84}
85
86impl<NData> PartialEq for Node<NData>
87where
88 NData: Clone + PartialEq + 'static,
89{
90 fn eq(&self, other: &Self) -> bool {
91 self.id == other.id && self.data == other.data
95 }
96}
97
98#[cfg(feature = "serde")]
99impl<NData> Serialize for Node<NData>
100where
101 NData: Clone + Serialize + 'static,
102{
103 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
104 where
105 S: Serializer,
106 {
107 if std::mem::size_of::<NData>() == 0 {
109 self.id.serialize(serializer)
110 } else {
111 (&self.id, &self.data).serialize(serializer)
113 }
114 }
115}
116
117#[cfg(feature = "serde")]
118impl<'de, NData> Deserialize<'de> for Node<NData>
119where
120 NData: Clone + Deserialize<'de> + 'static + Default,
121{
122 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
123 where
124 D: Deserializer<'de>,
125 {
126 if std::mem::size_of::<NData>() == 0 {
127 let node_id = NodeID::deserialize(deserializer)?;
128 Ok(Node::new(node_id, NData::default()))
129 } else {
130 let (node_id, data) = <(NodeID, NData)>::deserialize(deserializer)?;
131 Ok(Node::new(node_id, data))
132 }
133 }
134}
135
136#[cfg(all(test, feature = "serde", feature = "serde_json"))]
137mod tests {
138 use crate::nid;
139
140 use super::*;
141 use serde_test::{Token, assert_tokens, Configure};
142
143 #[test]
144 fn node_with_data_round_trip() {
145 let node: Node<i32> = Node::new(nid!("NodeA"), 99);
146
147 assert_tokens(
148 &node.compact(),
149 &[
150 Token::Tuple { len: 2 },
151 Token::Str("NodeA"),
152 Token::I32(99),
153 Token::TupleEnd,
154 ],
155 );
156 }
157
158 #[test]
159 fn node_with_unit_data_round_trip() {
160 let node: Node<()> = Node::new(nid!("NodeB"), ());
161
162 assert_tokens(
163 &node.compact(),
164 &[
165 Token::Str("NodeB"),
166 ],
167 );
168 }
169
170 #[test]
171 fn node_with_data_json_round_trip() {
172 let node: Node<i32> = Node::new(nid!("NodeA"), 99);
173 let json = serde_json::to_string(&node).unwrap();
174 assert_eq!(json, r#"["NodeA",99]"#);
175
176 let deserialized_node: Node<i32> = serde_json::from_str(&json).unwrap();
177 assert_eq!(deserialized_node, node);
178 }
179
180 #[test]
181 fn node_with_unit_data_json_round_trip() {
182 let node: Node<()> = Node::new(nid!("NodeB"), ());
183
184 let json = serde_json::to_string(&node).unwrap();
185 assert_eq!(json, r#""NodeB""#);
186
187 let deserialized_node: Node<()> = serde_json::from_str(&json).unwrap();
188 assert_eq!(deserialized_node, node);
189 }
190}