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