Created
June 23, 2022 16:36
-
-
Save daltonclaybrook/37307dfd3c16fe49beb9be288fa96deb to your computer and use it in GitHub Desktop.
Example of compile-time URL parsing in Rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate proc_macro; | |
use proc_macro::TokenStream; | |
use syn::parse_macro_input; | |
use quote::quote; | |
use regex::Regex; | |
#[proc_macro] | |
pub fn make_url(_item: TokenStream) -> TokenStream { | |
let input = parse_macro_input!(_item as syn::LitStr); | |
let url_regex = Regex::new(r"^(\w+)://([\w-]+(?:\.[\w-]+)*)((?:/[\w-]+)*)?(\?[\w\-=&]+)?$").unwrap(); | |
let value = input.value(); | |
let captures = url_regex.captures(&value).expect("The string literal is not a valid URL"); | |
let scheme = captures.get(1).expect("Could not determine scheme").as_str(); | |
let domain = captures.get(2).expect("Could not determine domain").as_str(); | |
let path = captures.get(3).expect("Could not determine path").as_str(); | |
let query = captures.get(4).map_or("", |m| m.as_str()); | |
let path = if path.is_empty() { "/" } else { path }; | |
quote! { | |
URL { | |
scheme: #scheme, | |
domain: #domain, | |
path: #path, | |
query: #query, | |
} | |
}.into() | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#[macro_use] | |
extern crate url_macros; | |
pub struct URL { | |
pub scheme: &'static str, | |
pub domain: &'static str, | |
pub path: &'static str, | |
pub query: &'static str, | |
} | |
fn main() { | |
let apple_url: URL = make_url!("http://apple.com?foo=bar&fizz=buzz"); | |
let invalid_url: URL = make_url!("foobar"); | |
println!("Scheme: {}", apple_url.scheme); | |
println!("Domain: {}", apple_url.domain); | |
println!("Path: {}", apple_url.path); | |
println!("Query: {}", apple_url.query); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment