1#![allow(clippy::len_without_is_empty)]
7
8use regex::Regex;
9use std::fmt;
10use std::str;
11
12use crate::errors::ParseError;
13use bytes::{BufMut, Bytes, BytesMut};
14use std::convert::TryFrom;
15use std::str::FromStr;
16
17use lazy_static::lazy_static;
18
19const MAX_ADDRESS_LENGTH: usize = 1023;
20
21#[derive(Debug)]
22pub enum AddressError {
23 InvalidLength(usize),
24 InvalidFormat,
25}
26
27lazy_static! {
28 static ref ADDRESS_PATTERN: Regex =
29 Regex::new(r"^(g|private|example|peer|self|test[1-3]?|local)([.][a-zA-Z0-9_~-]+)+$")
30 .unwrap();
31}
32
33use std::error::Error;
34impl Error for AddressError {
35 fn description(&self) -> &str {
36 match *self {
37 AddressError::InvalidLength(_length) => "Invalid address length",
38 AddressError::InvalidFormat => "Invalid address format",
39 }
40 }
41}
42
43impl fmt::Display for AddressError {
44 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45 self.description().fmt(f)
46 }
47}
48
49#[derive(Clone, Eq, Hash, PartialEq)]
51pub struct Address(Bytes);
52
53impl FromStr for Address {
54 type Err = ParseError;
55
56 fn from_str(src: &str) -> Result<Self, Self::Err> {
57 Address::try_from(Bytes::from(src))
58 }
59}
60
61impl TryFrom<Bytes> for Address {
62 type Error = ParseError;
63
64 fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
65 if bytes.len() > MAX_ADDRESS_LENGTH {
67 return Err(ParseError::InvalidAddress(AddressError::InvalidLength(
68 bytes.len(),
69 )));
70 }
71
72 if ADDRESS_PATTERN.is_match(str::from_utf8(&bytes)?) {
73 Ok(Address(bytes))
74 } else {
75 Err(ParseError::InvalidAddress(AddressError::InvalidFormat))
76 }
77 }
78}
79
80impl TryFrom<&[u8]> for Address {
81 type Error = ParseError;
82
83 fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
84 Self::try_from(Bytes::from(bytes))
85 }
86}
87
88impl std::ops::Deref for Address {
89 type Target = str;
90
91 fn deref(&self) -> &str {
92 unsafe { str::from_utf8_unchecked(self.0.as_ref()) }
95 }
96}
97
98impl AsRef<[u8]> for Address {
99 #[inline]
100 fn as_ref(&self) -> &[u8] {
101 self.0.as_ref()
102 }
103}
104
105impl AsRef<Bytes> for Address {
106 #[inline]
107 fn as_ref(&self) -> &Bytes {
108 &self.0
109 }
110}
111
112impl fmt::Debug for Address {
113 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
114 formatter
115 .debug_tuple("Address")
116 .field(&self.to_string())
117 .finish()
118 }
119}
120
121impl fmt::Display for Address {
122 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
123 formatter.write_str(self)
124 }
125}
126
127impl Address {
128 #[inline]
130 pub fn len(&self) -> usize {
131 self.0.len()
132 }
133
134 pub fn to_bytes(&self) -> Bytes {
136 self.0.clone()
137 }
138
139 #[inline]
145 pub unsafe fn new_unchecked(bytes: Bytes) -> Self {
146 debug_assert!(Address::try_from(bytes.as_ref()).is_ok());
147 Address(bytes)
148 }
149
150 pub fn segments(&self) -> impl DoubleEndedIterator<Item = &str> {
152 unsafe {
153 self.0
154 .split(|&b| b == b'.')
155 .map(|s| str::from_utf8_unchecked(&s))
156 }
157 }
158
159 pub fn scheme(&self) -> &str {
162 self.segments()
164 .next()
165 .expect("Addresses must have a scheme as the first segment")
166 }
167
168 pub fn with_suffix(&self, suffix: &[u8]) -> Result<Address, ParseError> {
170 let new_address_len = self.len() + 1 + suffix.len();
171 let mut new_address = BytesMut::with_capacity(new_address_len);
172
173 new_address.put_slice(self.0.as_ref());
174 new_address.put(b'.');
175 new_address.put_slice(suffix);
176
177 Address::try_from(new_address.freeze())
178 }
179}
180
181impl<'a> PartialEq<[u8]> for Address {
182 fn eq(&self, other: &[u8]) -> bool {
183 self.0 == other
184 }
185}
186
187#[cfg(any(feature = "serde", test))]
188impl<'de> serde::Deserialize<'de> for Address {
189 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
190 where
191 D: serde::Deserializer<'de>,
192 {
193 let string = <&str>::deserialize(deserializer)?;
194 Address::from_str(string).map_err(serde::de::Error::custom)
195 }
196}
197
198#[cfg(any(feature = "serde", test))]
199impl serde::Serialize for Address {
200 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
201 where
202 S: serde::Serializer,
203 {
204 serializer.serialize_str(&*self)
205 }
206}
207
208#[cfg(test)]
209mod test_address {
210 use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_ser_tokens, Token};
211
212 use super::*;
213
214 static VALID_ADDRESSES: &[&[u8]] = &[
215 b"test.alice.XYZ.1234.-_~",
216 b"g.us-fed.ach.0.acmebank.swx0a0.acmecorp.sales.199.~ipr.cdfa5e16-e759-4ba3-88f6-8b9dc83c1868.2",
217
218 b"g.A", b"private.A", b"example.A", b"peer.A", b"self.A",
219 b"test.A", b"test1.A", b"test2.A", b"test3.A", b"local.A",
220 ];
221
222 static INVALID_ADDRESSES: &[&[u8]] = &[
223 b"", b"test.alice 123",
226 b"test.alice!123",
227 b"test.alice/123",
228 b"test.alic\xF0",
229 b"test", b"what.alice", b"test4.alice", b"test.", b"test.alice.", b".test.alice", b"test..alice", ];
239
240 #[test]
241 fn test_try_from() {
242 for address in VALID_ADDRESSES {
243 assert_eq!(
244 Address::try_from(*address).unwrap(),
245 Address(Bytes::from(*address)),
246 "address: {:?}",
247 String::from_utf8_lossy(address),
248 );
249 }
250
251 let longest_address = &make_address(1023)[..];
252 assert_eq!(
253 Address::try_from(longest_address).unwrap(),
254 Address(Bytes::from(longest_address)),
255 );
256
257 for address in INVALID_ADDRESSES {
258 assert!(
259 Address::try_from(*address).is_err(),
260 "address: {:?}",
261 String::from_utf8_lossy(address),
262 );
263 }
264
265 let too_long_address = &make_address(1024)[..];
266 assert!(Address::try_from(too_long_address).is_err());
267 }
268
269 #[test]
270 fn test_deserialize() {
271 assert_de_tokens(
272 &Address::try_from(Bytes::from("test.alice")).unwrap(),
273 &[Token::BorrowedStr("test.alice")],
274 );
275 assert_de_tokens_error::<Address>(
276 &[Token::BorrowedStr("test.alice ")],
277 "Invalid address format",
278 );
279 }
280
281 #[test]
282 fn test_serialize() {
283 let addr = Address::try_from(Bytes::from("test.alice")).unwrap();
284 assert_ser_tokens(&addr, &[Token::Str("test.alice")]);
285 }
286
287 #[test]
288 fn test_len() {
289 assert_eq!(
290 Address::from_str("test.alice").unwrap().len(),
291 "test.alice".len(),
292 );
293 }
294
295 #[test]
296 fn test_segments() {
297 let addr = Address::from_str("test.alice.1234.5789").unwrap();
298 let expected = vec!["test", "alice", "1234", "5789"];
299 assert!(addr.segments().eq(expected));
300 }
301
302 #[test]
303 fn test_eq() {
304 let addr1 = Address::from_str("test.alice.1234.5789").unwrap();
305 let addr2 = Address::from_str("test.bob").unwrap();
306 assert_ne!(addr1, addr2);
307 assert_eq!(addr1, addr1);
308 assert_eq!(addr2, addr2);
309 assert!(addr1 == addr1.clone());
310 assert!(addr1 != addr2);
311 assert!(addr1.eq(&addr1));
312 assert!(addr1.ne(&addr2));
313 }
314
315 #[test]
316 fn test_with_suffix() {
317 assert_eq!(
318 Address::from_str("test.alice")
319 .unwrap()
320 .with_suffix(b"1234")
321 .unwrap(),
322 Address::from_str("test.alice.1234").unwrap(),
323 );
324 assert!({
326 Address::from_str("test.alice")
327 .unwrap()
328 .with_suffix(b"12 34")
329 .is_err()
330 });
331 assert!({
332 Address::from_str("test.alice")
333 .unwrap()
334 .with_suffix(b".1234")
335 .is_err()
336 });
337 }
338
339 #[test]
340 fn test_debug() {
341 assert_eq!(
342 format!("{:?}", Address::from_str("test.alice").unwrap()),
343 "Address(\"test.alice\")",
344 );
345 }
346
347 #[test]
348 fn test_display() {
349 assert_eq!(
350 format!("{}", Address::from_str("test.alice").unwrap()),
351 "test.alice",
352 );
353 }
354
355 #[test]
356 fn test_scheme() {
357 assert_eq!(Address::from_str("test.alice").unwrap().scheme(), "test");
358 assert_eq!(
359 Address::from_str("example.node.other").unwrap().scheme(),
360 "example"
361 );
362 assert_eq!(
363 Address::from_str("g.some-node.child-node.with_other_things~and-more")
364 .unwrap()
365 .scheme(),
366 "g"
367 );
368 }
369
370 fn make_address(length: usize) -> Vec<u8> {
371 let mut addr = b"test.".to_vec();
372 addr.resize(length, b'_');
373 addr
374 }
375}