#[macro_use]
extern crate proc_macro_error;
use std::convert::TryInto;
use proc_macro::TokenStream;
use proc_macro_error::abort;
use quote::quote;
use syn::{parse_macro_input, LitStr};
use git_ref_format_core::{refspec::PatternStr, Component, Error, Qualified, RefStr};
#[proc_macro_error]
#[proc_macro]
pub fn refname(input: TokenStream) -> TokenStream {
let lit = parse_macro_input!(input as LitStr);
let val = lit.value();
let parsed: Result<&RefStr, Error> = val.as_str().try_into();
match parsed {
Ok(safe) => {
let safe: &str = safe.as_str();
let expand = quote! {
unsafe {
use ::std::mem::transmute;
use ::radicle_git_ext::ref_format::RefString;
transmute::<_, RefString>(#safe.to_owned())
}
};
TokenStream::from(expand)
}
Err(e) => {
abort!(lit.span(), "invalid refname literal: {}", e);
}
}
}
#[proc_macro_error]
#[proc_macro]
pub fn qualified(input: TokenStream) -> TokenStream {
let lit = parse_macro_input!(input as LitStr);
let val = lit.value();
let parsed: Result<&RefStr, Error> = val.as_str().try_into();
match parsed {
Ok(name) => {
let qualified: Option<Qualified> = Qualified::from_refstr(name);
match qualified {
Some(safe) => {
let safe: &str = safe.as_str();
let expand = quote! {
unsafe {
use ::std::{borrow::Cow, mem::transmute};
use ::radicle_git_ext::ref_format::{Component, RefStr, RefString, Qualified};
let inner: RefString = transmute(#safe.to_owned());
let cow: Cow<'static, RefStr> = Cow::Owned(inner);
transmute::<_, Qualified>(cow)
}
};
TokenStream::from(expand)
}
None => {
abort!(
lit.span(),
"refname is not of the form 'refs/<category>/<name>'"
);
}
}
}
Err(e) => {
abort!(lit.span(), "invalid refname literal: {}", e);
}
}
}
#[proc_macro_error]
#[proc_macro]
pub fn component(input: TokenStream) -> TokenStream {
let lit = parse_macro_input!(input as LitStr);
let val = lit.value();
let name: Result<&RefStr, Error> = val.as_str().try_into();
match name {
Ok(name) => {
let comp: Option<Component> = name.into();
match comp {
Some(safe) => {
let safe: &str = safe.as_ref().as_str();
let expand = quote! {
unsafe {
use ::std::{borrow::Cow, mem::transmute};
use ::radicle_git_ext::ref_format::{Component, RefStr, RefString};
let inner: RefString = transmute(#safe.to_owned());
let cow: Cow<'static, RefStr> = Cow::Owned(inner);
transmute::<_, Component>(cow)
}
};
TokenStream::from(expand)
}
None => {
abort!(lit.span(), "component contains a '/'");
}
}
}
Err(e) => {
abort!(lit.span(), "invalid refname literal: {}", e);
}
}
}
#[proc_macro_error]
#[proc_macro]
pub fn pattern(input: TokenStream) -> TokenStream {
let lit = parse_macro_input!(input as LitStr);
let val = lit.value();
let parsed: Result<&PatternStr, Error> = val.as_str().try_into();
match parsed {
Ok(safe) => {
let safe: &str = safe.as_str();
let expand = quote! {
unsafe {
use ::std::mem::transmute;
use ::radicle_git_ext::ref_format::refspec::PatternString;
transmute::<_, PatternString>(#safe.to_owned())
}
};
TokenStream::from(expand)
}
Err(e) => {
abort!(lit.span(), "invalid refspec pattern literal: {}", e);
}
}
}
#[proc_macro_error]
#[proc_macro]
pub fn qualified_pattern(input: TokenStream) -> TokenStream {
let lit = parse_macro_input!(input as LitStr);
let val = lit.value();
let parsed: Result<&PatternStr, Error> = val.as_str().try_into();
match parsed {
Ok(safe) => {
let safe: &str = safe.as_str();
let expand = quote! {
unsafe {
use ::std::mem::transmute;
use ::radicle_git_ext::ref_format::refspec::QualifiedPattern;
transmute::<_, QualifiedPattern>(#safe.to_owned())
}
};
TokenStream::from(expand)
}
Err(e) => {
abort!(lit.span(), "invalid refspec pattern literal: {}", e);
}
}
}