parser_on_rust/
lib.rs

1use std::error::Error;
2
3use pest::Parser;
4use pest_derive::Parser;
5
6#[derive(Parser)]
7#[grammar = "url.pest"]
8struct UrlParser;
9
10#[derive(Debug)]
11pub struct ParsedUrl {
12    pub scheme: String,
13    pub host: String,
14    pub port: Option<u16>,
15    pub path: String,
16    pub query: Option<String>,
17    pub fragment: Option<String>,
18    pub file: Option<String>,
19}
20
21impl ParsedUrl {
22    fn new() -> Self {
23        ParsedUrl {
24            scheme: String::new(),
25            host: String::new(),
26            port: None,
27            path: String::new(),
28            query: None,
29            fragment: None,
30            file: None,
31        }
32    }
33}
34
35pub fn parse_url(url_string: &str) -> Result<ParsedUrl, Box<dyn Error>> {
36    let pairs = match UrlParser::parse(Rule::url, url_string) {
37        Ok(pairs) => pairs,
38        Err(e) => return Err(format!("Error parsing URL: {}", e).into()),
39    };
40
41    let mut parsed_url = ParsedUrl::new();
42
43    for pair in pairs.into_iter() {
44        for pair_inner in pair.into_inner() {
45            match pair_inner.as_rule() {
46                Rule::scheme => parsed_url.scheme = pair_inner.as_str().to_string(),
47                Rule::host => parsed_url.host = pair_inner.as_str().to_string(),
48                Rule::port => parsed_url.port = Some(pair_inner.as_str().parse().unwrap()),
49                Rule::path => parsed_url.path = pair_inner.as_str().to_string(),
50                Rule::query => parsed_url.query = Some(pair_inner.as_str().to_string()),
51                Rule::fragment => parsed_url.fragment = Some(pair_inner.as_str().to_string()),
52                Rule::file => parsed_url.file = Some(pair_inner.as_str().to_string()),
53                _ => {
54                    eprintln!("Unexpected rule: {:?}", pair_inner.as_rule());
55                }
56            }
57        }
58    }
59
60    Ok(parsed_url)
61}