Radish alpha
r
rad:z6cFWeWpnZNHh9rUW8phgA3b5yGt
Git libraries for Radicle
Radicle
Git
Merge remote-tracking branch 'origin/macro/qualified'
Fintan Halpenny committed 3 years ago
commit 8d65feb80d6a9ad1b8cb2bd5e7af2eea23963dc5
parent 0cec6b5
3 files changed +65 -2
modified git-ref-format/macro/src/lib.rs
@@ -13,7 +13,7 @@ use proc_macro_error::abort;
use quote::quote;
use syn::{parse_macro_input, LitStr};

-
use git_ref_format_core::{refspec::PatternStr, Component, Error, RefStr};
+
use git_ref_format_core::{refspec::PatternStr, Component, Error, Qualified, RefStr};

/// Create a [`git_ref_format_core::RefString`] from a string literal.
///
@@ -46,6 +46,52 @@ pub fn refname(input: TokenStream) -> TokenStream {
    }
}

+
/// Create a [`git_ref_format_core::Qualified`] from a string literal.
+
///
+
/// The string is validated at compile time, and an unsafe conversion is
+
/// emitted.
+
#[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 ::git_ref_format::{Component, RefStr, RefString};
+

+
                            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);
+
        },
+
    }
+
}
+

/// Create a [`git_ref_format_core::Component`] from a string literal.
///
/// The string is validated at compile time, and an unsafe conversion is
modified git-ref-format/src/lib.rs
@@ -145,6 +145,8 @@ pub mod name {
}

#[cfg(any(feature = "macro", feature = "git-ref-format-macro"))]
+
pub use git_ref_format_macro::qualified;
+
#[cfg(any(feature = "macro", feature = "git-ref-format-macro"))]
pub use git_ref_format_macro::refname;

pub mod refspec {
modified git-ref-format/t/src/tests.rs
@@ -1,7 +1,17 @@
// Copyright © 2022 The Radicle Link Contributors
// SPDX-License-Identifier: GPL-3.0-or-later

-
use git_ref_format::{component, name, refname, refspec, Error, Qualified, RefStr, RefString};
+
use git_ref_format::{
+
    component,
+
    name,
+
    qualified,
+
    refname,
+
    refspec,
+
    Error,
+
    Qualified,
+
    RefStr,
+
    RefString,
+
};

#[test]
fn refname_macro_works() {
@@ -9,6 +19,11 @@ fn refname_macro_works() {
}

#[test]
+
fn qualified_macro_works() {
+
    assert_eq!("refs/heads/main", qualified!("refs/heads/main").as_str())
+
}
+

+
#[test]
fn component_macro_works() {
    assert_eq!("self", name::component!("self").as_str())
}