1 // Copyright 2021 Ian Jackson and contributors to Hippotat
2 // SPDX-License-Identifier: AGPL-3.0-or-later
3 // There is NO WARRANTY.
8 pub struct ServerName(pub String);
10 #[derive(Debug,Clone,Copy)]
11 pub struct ClientName(pub Ipv4Addr);
13 #[derive(Debug,Clone)]
14 pub enum SectionName {
15 Link { server: ServerName, client: ClientName },
17 Server(ServerName), // includes SERVER, which is slightly special
21 pub use SectionName as SN;
23 impl FromStr for ClientName {
26 fn from_str(s: &str) -> Self {
27 let v4addr: Ipv4Addr = s.parse()
28 .context("invalid client name (IPv4 address)")?;
29 if s != v4addr.to_string() {
30 throw!(anyhow!("invalid client name (unusual IPv4 address syntax)"));
36 impl FromStr for ServerName {
39 fn from_str(s: &str) -> Self {
40 if ! regex_is_match!(r"
42 | [0-9a-z][-0-9a-z]* (:? \.
45 throw!(anyhow!("bad syntax for server name"));
47 if regex_is_match!(r"[a-z-]", s) {
48 throw!(anyhow!("bad syntax for server name \
49 (too much like an IPv4 address)"));
55 impl FromStr for SectionName {
58 fn from_str(s: &str) -> Self {
60 "COMMON" => return SN::Common,
61 "DEFAULT" => return SN::Default,
64 if let Ok(n@ ServerName(_)) = s.parse() { return SN::Server(n) }
65 if let Ok(n@ ClientName(_)) = s.parse() { return SN::Client(n) }
66 let (server, client) = s.split_ascii_whitespace().collect_tuple()
67 .ok_or_else(|| anyhow!(
69 (must be COMMON, DEFAULT, <server>, <client>, or <server> <client>"
71 let server = server.parse().context("server name in link section name")?;
72 let client = client.parse().context("client name in link section name")?;
73 SN::Link { server, client }