radicle_git_ref_format/
lib.rs1mod check;
27pub use check::{Error, Options, ref_format as check_ref_format};
28
29mod deriv;
30pub use deriv::{Namespaced, Qualified};
31
32pub mod lit;
33
34pub mod name;
35#[cfg(feature = "percent-encoding")]
36pub use name::PercentEncode;
37pub use name::{Component, RefStr, RefString};
38
39pub mod refspec;
40pub use refspec::DuplicateGlob;
41
42#[cfg(feature = "minicbor")]
43mod cbor;
44
45#[cfg(feature = "serde")]
46mod serde;
47
48#[cfg(any(feature = "macro", test))]
54#[macro_export]
55macro_rules! refname {
56 ($arg:literal) => {{
57 use $crate::RefString;
58
59 #[cfg(debug_assertions)]
60 {
61 RefString::try_from($arg).expect(core::concat!(
62 "literal `",
63 $arg,
64 "` must be a valid reference name"
65 ))
66 }
67
68 #[cfg(not(debug_assertions))]
69 {
70 extern crate alloc;
71
72 use alloc::string::String;
73
74 let s: String = $arg.to_owned();
75 unsafe { core::mem::transmute::<_, RefString>(s) }
76 }
77 }};
78}
79
80#[cfg(any(feature = "macro", test))]
86#[macro_export]
87macro_rules! qualified {
88 ($arg:literal) => {{
89 use $crate::Qualified;
90
91 #[cfg(debug_assertions)]
92 {
93 Qualified::from_refstr($crate::refname!($arg)).expect(core::concat!(
94 "literal `",
95 $arg,
96 "` must be of the form 'refs/<category>/<name>'"
97 ))
98 }
99
100 #[cfg(not(debug_assertions))]
101 {
102 extern crate alloc;
103
104 use core::mem::transmute;
105
106 use alloc::borrow::Cow;
107 use alloc::string::String;
108
109 use $crate::{RefStr, RefString};
110
111 let s: String = $arg.to_owned();
112 let refstring: RefString = unsafe { transmute(s) };
113 let cow: Cow<'_, RefStr> = Cow::Owned(refstring);
114 let qualified: Qualified = unsafe { transmute(cow) };
115
116 qualified
117 }
118 }};
119}
120
121#[cfg(any(feature = "macro", test))]
127#[macro_export]
128macro_rules! component {
129 ($arg:literal) => {{
130 use $crate::Component;
131
132 #[cfg(debug_assertions)]
133 {
134 Component::from_refstr($crate::refname!($arg)).expect(core::concat!(
135 "literal `",
136 $arg,
137 "` must be a valid component (cannot contain '/')"
138 ))
139 }
140
141 #[cfg(not(debug_assertions))]
142 {
143 extern crate alloc;
144
145 use core::mem::transmute;
146
147 use alloc::borrow::Cow;
148 use alloc::string::String;
149
150 use $crate::{RefStr, RefString};
151
152 let s: String = $arg.to_owned();
153 let refstring: RefString = unsafe { transmute(s) };
154 let cow: Cow<'_, RefStr> = Cow::Owned(refstring);
155 let component: Component = unsafe { transmute(cow) };
156
157 component
158 }
159 }};
160}
161
162#[cfg(any(feature = "macro", test))]
168#[macro_export]
169macro_rules! pattern {
170 ($arg:literal) => {{
171 use $crate::refspec::PatternString;
172
173 #[cfg(debug_assertions)]
174 {
175 PatternString::try_from($arg).expect(core::concat!(
176 "literal `",
177 $arg,
178 "` must be a valid refspec pattern"
179 ))
180 }
181
182 #[cfg(not(debug_assertions))]
183 {
184 extern crate alloc;
185
186 use alloc::string::String;
187
188 let s: String = $arg.to_owned();
189 unsafe { core::mem::transmute::<_, PatternString>(s) }
190 }
191 }};
192}
193
194#[cfg(any(feature = "macro", test))]
200#[macro_export]
201macro_rules! qualified_pattern {
202 ($arg:literal) => {{
203 use $crate::refspec::QualifiedPattern;
204
205 #[cfg(debug_assertions)]
206 {
207 use core::concat;
208
209 use $crate::refspec::PatternStr;
210
211 let pattern = PatternStr::try_from_str($arg).expect(concat!(
212 "literal `",
213 $arg,
214 "` must be a valid refspec pattern"
215 ));
216
217 QualifiedPattern::from_patternstr(pattern).expect(concat!(
218 "literal `",
219 $arg,
220 "` must be a valid qualified refspec pattern"
221 ))
222 }
223
224 #[cfg(not(debug_assertions))]
225 {
226 extern crate alloc;
227
228 use core::mem::transmute;
229
230 use alloc::borrow::Cow;
231 use alloc::string::String;
232
233 use $crate::refspec::{PatternStr, PatternString};
234
235 let s: String = $arg.to_owned();
236 let pattern: PatternString = unsafe { transmute(s) };
237 let cow: Cow<'_, PatternStr> = Cow::Owned(pattern);
238 let qualified: QualifiedPattern = unsafe { transmute(cow) };
239
240 qualified
241 }
242 }};
243}
244
245#[cfg(test)]
246mod test {
247 #[test]
248 fn refname() {
249 let _ = crate::refname!("refs/heads/main");
250 let _ = crate::refname!("refs/tags/v1.0.0");
251 let _ = crate::refname!("refs/remotes/origin/main");
252 let _ = crate::refname!("a");
253 }
254
255 #[test]
256 #[should_panic]
257 fn refname_invalid() {
258 let _ = crate::refname!("a~b");
259 }
260
261 #[test]
262 fn qualified() {
263 let _ = crate::qualified!("refs/heads/main");
264 let _ = crate::qualified!("refs/tags/v1.0.0");
265 let _ = crate::qualified!("refs/remotes/origin/main");
266 }
267
268 #[test]
269 #[should_panic]
270 fn qualified_invalid() {
271 let _ = crate::qualified!("a");
272 }
273
274 #[test]
275 fn component() {
276 let _ = crate::component!("a");
277 }
278
279 #[test]
280 #[should_panic]
281 fn component_invalid() {
282 let _ = crate::component!("a/b");
283 }
284
285 #[test]
286 fn pattern() {
287 let _ = crate::pattern!("refs/heads/main");
288 let _ = crate::pattern!("refs/tags/v1.0.0");
289 let _ = crate::pattern!("refs/remotes/origin/main");
290
291 let _ = crate::pattern!("a");
292 let _ = crate::pattern!("a/*");
293 let _ = crate::pattern!("*");
294 let _ = crate::pattern!("a/b*");
295 let _ = crate::pattern!("a/b*/c");
296 let _ = crate::pattern!("a/*/c");
297 }
298
299 #[test]
300 fn qualified_pattern() {
301 let _ = crate::qualified_pattern!("refs/heads/main");
302 let _ = crate::qualified_pattern!("refs/tags/v1.0.0");
303 let _ = crate::qualified_pattern!("refs/remotes/origin/main");
304
305 let _ = crate::qualified_pattern!("refs/heads/main/*");
306 let _ = crate::qualified_pattern!("refs/tags/v*");
307 let _ = crate::qualified_pattern!("refs/remotes/origin/main");
308 let _ = crate::qualified_pattern!("refs/remotes/origin/department/*/person");
309 }
310
311 #[test]
312 #[should_panic]
313 fn qualified_pattern_invalid() {
314 let _ = crate::qualified_pattern!("a/*/b");
315 }
316}