Mercurial > crates > systemd-socket
annotate src/resolv_addr.rs @ 13:f740dadd2948
Added enable_systemd feature
This feature makes systemd support optional, on by default. While it may
seem strange that this feature exists, it makes sense for authors of
applications who want to make systemd optional. Thanks to this feature
the interface stays the same, it just fails to parse `systemd://`
addresses with a helpful error message.
| author | Martin Habovstiak <martin.habovstiak@gmail.com> |
|---|---|
| date | Thu, 03 Dec 2020 16:34:09 +0100 |
| parents | 66c0e10c89fc |
| children | cfef4593e207 |
| rev | line source |
|---|---|
|
4
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
1 use thiserror::Error; |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
2 use std::fmt; |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
3 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
4 #[derive(Debug, PartialEq)] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
5 pub(crate) struct ResolvAddr(String); |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
6 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
7 impl ResolvAddr { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
8 pub(crate) fn as_str(&self) -> &str { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
9 &self.0 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
10 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
11 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
12 pub(crate) fn try_from_generic<T: std::ops::Deref<Target=str> + Into<String>>(string: T) -> Result<Self, ResolvAddrError> { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
13 // can't use a combinator due to borrowing |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
14 let colon = match string.rfind(':') { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
15 Some(colon) => colon, |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
16 None => return Err(ResolvAddrError::MissingPort(string.into())), |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
17 }; |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
18 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
19 let (hostname, port) = string.split_at(colon); |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
20 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
21 if let Err(error) = port[1..].parse::<u16>() { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
22 return Err(ResolvAddrError::InvalidPort { string: string.into(), error, }); |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
23 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
24 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
25 let len = hostname.len(); |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
26 if len > 253 { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
27 return Err(ResolvAddrError::TooLong { string: string.into(), len, } ) |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
28 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
29 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
30 let mut label_start = 0usize; |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
31 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
32 for (i, c) in hostname.chars().enumerate() { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
33 match c { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
34 '.' => { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
35 if i - label_start == 0 { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
36 return Err(ResolvAddrError::EmptyLabel { string: string.into(), label_start, }); |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
37 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
38 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
39 label_start = i + 1; |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
40 }, |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
41 'a'..='z' | 'A'..='Z' | '0'..='9' | '-' => (), |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
42 _ => return Err(ResolvAddrError::InvalidCharacter { string: string.into(), c, pos: i, }), |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
43 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
44 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
45 if i - label_start > 63 { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
46 return Err(ResolvAddrError::LongLabel { string: string.into(), label_start, label_end: i, }); |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
47 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
48 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
49 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
50 Ok(ResolvAddr(string.into())) |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
51 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
52 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
53 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
54 impl fmt::Display for ResolvAddr { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
55 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
56 fmt::Display::fmt(&self.0, f) |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
57 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
58 } |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
59 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
60 |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
61 #[derive(Debug, Error)] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
62 pub(crate) enum ResolvAddrError { |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
63 #[error("hostname {string} has {len} character which exceeds the limit of 253")] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
64 TooLong { string: String, len: usize }, |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
65 #[error("invalid character {c} in hostname {string} at position {pos}")] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
66 InvalidCharacter { string: String, pos: usize, c: char, }, |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
67 #[error("hostname {string} contains a label {} at position {label_start} which is {} characters long - more than the limit 63", &string[(*label_start)..(*label_end)], label_end - label_start)] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
68 LongLabel { string: String, label_start: usize, label_end: usize, }, |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
69 #[error("hostname {string} contains an empty label at position {label_start}")] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
70 EmptyLabel { string: String, label_start: usize, }, |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
71 #[error("the address {0} is missing a port")] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
72 MissingPort(String), |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
73 #[error("failed to parse port numer in the address {string}")] |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
74 InvalidPort { string: String, error: std::num::ParseIntError, }, |
|
66c0e10c89fc
Support resolving hostnames
Martin Habovstiak <martin.habovstiak@gmail.com>
parents:
diff
changeset
|
75 } |
