From: Ian Jackson Date: Fri, 23 Jul 2021 21:12:34 +0000 (+0100) Subject: wip parsing X-Git-Tag: hippotat/1.0.0~517 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=6e0f2e47479654d10f3d7d57f6f86a5490b2125c;p=hippotat.git wip parsing Signed-off-by: Ian Jackson --- diff --git a/Cargo.lock b/Cargo.lock index b3abe38..e2c8aa2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,6 +82,12 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7201ee416d124d589a820111ba755930df8b75855321a9a1b87312a0597ec8f" +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + [[package]] name = "env_logger" version = "0.9.0" @@ -195,7 +201,10 @@ dependencies = [ "extend", "fehler", "hyper", + "itertools", + "lazy-regex", "log", + "regex", "structopt", "tokio", "void", @@ -272,12 +281,44 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "itertools" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +[[package]] +name = "lazy-regex" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17d198f91272f6e788a5c0bd5d741cf778da4e5bc761ec67b32d5d3b0db34a54" +dependencies = [ + "lazy-regex-proc_macros", + "once_cell", + "regex", +] + +[[package]] +name = "lazy-regex-proc_macros" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c12938b1b92cf5be22940527e15b79fd0c7e706e34bc70816f6a72b3484f84e" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn", +] + [[package]] name = "lazy_static" version = "1.4.0" diff --git a/Cargo.toml b/Cargo.toml index 96415da..564b8d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,9 @@ env_logger = "0.9" extend = "1" fehler = "1" hyper = "0.14" +itertools = "0.10" +lazy-regex = "2" +regex = "1.5" log = "0.4" structopt = "0.3" tokio = { version = "1", features = ["full"] } diff --git a/src/lib.rs b/src/lib.rs index 0667ee9..1f6a3cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,4 +7,5 @@ pub mod prelude; pub mod config; +pub mod types; pub mod utils; diff --git a/src/prelude.rs b/src/prelude.rs index dbba79a..b752627 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -7,13 +7,16 @@ pub use std::fs; pub use std::fmt::Debug; pub use std::io::{self, ErrorKind, Read as _}; pub use std::mem; -pub use std::net::IpAddr; +pub use std::net::{IpAddr, Ipv4Addr}; pub use std::path::{Path, PathBuf}; +pub use std::str::FromStr; pub use anyhow::{anyhow, Context}; pub use extend::ext; pub use fehler::{throw, throws}; pub use hyper::Uri; +pub use itertools::Itertools; +pub use lazy_regex::regex_is_match; pub use structopt::StructOpt; pub use tokio::time::Duration; pub use void::{self, Void}; diff --git a/src/types.rs b/src/types.rs index fea9f36..38fcbfe 100644 --- a/src/types.rs +++ b/src/types.rs @@ -5,13 +5,13 @@ use crate::prelude::*; #[derive(Debug,Clone)] -struct ServerName(pub String); +pub struct ServerName(pub String); #[derive(Debug,Clone,Copy)] -struct ClientName(pub Ipv4Addr); +pub struct ClientName(pub Ipv4Addr); #[derive(Debug,Clone)] -enum SectionName { +pub enum SectionName { Link { server: ServerName, client: ClientName }, Client(ClientName), Server(ServerName), // includes SERVER, which is slightly special @@ -24,7 +24,8 @@ 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)")?; + let v4addr: Ipv4Addr = s.parse() + .context("invalid client name (IPv4 address)")?; if s != v4addr.to_string() { throw!(anyhow!("invalid client name (unusual IPv4 address syntax)")); } @@ -36,23 +37,18 @@ 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 ! regex_is_match!(r" + ^ (?: SERVER + | [0-9a-z][-0-9a-z]* (:? \. + [0-9a-z][-0-9a-z]* )* + )"x, s) { + throw!(anyhow!("bad syntax for server name")); } - 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 regex_is_match!(r"[a-z-]", s) { + throw!(anyhow!("bad syntax for server name \ + (too much like an IPv4 address)")); } - if s == SERVER - - d == "." || - - ClientName(s.parse().context( - "failed to parse client name (IPv4 address)" - )?) + ServerName(s.into()) } } @@ -63,16 +59,17 @@ impl FromStr for SectionName { 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( - + if let Ok(n@ ServerName(_)) = s.parse() { return SN::Server(n) } + if let Ok(n@ ClientName(_)) = s.parse() { return SN::Client(n) } + let (server, client) = s.split_ascii_whitespace().collect_tuple() + .ok_or_else(|| anyhow!( + "bad section name \ + (must be COMMON, DEFAULT, , , or " + ))?; + let server = server.parse().context("server name in link section name")?; + let client = client.parse().context("client name in link section name")?; + SN::Link { server, client } } +}