repo: get list of pkgs and boxed pkg
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
f08ae227a2
commit
631c3a19e5
@ -278,7 +278,72 @@ pub(crate) fn derive_repository(input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
let name = input.ident.clone();
|
let name = input.ident.clone();
|
||||||
|
|
||||||
let expanded = quote! {
|
let ::syn::Data::Struct(items) = &input.data else {
|
||||||
|
use ::syn::spanned::Spanned;
|
||||||
|
return ::syn::Error::new(
|
||||||
|
input.span(),
|
||||||
|
"#[derive(::bok::Repository)]: not called on a struct",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
};
|
||||||
|
|
||||||
|
if items
|
||||||
|
.fields
|
||||||
|
.iter()
|
||||||
|
.find(|&f| {
|
||||||
|
f.ident
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|id| id.to_string() == "_bok_repo")
|
||||||
|
})
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
use ::syn::spanned::Spanned;
|
||||||
|
return ::syn::Error::new(
|
||||||
|
input.span(),
|
||||||
|
"#[derive(::bok::Repository)]: struct is not a bok repo. use \
|
||||||
|
`#[::bok::repository(..)]` first",
|
||||||
|
)
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
// holds the list of all package names, snake case
|
||||||
|
let mut all_pkgs =
|
||||||
|
Vec::<(String, ::syn::Path)>::with_capacity(items.fields.len());
|
||||||
|
|
||||||
|
for it in items.fields.iter() {
|
||||||
|
let Some(id) = &it.ident else { continue };
|
||||||
|
let id_str = id.to_string();
|
||||||
|
if id_str.starts_with("_p_") {
|
||||||
|
let path = {
|
||||||
|
let ::syn::Type::Path(phantom_path) = &it.ty else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
let segment = phantom_path.path.segments.last().unwrap();
|
||||||
|
let ::syn::PathArguments::AngleBracketed(bracketed) =
|
||||||
|
&segment.arguments
|
||||||
|
else {
|
||||||
|
panic!("derive: phantom without anglebracket?");
|
||||||
|
};
|
||||||
|
let ::syn::GenericArgument::Type(::syn::Type::Path(t)) =
|
||||||
|
bracketed.args.first().expect("phantom bracketed, no args")
|
||||||
|
else {
|
||||||
|
panic!(
|
||||||
|
"derive: phantom bracketed, generic not a type path"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
t.path.clone()
|
||||||
|
};
|
||||||
|
let name = id_str.strip_prefix("_p_").unwrap().to_owned();
|
||||||
|
all_pkgs.push((name, path));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
all_pkgs.sort_by(|a, b| a.0.cmp(&b.0));
|
||||||
|
let pkgs_num: usize = all_pkgs.len();
|
||||||
|
let (pkg_names, pkg_types): (Vec<String>, Vec<::syn::Path>) =
|
||||||
|
all_pkgs.into_iter().map(|(a, b)| (a, b)).unzip();
|
||||||
|
|
||||||
|
quote! {
|
||||||
impl ::bok::Repository for #name {
|
impl ::bok::Repository for #name {
|
||||||
fn name(&self) -> ::bok::RepoName {
|
fn name(&self) -> ::bok::RepoName {
|
||||||
(module_path!().to_owned() + "::" + ::std::stringify!(#name)).as_str().into()
|
(module_path!().to_owned() + "::" + ::std::stringify!(#name)).as_str().into()
|
||||||
@ -286,10 +351,22 @@ pub(crate) fn derive_repository(input: TokenStream) -> TokenStream {
|
|||||||
fn path(&self) -> ::bok::Path<::bok::RepoName> {
|
fn path(&self) -> ::bok::Path<::bok::RepoName> {
|
||||||
(module_path!().to_owned() + "::" + ::std::stringify!(#name)).as_str().into()
|
(module_path!().to_owned() + "::" + ::std::stringify!(#name)).as_str().into()
|
||||||
}
|
}
|
||||||
|
fn pkg_list(&self) -> &[&'static str] {
|
||||||
|
const PKGS : [&'static str; #pkgs_num] = [
|
||||||
|
#(#pkg_names),
|
||||||
|
*
|
||||||
|
];
|
||||||
|
&PKGS
|
||||||
}
|
}
|
||||||
};
|
fn get(&self, pkg_name: &str) -> Option<::std::boxed::Box<dyn ::bok::Pkg>> {
|
||||||
|
match pkg_name {
|
||||||
TokenStream::from(expanded)
|
#(#pkg_names => Some(::std::boxed::Box::new(#pkg_types::default())),)
|
||||||
|
*
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.into()
|
||||||
}
|
}
|
||||||
struct PathList(Vec<::syn::Path>);
|
struct PathList(Vec<::syn::Path>);
|
||||||
|
|
||||||
|
@ -50,6 +50,8 @@ macro_rules! moduse {
|
|||||||
pub trait Repository: ::core::fmt::Debug {
|
pub trait Repository: ::core::fmt::Debug {
|
||||||
fn name(&self) -> RepoName;
|
fn name(&self) -> RepoName;
|
||||||
fn path(&self) -> Path<RepoName>;
|
fn path(&self) -> Path<RepoName>;
|
||||||
|
fn pkg_list(&self) -> &[&'static str];
|
||||||
|
fn get(&self, pkg_name: &str) -> Option<::std::boxed::Box<dyn Pkg>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is an empty Package List.
|
/// This is an empty Package List.
|
||||||
@ -66,6 +68,13 @@ impl Repository for RepositoryEmpty {
|
|||||||
fn path(&self) -> Path<RepoName> {
|
fn path(&self) -> Path<RepoName> {
|
||||||
"::bok::RepositoryEmpty".into()
|
"::bok::RepositoryEmpty".into()
|
||||||
}
|
}
|
||||||
|
fn pkg_list(&self) -> &[&'static str] {
|
||||||
|
const PKGS: [&'static str; 0] = [];
|
||||||
|
&PKGS
|
||||||
|
}
|
||||||
|
fn get(&self, _pkg_name: &str) -> Option<::std::boxed::Box<dyn Pkg>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Print the code of the package
|
/// Print the code of the package
|
||||||
|
Loading…
Reference in New Issue
Block a user