chiark / gitweb /
wip parsing
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 23 Jul 2021 18:44:16 +0000 (19:44 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 23 Jul 2021 18:44:16 +0000 (19:44 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/types.rs [new file with mode: 0644]

diff --git a/src/types.rs b/src/types.rs
new file mode 100644 (file)
index 0000000..fea9f36
--- /dev/null
@@ -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(
+      
+  }