#![allow(dead_code)]
use RawKind::*;
#[derive(Clone, Copy, PartialEq, Eq)]
enum RawKind {
Invalid,
Iri,
IriAbsolute,
IriRelative,
Uri,
UriAbsolute,
UriRelative,
}
impl RawKind {
fn spec_is(self, spec: Spec) -> bool {
match spec {
Spec::Uri => matches!(self, Self::Uri | Self::UriAbsolute | Self::UriRelative),
Spec::Iri => self != Self::Invalid,
}
}
fn kind_is(self, kind: Kind) -> bool {
match kind {
Kind::Absolute => matches!(self, Self::UriAbsolute | Self::IriAbsolute),
Kind::Normal => matches!(
self,
Self::UriAbsolute | Self::Uri | Self::IriAbsolute | Self::Iri
),
Kind::Reference => self != Self::Invalid,
Kind::Relative => matches!(self, Self::UriRelative | Self::IriRelative),
}
}
fn is(self, spec: Spec, kind: Kind) -> bool {
self.spec_is(spec) && self.kind_is(kind)
}
}
const STRINGS: &[(RawKind, &str)] = &[
(UriAbsolute, "https://user:pass@example.com:8080"),
(UriAbsolute, "https://example.com/"),
(UriAbsolute, "https://example.com/foo?bar=baz"),
(Uri, "https://example.com/foo?bar=baz#qux"),
(UriAbsolute, "foo:bar"),
(UriAbsolute, "foo:"),
(UriAbsolute, "foo:/"),
(UriAbsolute, "foo://"),
(UriAbsolute, "foo:///"),
(UriAbsolute, "foo:////"),
(UriAbsolute, "foo://///"),
(UriRelative, "foo"),
(UriRelative, "foo/bar"),
(UriRelative, "foo//bar"),
(UriRelative, "/"),
(UriRelative, "/foo"),
(UriRelative, "/foo/bar"),
(UriRelative, "//foo/bar"),
(UriRelative, "/foo//bar"),
(UriRelative, "?"),
(UriRelative, "???"),
(UriRelative, "?foo"),
(UriRelative, "#"),
(UriRelative, "#foo"),
(Invalid, "##"),
(Invalid, "fragment#cannot#have#hash#char"),
(Invalid, "<"),
(Invalid, ">"),
(Invalid, "lt<and-gt>not-allowed"),
(Invalid, "%"),
(Invalid, "%0"),
(Invalid, "%f"),
(Invalid, "%F"),
(Invalid, "%0g"),
(Invalid, "%0G"),
(Invalid, "%GG"),
(Invalid, "%G0"),
];
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Spec {
Uri,
Iri,
}
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Kind {
Absolute,
Normal,
Reference,
Relative,
}
pub fn positive(spec: Spec, kind: Kind) -> impl Iterator<Item = &'static str> {
STRINGS
.iter()
.filter(move |(raw_kind, _)| raw_kind.is(spec, kind))
.map(|(_, s)| *s)
}
pub fn negative(spec: Spec, kind: Kind) -> impl Iterator<Item = &'static str> {
STRINGS
.iter()
.filter(move |(raw_kind, _)| !raw_kind.is(spec, kind))
.map(|(_, s)| *s)
}