annotate src/resolv_addr.rs @ 5:27456533853e

Attempt to setup CI using GitHub Actions This sets up CI to test the crate on Ubuntu, Windows and macOS. It's expected to fail on Windows now and it will be fixed after we know which things need to be configured-away.
author Martin Habovštiak <martin.habovstiak@gmail.com>
date Fri, 27 Nov 2020 15:18:25 +0100
parents 66c0e10c89fc
children cfef4593e207
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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 }