Mercurial > crates > systemd-socket
view 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 |
line wrap: on
line source
use thiserror::Error; use std::fmt; #[derive(Debug, PartialEq)] pub(crate) struct ResolvAddr(String); impl ResolvAddr { pub(crate) fn as_str(&self) -> &str { &self.0 } pub(crate) fn try_from_generic<T: std::ops::Deref<Target=str> + Into<String>>(string: T) -> Result<Self, ResolvAddrError> { // can't use a combinator due to borrowing let colon = match string.rfind(':') { Some(colon) => colon, None => return Err(ResolvAddrError::MissingPort(string.into())), }; let (hostname, port) = string.split_at(colon); if let Err(error) = port[1..].parse::<u16>() { return Err(ResolvAddrError::InvalidPort { string: string.into(), error, }); } let len = hostname.len(); if len > 253 { return Err(ResolvAddrError::TooLong { string: string.into(), len, } ) } let mut label_start = 0usize; for (i, c) in hostname.chars().enumerate() { match c { '.' => { if i - label_start == 0 { return Err(ResolvAddrError::EmptyLabel { string: string.into(), label_start, }); } label_start = i + 1; }, 'a'..='z' | 'A'..='Z' | '0'..='9' | '-' => (), _ => return Err(ResolvAddrError::InvalidCharacter { string: string.into(), c, pos: i, }), } if i - label_start > 63 { return Err(ResolvAddrError::LongLabel { string: string.into(), label_start, label_end: i, }); } } Ok(ResolvAddr(string.into())) } } impl fmt::Display for ResolvAddr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } } #[derive(Debug, Error)] pub(crate) enum ResolvAddrError { #[error("hostname {string} has {len} character which exceeds the limit of 253")] TooLong { string: String, len: usize }, #[error("invalid character {c} in hostname {string} at position {pos}")] InvalidCharacter { string: String, pos: usize, c: char, }, #[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)] LongLabel { string: String, label_start: usize, label_end: usize, }, #[error("hostname {string} contains an empty label at position {label_start}")] EmptyLabel { string: String, label_start: usize, }, #[error("the address {0} is missing a port")] MissingPort(String), #[error("failed to parse port numer in the address {string}")] InvalidPort { string: String, error: std::num::ParseIntError, }, }
