Skip to main content

igc_net/
id.rs

1use std::borrow::Borrow;
2use std::fmt;
3use std::ops::Deref;
4use std::str::FromStr;
5
6use serde::{Deserialize, Deserializer, Serialize, Serializer};
7
8use crate::util::is_lower_hex_64;
9
10#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)]
11pub enum IdentifierError {
12    #[error("invalid blake3 hex (expected 64 lowercase hex chars): {0:?}")]
13    Blake3Hex(String),
14    #[error("invalid node ID hex (expected 64 lowercase hex chars): {0:?}")]
15    NodeIdHex(String),
16}
17
18#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
19pub struct Blake3Hex(String);
20
21impl Blake3Hex {
22    pub fn parse(value: impl Into<String>) -> Result<Self, IdentifierError> {
23        let value = value.into();
24        if is_lower_hex_64(&value) {
25            Ok(Self(value))
26        } else {
27            Err(IdentifierError::Blake3Hex(value))
28        }
29    }
30
31    pub fn as_str(&self) -> &str {
32        &self.0
33    }
34
35    pub fn into_string(self) -> String {
36        self.0
37    }
38
39    pub fn from_hash(hash: blake3::Hash) -> Self {
40        Self(hex::encode(hash.as_bytes()))
41    }
42
43    pub fn from_bytes(bytes: &[u8; 32]) -> Self {
44        Self(hex::encode(bytes))
45    }
46}
47
48impl fmt::Display for Blake3Hex {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        self.0.fmt(f)
51    }
52}
53
54impl Deref for Blake3Hex {
55    type Target = str;
56
57    fn deref(&self) -> &Self::Target {
58        self.as_str()
59    }
60}
61
62impl Borrow<str> for Blake3Hex {
63    fn borrow(&self) -> &str {
64        self.as_str()
65    }
66}
67
68impl FromStr for Blake3Hex {
69    type Err = IdentifierError;
70
71    fn from_str(s: &str) -> Result<Self, Self::Err> {
72        Self::parse(s)
73    }
74}
75
76impl TryFrom<String> for Blake3Hex {
77    type Error = IdentifierError;
78
79    fn try_from(value: String) -> Result<Self, Self::Error> {
80        Self::parse(value)
81    }
82}
83
84impl TryFrom<&str> for Blake3Hex {
85    type Error = IdentifierError;
86
87    fn try_from(value: &str) -> Result<Self, Self::Error> {
88        Self::parse(value)
89    }
90}
91
92impl From<Blake3Hex> for String {
93    fn from(value: Blake3Hex) -> Self {
94        value.into_string()
95    }
96}
97
98impl Serialize for Blake3Hex {
99    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
100    where
101        S: Serializer,
102    {
103        serializer.serialize_str(self.as_str())
104    }
105}
106
107impl<'de> Deserialize<'de> for Blake3Hex {
108    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
109    where
110        D: Deserializer<'de>,
111    {
112        let value = String::deserialize(deserializer)?;
113        Self::parse(value).map_err(serde::de::Error::custom)
114    }
115}
116
117#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
118pub struct NodeIdHex(String);
119
120impl NodeIdHex {
121    pub fn parse(value: impl Into<String>) -> Result<Self, IdentifierError> {
122        let value = value.into();
123        if is_lower_hex_64(&value) {
124            Ok(Self(value))
125        } else {
126            Err(IdentifierError::NodeIdHex(value))
127        }
128    }
129
130    pub fn as_str(&self) -> &str {
131        &self.0
132    }
133
134    pub fn into_string(self) -> String {
135        self.0
136    }
137
138    pub fn from_public_key(key: iroh::PublicKey) -> Self {
139        Self(key.to_string())
140    }
141}
142
143impl fmt::Display for NodeIdHex {
144    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145        self.0.fmt(f)
146    }
147}
148
149impl Deref for NodeIdHex {
150    type Target = str;
151
152    fn deref(&self) -> &Self::Target {
153        self.as_str()
154    }
155}
156
157impl Borrow<str> for NodeIdHex {
158    fn borrow(&self) -> &str {
159        self.as_str()
160    }
161}
162
163impl FromStr for NodeIdHex {
164    type Err = IdentifierError;
165
166    fn from_str(s: &str) -> Result<Self, Self::Err> {
167        Self::parse(s)
168    }
169}
170
171impl TryFrom<String> for NodeIdHex {
172    type Error = IdentifierError;
173
174    fn try_from(value: String) -> Result<Self, Self::Error> {
175        Self::parse(value)
176    }
177}
178
179impl TryFrom<&str> for NodeIdHex {
180    type Error = IdentifierError;
181
182    fn try_from(value: &str) -> Result<Self, Self::Error> {
183        Self::parse(value)
184    }
185}
186
187impl From<NodeIdHex> for String {
188    fn from(value: NodeIdHex) -> Self {
189        value.into_string()
190    }
191}
192
193impl Serialize for NodeIdHex {
194    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
195    where
196        S: Serializer,
197    {
198        serializer.serialize_str(self.as_str())
199    }
200}
201
202impl<'de> Deserialize<'de> for NodeIdHex {
203    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
204    where
205        D: Deserializer<'de>,
206    {
207        let value = String::deserialize(deserializer)?;
208        Self::parse(value).map_err(serde::de::Error::custom)
209    }
210}