dev_kit/command/uri/
mod.rs

1use derive_more::{Deref, Display, FromStr};
2use itertools::Itertools;
3use serde::Deserialize;
4use std::collections::BTreeMap;
5
6#[derive(clap::Subcommand)]
7pub enum UriCommand {
8    #[clap(about = "decode uri component, alias d", alias = "d")]
9    Decode {
10        #[arg(help = "uri component to decode", default_value = "-")]
11        uri: Uri
12    },
13    #[clap(about = "encode uri component, alias e", alias = "e")]
14    Encode {
15        #[arg(help = "uri component to encode", default_value = "-")]
16        uri: Uri
17    },
18    #[clap(about = "parse uri component, alias p", alias = "p")]
19    Parse {
20        #[arg(help = "uri component to encode", default_value = "-")]
21        uri: Uri,
22        #[arg(long, help = "component filter of uri: scheme, authority, host, port, path, query", value_delimiter = ',')]
23        filter: Option<Vec<UriComponent>>,
24    },
25}
26
27impl super::Command for UriCommand {
28    fn run(&self) -> crate::Result<()> {
29        match self {
30            UriCommand::Decode { uri } => {
31                let result = uri.decode()?;
32                println!("{result}");
33                Ok(())
34            }
35            UriCommand::Encode { uri } => {
36                let result = uri.encode()?;
37                println!("{result}");
38                Ok(())
39            }
40            UriCommand::Parse { uri, filter } => {
41                let result = uri.parse(filter)?;
42                let filter_len = filter.as_ref().map(|it| it.len()).unwrap_or(0);
43                for it in result {
44                    match filter_len {
45                        1 => {
46                            if let UriComponentValue::Query(parts) = it {
47                                let string = parts.into_iter().map(|(_, v)|
48                                    v.to_string()
49                                ).next().unwrap_or_default();
50                                println!("{}", string)
51                            } else {
52                                println!("{}", it.string_value())
53                            }
54                        }
55                        _ => {
56                            if let UriComponentValue::Query(parts) = it {
57                                let parts = parts.into_iter().map(|(k, v)|
58                                    format!("   {}={}", k, v)
59                                ).join("\n");
60                                println!("query:\n{parts}")
61                            } else {
62                                println!("{}: {}", it.name(), it.string_value())
63                            }
64                        }
65                    }
66                }
67                Ok(())
68            }
69        }
70    }
71}
72
73#[derive(Debug, Clone, Display)]
74pub enum Uri {
75    Url(url::Url),
76    String(String),
77    HttpRequest(super::http_parser::HttpRequest),
78}
79
80mod uri;
81
82#[derive(Debug, Clone, Display, Deserialize)]
83pub enum UriComponent {
84    Scheme,
85    Authority,
86    Host,
87    Port,
88    Path,
89    #[display("{_0:?}")]
90    Query(Option<QueryPartName>),
91}
92
93#[derive(Debug, Clone)]
94pub enum UriComponentValue {
95    Scheme(String),
96    Authority(Option<String>),
97    Host(String),
98    Port(u16),
99    Path(String),
100    Query(BTreeMap<QueryPartName, QueryPartVal>),
101}
102
103#[derive(Debug, Clone, Deserialize, Deref, Display, Eq, PartialEq, Ord, PartialOrd, FromStr)]
104pub struct QueryPartName(String);
105#[derive(Debug, Clone, Deserialize)]
106pub enum QueryPartVal {
107    Single(Option<String>),
108    Multi(Vec<String>),
109}
110
111mod components;