From: Ian Jackson Date: Fri, 23 Jul 2021 18:44:16 +0000 (+0100) Subject: wip parsing X-Git-Tag: hippotat/1.0.0~518 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=721e5d3422e05fc77472e04f613d6b3aca6449f6;p=hippotat.git wip parsing Signed-off-by: Ian Jackson --- diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 0000000..fea9f36 --- /dev/null +++ b/src/types.rs @@ -0,0 +1,78 @@ +// Copyright 2021 Ian Jackson and contributors to Hippotat +// SPDX-License-Identifier: AGPL-3.0-or-later +// There is NO WARRANTY. + +use crate::prelude::*; + +#[derive(Debug,Clone)] +struct ServerName(pub String); + +#[derive(Debug,Clone,Copy)] +struct ClientName(pub Ipv4Addr); + +#[derive(Debug,Clone)] +enum SectionName { + Link { server: ServerName, client: ClientName }, + Client(ClientName), + Server(ServerName), // includes SERVER, which is slightly special + Common, + Default, +} +pub use SectionName as SN; + +impl FromStr for ClientName { + type Err = AE; + #[throws(AE)] + fn from_str(s: &str) -> Self { + let v4addr = s.parse().context("invalid client name (IPv4 address)")?; + if s != v4addr.to_string() { + throw!(anyhow!("invalid client name (unusual IPv4 address syntax)")); + } + ClientName(v4addr) + } +} + +impl FromStr for ServerName { + type Err = AE; + #[throws(AE)] + fn from_str(s: &str) -> Self { + if let Some(bad) = s.chars.find(|c| !{ + c.is_ascii_alphanumeric() || c=='.' || c=='-' + }) { + throw!(anyhow!("invalid server name: bad character {:?}", c)); + } + if ! s.split('.').all( + |d| matches!(d.chars().next(), + Some(c) if c.is_ascii_alphanumeric() )) { + throw!(anyhow!("invalid server name: must be valid domain name")); + } + if s == SERVER + + d == "." || + + ClientName(s.parse().context( + "failed to parse client name (IPv4 address)" + )?) + } +} + +impl FromStr for SectionName { + type Err = AE; + #[throws(AE)] + fn from_str(s: &str) -> Self { + match s { + "COMMON" => return SN::Common, + "DEFAULT" => return SN::Default, + }; + + )) { + // looks like a domain name or IP address + if let Ok(v4addr) = s.parse() { + return SN::Client(ClientName(v4addr)) + } else if (s.chars().any(|c| c==':')) { + throw!(anyhow!("colons not allowed in section names \ + (IPv6 transport is not supported)")); + } else { + return SN::Server( + + }