wolf_graph/
ids.rs

1use core::fmt;
2use std::{str::FromStr, sync::Arc};
3#[cfg(feature = "serde")]
4use serde::{de, Deserialize, Deserializer, Serialize};
5
6use anyhow::Result;
7
8use fuid::Fuid;
9
10/// A unique identifier for a node in a graph.
11#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub struct NodeID(Arc<String>);
13
14impl NodeID {
15    /// Creates a new, random NodeID.
16    pub fn new() -> NodeID {
17        NodeID(Arc::new(Fuid::new().to_string()))
18    }
19
20    /// Creates a new EdgeID from the given string. FUID-compatible strings may
21    /// include numerals and upper and lower case English letters.
22    pub fn with_str(s: &str) -> Result<NodeID> {
23        Ok(NodeID(Arc::new(s.to_string())))
24    }
25
26    /// Creates a new NodeID from the given u128.
27    pub fn with_u128(i: u128) -> NodeID {
28        NodeID(Arc::new(i.to_string()))
29    }
30
31    pub fn as_str(&self) -> &str {
32        self.0.as_str()
33    }
34}
35
36impl Default for NodeID {
37    fn default() -> Self {
38        Self::new()
39    }
40}
41
42impl fmt::Display for NodeID {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        write!(f, "{}", self.0)
45    }
46}
47
48impl fmt::Debug for NodeID {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        f.debug_tuple("NodeID")
51            .field(&self.to_string())
52            .finish()
53    }
54}
55
56impl FromStr for NodeID {
57    type Err = anyhow::Error;
58
59    fn from_str(s: &str) -> Result<Self> {
60        NodeID::with_str(s)
61    }
62}
63
64impl From<&str> for NodeID {
65    fn from(val: &str) -> Self {
66        NodeID::with_str(val).unwrap()
67    }
68}
69
70impl From<String> for NodeID {
71    fn from(val: String) -> Self {
72        NodeID::with_str(&val).unwrap()
73    }
74}
75
76impl From<NodeID> for String {
77    fn from(val: NodeID) -> Self {
78        val.to_string()
79    }
80}
81
82impl From<&NodeID> for String {
83    fn from(val: &NodeID) -> Self {
84        val.to_string()
85    }
86}
87
88impl From<u128> for NodeID {
89    fn from(val: u128) -> Self {
90        NodeID::with_u128(val)
91    }
92}
93
94impl AsRef<NodeID> for NodeID {
95    fn as_ref(&self) -> &NodeID {
96        self
97    }
98}
99
100#[cfg(feature = "serde")]
101impl Serialize for NodeID {
102    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
103        serializer.serialize_str(&self.to_string())
104    }
105}
106
107#[cfg(feature = "serde")]
108impl<'de> Deserialize<'de> for NodeID {
109    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
110        let s = String::deserialize(deserializer)?;
111        NodeID::with_str(&s).map_err(de::Error::custom)
112    }
113}
114
115/// A unique identifier for an edge in a graph.
116#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
117pub struct EdgeID(Arc<String>);
118
119impl EdgeID {
120    /// Creates a new, random EdgeID.
121    pub fn new() -> EdgeID {
122        EdgeID(Arc::new(Fuid::new().to_string()))
123    }
124
125    /// Creates a new EdgeID from the given string. FUID-compatible strings may
126    /// include numerals and upper and lower case English letters.
127    pub fn with_str(s: &str) -> Result<EdgeID> {
128        Ok(EdgeID(Arc::new(s.to_string())))
129    }
130
131    /// Creates a new EdgeID from the given u128.
132    pub fn with_u128(i: u128) -> EdgeID {
133        EdgeID(Arc::new(i.to_string()))
134    }
135
136    pub fn as_str(&self) -> &str {
137        self.0.as_str()
138    }
139}
140
141impl Default for EdgeID {
142    fn default() -> Self {
143        Self::new()
144    }
145}
146
147impl fmt::Display for EdgeID {
148    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
149        write!(f, "{}", self.0)
150    }
151}
152
153impl fmt::Debug for EdgeID {
154    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155        f.debug_tuple("EdgeID")
156            .field(&self.to_string())
157            .finish()
158    }
159}
160
161impl FromStr for EdgeID {
162    type Err = anyhow::Error;
163
164    fn from_str(s: &str) -> Result<Self> {
165        EdgeID::with_str(s)
166    }
167}
168
169impl From<&str> for EdgeID {
170    fn from(val: &str) -> Self {
171        EdgeID::with_str(val).unwrap()
172    }
173}
174
175impl From<String> for EdgeID {
176    fn from(val: String) -> Self {
177        EdgeID::with_str(&val).unwrap()
178    }
179}
180
181impl From<EdgeID> for String {
182    fn from(val: EdgeID) -> Self {
183        val.to_string()
184    }
185}
186
187impl From<&EdgeID> for String {
188    fn from(val: &EdgeID) -> Self {
189        val.to_string()
190    }
191}
192
193impl From<u128> for EdgeID {
194    fn from(val: u128) -> Self {
195        EdgeID::with_u128(val)
196    }
197}
198
199impl AsRef<EdgeID> for EdgeID {
200    fn as_ref(&self) -> &EdgeID {
201        self
202    }
203}
204
205#[cfg(feature = "serde")]
206impl Serialize for EdgeID {
207    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
208        serializer.serialize_str(&self.to_string())
209    }
210}
211
212#[cfg(feature = "serde")]
213impl<'de> Deserialize<'de> for EdgeID {
214    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
215        let s = String::deserialize(deserializer)?;
216        EdgeID::with_str(&s).map_err(de::Error::custom)
217    }
218}
219
220#[cfg(test)]
221
222mod tests {
223    use super::*;
224
225    #[test]
226    fn test_node_id() -> Result<(), Box<dyn std::error::Error>> {
227        let a = "6fTiplVKIi6bJFe8rTXPcu";
228        let b = "5z1JeaxqBJ4Y3pEXh2B8Sj";
229
230        let fa = NodeID::with_str(a)?;
231        let fb = NodeID::with_str(b)?;
232
233        assert_eq!(fa.to_string(), a);
234        assert_eq!(fb.to_string(), b);
235
236        assert_ne!(NodeID::new(), fa);
237        assert_ne!(NodeID::new(), fb);
238
239        let _: NodeID = "A".into();
240        let _: NodeID = "A".to_string().into();
241        let _: NodeID = 1.into();
242
243        Ok(())
244    }
245
246    #[cfg(feature = "serde")]
247    #[test]
248    fn test_node_id_serde() -> Result<(), Box<dyn std::error::Error>> {
249        use serde_json::{to_string, from_str};
250
251        let a = NodeID::new();
252        let b = to_string(&a)?;
253        // println!("{}", b);
254        let c: NodeID = from_str(&b)?;
255        assert_eq!(a, c);
256
257        Ok(())
258    }
259
260    #[test]
261    fn test_edge_id() -> Result<(), Box<dyn std::error::Error>> {
262        let a = "6fTiplVKIi6bJFe8rTXPcu";
263        let b = "5z1JeaxqBJ4Y3pEXh2B8Sj";
264
265        let fa = EdgeID::with_str(a)?;
266        let fb = EdgeID::with_str(b)?;
267
268        assert_eq!(fa.to_string(), a);
269        assert_eq!(fb.to_string(), b);
270
271        assert_ne!(EdgeID::new(), fa);
272        assert_ne!(EdgeID::new(), fb);
273
274        let _: EdgeID = "A".into();
275        let _: EdgeID = "A".to_string().into();
276        let _: EdgeID = 1.into();
277
278        Ok(())
279    }
280
281    #[cfg(feature = "serde")]
282    #[test]
283    fn test_edge_id_serde() -> Result<(), Box<dyn std::error::Error>> {
284        use serde_json::{to_string, from_str};
285
286        let a = EdgeID::new();
287        let b = to_string(&a)?;
288        // println!("{}", b);
289        let c: EdgeID = from_str(&b)?;
290        assert_eq!(a, c);
291
292        Ok(())
293    }
294}