1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
//! This is a companion crate for [`iref`][iref] providing macros to build
//! `'static` URI/IRIs and URI/IRI references at compile time.
//!
//! [iref]: <https://github.com/timothee-haudebourg/iref>
//!
//! ## Basic usage
//!
//! Use the `uri!` (resp. `iri!`) macro to build URI (resp. IRI) statically, and
//! the `uri_ref!` (resp `iri_ref!`) macro to build URI (resp. IRI) references
//! statically.
//!
//! ```rust
//! use iref::{Iri, IriRef};
//! use static_iref::{iri, iri_ref};
//!
//! const IRI: &'static Iri = iri!("https://www.rust-lang.org/foo/bar#frag");
//! const IRI_REF: &'static IriRef = iri_ref!("/foo/bar#frag");
//! ```
use iref::{IriBuf, IriRefBuf, UriBuf, UriRefBuf};
use proc_macro::TokenStream;
use quote::quote;
/// Build an URI with a `'static` lifetime at compile time.
///
/// This macro expects a single string literal token representing the URI.
#[proc_macro]
pub fn uri(tokens: TokenStream) -> TokenStream {
match syn::parse::<syn::LitStr>(tokens) {
Ok(lit) => match UriBuf::new(lit.value().into_bytes()) {
Ok(uri) => {
let value = uri.as_bytes();
quote! {
unsafe {
::iref::Uri::new_unchecked(&[#(#value),*])
}
}
.into()
}
Err(_) => produce_error("invalid URI"),
},
Err(e) => e.to_compile_error().into(),
}
}
/// Build an URI reference with a `'static` lifetime at compile time.
///
/// This macro expects a single string literal token representing the URI reference.
#[proc_macro]
pub fn uri_ref(tokens: TokenStream) -> TokenStream {
match syn::parse::<syn::LitStr>(tokens) {
Ok(lit) => match UriRefBuf::new(lit.value().into_bytes()) {
Ok(uri_ref) => {
let value = uri_ref.as_bytes();
quote! {
unsafe {
::iref::UriRef::new_unchecked(&[#(#value),*])
}
}
.into()
}
Err(_) => produce_error("invalid URI reference"),
},
Err(e) => e.to_compile_error().into(),
}
}
/// Build an IRI with a `'static` lifetime at compile time.
///
/// This macro expects a single string literal token representing the IRI.
#[proc_macro]
pub fn iri(tokens: TokenStream) -> TokenStream {
match syn::parse::<syn::LitStr>(tokens) {
Ok(lit) => match IriBuf::new(lit.value()) {
Ok(iri) => {
let value = iri.as_str();
quote! {
unsafe {
::iref::Iri::new_unchecked(#value)
}
}
.into()
}
Err(_) => produce_error("invalid IRI"),
},
Err(e) => e.to_compile_error().into(),
}
}
/// Build an IRI reference with a `'static` lifetime at compile time.
///
/// This macro expects a single string literal token representing the IRI reference.
#[proc_macro]
pub fn iri_ref(tokens: TokenStream) -> TokenStream {
match syn::parse::<syn::LitStr>(tokens) {
Ok(lit) => match IriRefBuf::new(lit.value()) {
Ok(iri_ref) => {
let value = iri_ref.as_str();
quote! {
unsafe {
::iref::IriRef::new_unchecked(#value)
}
}
.into()
}
Err(_) => produce_error("invalid IRI reference"),
},
Err(e) => e.to_compile_error().into(),
}
}
fn produce_error(msg: &str) -> TokenStream {
format!("compile_error!(\"{}\")", msg).parse().unwrap()
}