git_ref_format_macro/
lib.rs1#[macro_use]
2extern crate proc_macro_error2;
3
4use std::convert::TryInto;
5
6use proc_macro::TokenStream;
7use proc_macro_error2::abort;
8use quote::quote;
9use syn::{parse_macro_input, LitStr};
10
11use git_ref_format_core::{refspec::PatternStr, Component, Error, Qualified, RefStr};
12
13#[proc_macro_error]
18#[proc_macro]
19pub fn refname(input: TokenStream) -> TokenStream {
20 let lit = parse_macro_input!(input as LitStr);
21 let val = lit.value();
22
23 let parsed: Result<&RefStr, Error> = val.as_str().try_into();
24 match parsed {
25 Ok(safe) => {
26 let safe: &str = safe.as_str();
27 let expand = quote! {
28 unsafe {
29 use ::std::mem::transmute;
30 use ::radicle_git_ext::ref_format::RefString;
31
32 transmute::<_, RefString>(#safe.to_owned())
33 }
34 };
35 TokenStream::from(expand)
36 }
37
38 Err(e) => {
39 abort!(lit.span(), "invalid refname literal: {}", e);
40 }
41 }
42}
43
44#[proc_macro_error]
49#[proc_macro]
50pub fn qualified(input: TokenStream) -> TokenStream {
51 let lit = parse_macro_input!(input as LitStr);
52 let val = lit.value();
53
54 let parsed: Result<&RefStr, Error> = val.as_str().try_into();
55 match parsed {
56 Ok(name) => {
57 let qualified: Option<Qualified> = Qualified::from_refstr(name);
58 match qualified {
59 Some(safe) => {
60 let safe: &str = safe.as_str();
61 let expand = quote! {
62 unsafe {
63 use ::std::{borrow::Cow, mem::transmute};
64 use ::radicle_git_ext::ref_format::{Component, RefStr, RefString, Qualified};
65
66 let inner: RefString = transmute(#safe.to_owned());
67 let cow: Cow<'static, RefStr> = Cow::Owned(inner);
68 transmute::<_, Qualified>(cow)
69 }
70 };
71
72 TokenStream::from(expand)
73 }
74
75 None => {
76 abort!(
77 lit.span(),
78 "refname is not of the form 'refs/<category>/<name>'"
79 );
80 }
81 }
82 }
83
84 Err(e) => {
85 abort!(lit.span(), "invalid refname literal: {}", e);
86 }
87 }
88}
89
90#[proc_macro_error]
95#[proc_macro]
96pub fn component(input: TokenStream) -> TokenStream {
97 let lit = parse_macro_input!(input as LitStr);
98 let val = lit.value();
99
100 let name: Result<&RefStr, Error> = val.as_str().try_into();
101 match name {
102 Ok(name) => {
103 let comp: Option<Component> = name.into();
104 match comp {
105 Some(safe) => {
106 let safe: &str = safe.as_ref().as_str();
107 let expand = quote! {
108 unsafe {
109 use ::std::{borrow::Cow, mem::transmute};
110 use ::radicle_git_ext::ref_format::{Component, RefStr, RefString};
111
112 let inner: RefString = transmute(#safe.to_owned());
113 let cow: Cow<'static, RefStr> = Cow::Owned(inner);
114 transmute::<_, Component>(cow)
115 }
116 };
117
118 TokenStream::from(expand)
119 }
120
121 None => {
122 abort!(lit.span(), "component contains a '/'");
123 }
124 }
125 }
126
127 Err(e) => {
128 abort!(lit.span(), "invalid refname literal: {}", e);
129 }
130 }
131}
132
133#[proc_macro_error]
139#[proc_macro]
140pub fn pattern(input: TokenStream) -> TokenStream {
141 let lit = parse_macro_input!(input as LitStr);
142 let val = lit.value();
143
144 let parsed: Result<&PatternStr, Error> = val.as_str().try_into();
145 match parsed {
146 Ok(safe) => {
147 let safe: &str = safe.as_str();
148 let expand = quote! {
149 unsafe {
150 use ::std::mem::transmute;
151 use ::radicle_git_ext::ref_format::refspec::PatternString;
152
153 transmute::<_, PatternString>(#safe.to_owned())
154 }
155 };
156 TokenStream::from(expand)
157 }
158
159 Err(e) => {
160 abort!(lit.span(), "invalid refspec pattern literal: {}", e);
161 }
162 }
163}
164
165#[proc_macro_error]
171#[proc_macro]
172pub fn qualified_pattern(input: TokenStream) -> TokenStream {
173 let lit = parse_macro_input!(input as LitStr);
174 let val = lit.value();
175
176 let parsed: Result<&PatternStr, Error> = val.as_str().try_into();
177 match parsed {
178 Ok(safe) => {
179 let safe: &str = safe.as_str();
180 let expand = quote! {
181 unsafe {
182 use ::std::mem::transmute;
183 use ::radicle_git_ext::ref_format::refspec::QualifiedPattern;
184
185 transmute::<_, QualifiedPattern>(#safe.to_owned())
186 }
187 };
188 TokenStream::from(expand)
189 }
190
191 Err(e) => {
192 abort!(lit.span(), "invalid refspec pattern literal: {}", e);
193 }
194 }
195}