1use std::{fmt::Display, str::FromStr};
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, thiserror::Error)]
6#[error("ID is empty")]
7pub struct EmptyId;
8
9macro_rules! id_type {
10 ($($name: ident),+) => { $(
11 #[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
12 #[repr(transparent)]
13 #[serde(transparent)]
14 pub struct $name(pub(self) String);
15
16 impl $name {
17 pub fn into_inner(self) -> String {
18 self.0
19 }
20
21 pub fn as_str(&self) -> &str {
22 &self.0
23 }
24 }
25
26 impl Display for $name {
27 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28 self.0.fmt(f)
29 }
30 }
31
32 impl FromStr for $name {
33 type Err = EmptyId;
34
35 fn from_str(value: &str) -> Result<Self, Self::Err> {
36 if value.is_empty() {
37 Err(EmptyId)
38 } else {
39 Ok(Self(value.to_string()))
40 }
41 }
42 }
43
44 impl TryFrom<String> for $name {
45 type Error = EmptyId;
46
47 fn try_from(value: String) -> Result<Self, Self::Error> {
48 if value.is_empty() {
49 Err(EmptyId)
50 } else {
51 Ok(Self(value))
52 }
53 }
54 }
55 )+};
56}
57
58id_type!(NodeId, EdgeId);