diff options
Diffstat (limited to 'vendor/iri-string/examples/parse.rs')
| -rw-r--r-- | vendor/iri-string/examples/parse.rs | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/vendor/iri-string/examples/parse.rs b/vendor/iri-string/examples/parse.rs new file mode 100644 index 00000000..b447e461 --- /dev/null +++ b/vendor/iri-string/examples/parse.rs @@ -0,0 +1,159 @@ +//! An example to parse IRI from the CLI argument. + +use iri_string::types::{IriStr, RiReferenceStr, RiStr}; + +const USAGE: &str = "\ +USAGE: + parse [FLAGS] [--] IRI + +FLAGS: + -h, --help Prints this help + -i, --iri Handle the input as an IRI (RFC 3987) + -u, --uri Handle the input as an URI (RFC 3986) + +ARGS: + <IRI> IRI or URI +"; + +fn print_help() { + eprintln!("{}", USAGE); +} + +fn help_and_exit() -> ! { + print_help(); + std::process::exit(1); +} + +fn die(msg: impl std::fmt::Display) -> ! { + eprintln!("ERROR: {}", msg); + eprintln!(); + print_help(); + std::process::exit(1); +} + +/// Syntax specification. +#[derive(Debug, Clone, Copy)] +enum Spec { + /// RFC 3986 URI. + Uri, + /// RFC 3987 IRI. + Iri, +} + +impl Default for Spec { + #[inline] + fn default() -> Self { + Self::Iri + } +} + +/// CLI options. +#[derive(Default, Debug, Clone)] +struct CliOpt { + /// IRI. + iri: String, + /// Syntax spec. + spec: Spec, +} + +impl CliOpt { + fn parse() -> Self { + let mut args = std::env::args(); + // Skip `argv[0]`. + args.next(); + + let mut iri = None; + let mut spec = None; + + for arg in args.by_ref() { + match arg.as_str() { + "--iri" | "-i" => spec = Some(Spec::Iri), + "--uri" | "-u" => spec = Some(Spec::Uri), + "--help" | "-h" => help_and_exit(), + opt if opt.starts_with('-') => die(format_args!("Unknown option: {}", opt)), + _ => { + if iri.replace(arg).is_some() { + die("IRI can be specified at most once"); + } + } + } + } + + for arg in args { + if iri.replace(arg).is_some() { + eprintln!("ERROR: IRI can be specified at most once"); + } + } + + let iri = iri.unwrap_or_else(|| die("IRI should be specified")); + let spec = spec.unwrap_or_default(); + Self { iri, spec } + } +} + +fn main() { + let opt = CliOpt::parse(); + + match opt.spec { + Spec::Iri => parse_iri(&opt), + Spec::Uri => parse_uri(&opt), + } +} + +fn parse_iri(opt: &CliOpt) { + let iri = parse::<iri_string::spec::IriSpec>(opt); + let uri = iri.encode_to_uri(); + println!("ASCII: {:?}", uri); +} + +fn parse_uri(opt: &CliOpt) { + let iri = parse::<iri_string::spec::UriSpec>(opt); + println!("ASCII: {:?}", iri); +} + +fn parse<S: iri_string::spec::Spec>(opt: &CliOpt) -> &RiReferenceStr<S> +where + RiStr<S>: AsRef<RiStr<iri_string::spec::IriSpec>>, +{ + let raw = &opt.iri.as_str(); + let iri = match RiReferenceStr::<S>::new(raw) { + Ok(v) => v, + Err(e) => die(format_args!("Failed to parse {:?}: {}", raw, e)), + }; + println!("Successfully parsed: {:?}", iri); + + let absolute = iri.to_iri().ok(); + match absolute { + Some(_) => println!("IRI is ablolute."), + None => println!("IRI is relative."), + } + + print_components(iri); + if let Some(absolute) = absolute { + print_normalized(absolute.as_ref()); + } + + iri +} + +fn print_components<S: iri_string::spec::Spec>(iri: &RiReferenceStr<S>) { + println!("scheme: {:?}", iri.scheme_str()); + println!("authority: {:?}", iri.authority_str()); + if let Some(components) = iri.authority_components() { + println!(" userinfo: {:?}", components.userinfo()); + println!(" host: {:?}", components.host()); + println!(" port: {:?}", components.port()); + } + println!("path: {:?}", iri.path_str()); + println!("query: {:?}", iri.query_str()); + println!("fragment: {:?}", iri.fragment()); +} + +pub fn print_normalized(iri: &IriStr) { + println!("is_normalized_rfc3986: {}", iri.is_normalized_rfc3986()); + println!( + "is_normalized_but_authorityless_relative_path_preserved: {}", + iri.is_normalized_but_authorityless_relative_path_preserved() + ); + println!("normalized: {}", iri.normalize()); +} |
