Collection: cast to concrete type

Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
Luca Fulchir 2024-12-13 16:57:46 +01:00
parent 0c9bd1948f
commit 7beea1a36b
Signed by: luca.fulchir
GPG Key ID: 8F6440603D13A78E
8 changed files with 89 additions and 35 deletions

View File

@ -60,6 +60,7 @@ pub(crate) fn collection(
*
#(#[::bok_macro::collection_dep(#all_deps_builder)])
*
#[derive(::core::fmt::Debug)]
pub struct Collection {
repo: ::std::sync::Arc<#name>,
pkgs: ::std::sync::RwLock<

View File

@ -58,7 +58,7 @@ pub(crate) fn package(attrs: TokenStream, input: TokenStream) -> TokenStream {
|| path.segments[1].ident.to_string() != "PkgEmpty"
{
let repo_argument = {
let generic_id: ::syn::Path = ::syn::parse_quote!(id<R>);
let generic_id: ::syn::Path = ::syn::parse_quote!(id<R, C>);
generic_id.segments.last().unwrap().arguments.clone()
};
path.segments.last_mut().unwrap().arguments = repo_argument;
@ -103,7 +103,11 @@ pub(crate) fn package_path(
.into();
};
let generic_struct: ::syn::ItemStruct = ::syn::parse_quote! {
pub struct test<R> where R: ::bok::Repository + 'static {}
pub struct test<R, C>
where
R: ::bok::Repository + 'static,
C: ::bok::Collection,
{}
};
let (_, generics, where_clause) = generic_struct.generics.split_for_impl();
@ -142,9 +146,15 @@ pub(crate) fn package_path(
_bok_repo: ::std::marker::PhantomData<R>
})
.unwrap();
let collection_marker = ::syn::Field::parse_named
.parse2(quote! {
_bok_collection: ::std::marker::PhantomData<C>
})
.unwrap();
base_fields_extra.push(pkg_version);
base_fields_extra.push(base_marker);
base_fields_extra.push(repo_marker);
base_fields_extra.push(collection_marker);
}
None => {
return ::syn::Error::new(
@ -165,6 +175,7 @@ pub(crate) fn package_path(
if id.to_string() == "version"
|| id.to_string() == "_bok_base"
|| id.to_string() == "_bok_repo"
|| id.to_string() == "_bok_collection"
{
continue;
}
@ -359,8 +370,16 @@ pub(crate) fn package_impl(
"BokDeps{}",
t_id.path.segments.last().unwrap().ident
);
let trait_deps_builder = ::quote::format_ident!(
"BokBuilderDeps{}",
t_id.path.segments.last().unwrap().ident
);
let g: ::syn::ItemImpl = ::syn::parse_quote! {
impl<R> trait_name for #t_id<R> where R: ::bok::Repository + #trait_deps {}
impl<R, C> trait_name for #t_id<R, C>
where
R: #trait_deps,
C: #trait_deps_builder,
{}
};
ast.generics = g.generics;
ast.self_ty = g.self_ty;
@ -638,16 +657,30 @@ pub(crate) fn package_impl_builder(
};
Ok(actual_repo)
}?;
/*
let #arg_build = {
let build_any = #arg_build.0.as_any();
let Some(actual_build) =
build_any.downcast_ref::<#trait_deps_builder>() else {
build_any.downcast_ref::<C>() else {
return Err(());
};
Ok(::bok::deps::Build(actual_build))
Ok(actual_build)
}?;
let #arg_runtime = {
let runtime_any = #arg_runtime.0.as_any();
let Some(actual_runtime) =
runtime_any.downcast_ref::<C>() else {
return Err(());
};
Ok(actual_runtime)
}?;
let #arg_test = {
let test_any = #arg_test.0.as_any();
let Some(actual_test) =
test_any.downcast_ref::<C>() else {
return Err(());
};
Ok(actual_test)
}?;
*/
Ok(())
}
};
@ -675,6 +708,7 @@ pub(crate) fn package_impl_builder(
if id.to_string() == "version"
|| id.to_string() == "_bok_base"
|| id.to_string() == "_bok_repo"
|| id.to_string() == "_bok_collection"
{
return None;
}
@ -705,6 +739,7 @@ pub(crate) fn package_impl_builder(
if id.to_string() == "version"
|| id.to_string() == "_bok_base"
|| id.to_string() == "_bok_repo"
|| id.to_string() == "_bok_collection"
{
return None;
}
@ -735,6 +770,7 @@ pub(crate) fn package_impl_builder(
if id.to_string() == "version"
|| id.to_string() == "_bok_base"
|| id.to_string() == "_bok_repo"
|| id.to_string() == "_bok_collection"
{
return None;
}
@ -765,6 +801,7 @@ pub(crate) fn package_impl_builder(
if id.to_string() == "version"
|| id.to_string() == "_bok_base"
|| id.to_string() == "_bok_repo"
|| id.to_string() == "_bok_collection"
{
return None;
}
@ -822,30 +859,33 @@ pub(crate) fn package_impl_builder(
quote! {
#[derive(::std::default::Default, ::std::fmt::Debug)]
pub struct #name_builder<R>
pub struct #name_builder<R, C>
where
R: ::bok::Repository + 'static + #trait_deps,
R: 'static + #trait_deps,
C: 'static + #trait_deps_builder
{
_bok_repo: ::std::marker::PhantomData<R>,
_bok_collection: ::std::marker::PhantomData<C>,
#(#non_opt_fields: ::std::option::Option<#non_opt_types>,)*
#(#opt_fields: ::std::option::Option<#opt_types>,)*
}
#[::macro_magic::export_tokens(#full_export_path_name)]
impl<R> ::bok::PkgBuilder for #name_builder<R>
impl<R, C> ::bok::PkgBuilder for #name_builder<R, C>
where
R: ::bok::Repository + 'static + #trait_deps,
R: 'static + #trait_deps,
C: 'static + #trait_deps_builder,
{
fn name(&self) -> ::bok::PkgName {
use ::bok::Pkg;
#pkg_name::<R>::default().name()
#pkg_name::<R,C>::default().name()
}
fn path(&self) -> ::bok::Path<::bok::PkgName> {
use ::bok::Pkg;
#pkg_name::<R>::default().path()
#pkg_name::<R,C>::default().path()
}
fn version(&self) -> ::bok::Version {
use ::bok::Pkg;
#pkg_name::<R>::default().version()
#pkg_name::<R,C>::default().version()
}
fn as_any(&self) -> &dyn ::std::any::Any {
self
@ -854,7 +894,7 @@ pub(crate) fn package_impl_builder(
self
}
fn default_unused(&mut self) -> &mut dyn ::bok::PkgBuilder {
let def = #pkg_name::<R>::default();
let def = #pkg_name::<R,C>::default();
#(if self.#non_opt_fields5.is_none() {
self.#non_opt_fields5 = Some(def.#non_opt_fields5);
})*
@ -869,7 +909,7 @@ pub(crate) fn package_impl_builder(
#(if self.#non_opt_fields2.is_none() {
return ::std::result::Result::Err("unset field".into());
})*
let mut pkg = ::std::boxed::Box::new(#pkg_name::<R>::default());
let mut pkg = ::std::boxed::Box::new(#pkg_name::<R,C>::default());
#(pkg.#non_opt_fields3 = self.#non_opt_fields3.clone().unwrap();)
*
#(pkg.#opt_fields2 = self.#opt_fields2.clone();)
@ -879,13 +919,16 @@ pub(crate) fn package_impl_builder(
#(#local_funcs)
*
}
impl<R> #name_builder<R>
impl<R, C> #name_builder<R, C>
where
R: ::bok::Repository +'static + #trait_deps,
R: 'static + #trait_deps,
C: 'static + #trait_deps_builder,
{
// FIXME: difference from `::default()`?
pub fn new() -> Self {
Self {
_bok_repo: ::std::marker::PhantomData::default(),
_bok_collection: ::std::marker::PhantomData::default(),
#(#non_opt_fields6: None,)*
#(#opt_fields4: None,)*
}
@ -937,9 +980,10 @@ pub(crate) fn package_impl_builder(
-> ::std::result::Result<(),()>;)
*
}
impl<R> #trait_options for #name_builder<R>
impl<R, C> #trait_options for #name_builder<R, C>
where
R: ::bok::Repository +'static + #trait_deps,
R: 'static + #trait_deps,
C: 'static + #trait_deps_builder,
{
#(fn #non_opt_fields8 (&mut self, val : #non_opt_types4)
-> ::std::result::Result<(),()> {
@ -1044,10 +1088,13 @@ pub(crate) fn package_impl_base_add(
}
let trait_deps = ::quote::format_ident!("BokDeps{}", name_pkg);
let trait_deps_builder =
::quote::format_ident!("BokBuilderDeps{}", name_pkg);
let generic_struct: ::syn::ItemImpl = ::syn::parse_quote! {
impl<R> test for #name_pkg <R>
impl<R, C> test for #name_pkg<R, C>
where
R: ::bok::Repository + 'static + #trait_deps,
R: 'static + #trait_deps,
C: 'static + #trait_deps_builder,
{}
};
@ -1156,21 +1203,24 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
}
let trait_deps = ::quote::format_ident!("BokDeps{}", name);
let trait_deps_builder = ::quote::format_ident!("BokBuilderDeps{}", name);
let expanded = quote! {
impl<R> ::core::fmt::Display for #name<R>
impl<R, C> ::core::fmt::Display for #name<R, C>
where
R: ::bok::Repository + #trait_deps,
R: #trait_deps,
C: #trait_deps_builder,
{
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>)
->::core::fmt::Result
{
<#name<R> as ::bok::PkgCode>::fmt(self, f)
<#name<R, C> as ::bok::PkgCode>::fmt(self, f)
}
}
impl<R> ::bok::PkgCode for #name<R>
impl<R, C> ::bok::PkgCode for #name<R, C>
where
R: ::bok::Repository + 'static + #trait_deps,
R: 'static + #trait_deps,
C: 'static + #trait_deps_builder,
{
fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>)
->::core::fmt::Result
@ -1231,9 +1281,10 @@ pub(crate) fn derive_package(input: TokenStream) -> TokenStream {
f.write_str(&formatted)
}
}
impl<R> #name<R>
impl<R, C> #name<R, C>
where
R: ::bok::Repository + 'static + #trait_deps + ::core::default::Default,
R: 'static + #trait_deps + ::core::default::Default,
C: 'static + #trait_deps_builder,
{
pub fn as_any(&self) -> &dyn ::std::any::Any {
self

View File

@ -279,7 +279,7 @@ pub(crate) fn repo_packages(
// "#[repo_packages(my::pkg)]" -->> "#[repo_packages(my::pkg<Self>)])"
let mut rewrite = false;
let repo_argument = {
let generic_id: ::syn::Path = ::syn::parse_quote!(id<Self>);
let generic_id: ::syn::Path = ::syn::parse_quote!(id<Self, Collection>);
generic_id.segments.last().unwrap().arguments.clone()
};
for p in packages.0.iter_mut() {

View File

@ -16,6 +16,7 @@
*/
mod conf;
//mod expanded;
mod repos;
fn main() {

View File

@ -32,6 +32,7 @@ impl ::std::default::Default for One {
One {
_bok_base: ::std::marker::PhantomData::default(),
_bok_repo: ::std::marker::PhantomData::default(),
_bok_collection: ::std::marker::PhantomData::default(),
my_attr: 1,
version: ::bok::Version {
major: 0,

View File

@ -22,14 +22,13 @@ pub struct Three {
pub my_attr: u32,
}
impl<R> ::std::default::Default for Three<R>
where
R: ::bok::Repository,
{
#[::bok::package_impl]
impl ::std::default::Default for Three {
fn default() -> Self {
Three {
_bok_base: ::std::marker::PhantomData::default(),
_bok_repo: ::std::marker::PhantomData::default(),
_bok_collection: ::std::marker::PhantomData::default(),
version: ::bok::Version {
major: 0,
minor: 0,

View File

@ -28,6 +28,7 @@ impl ::std::default::Default for Two {
Two {
_bok_base: ::std::marker::PhantomData::default(),
_bok_repo: ::std::marker::PhantomData::default(),
_bok_collection: ::std::marker::PhantomData::default(),
my_attr: 2,
my_attr2: 2,
version: ::bok::Version {

View File

@ -33,7 +33,7 @@ pub type PkgMap =
BTreeMap<Path<PkgName>, (Arc<dyn Repository>, ArcLock<dyn PkgBuilder>)>;
*/
pub trait Collection: ::std::any::Any {
pub trait Collection: ::std::any::Any + ::core::fmt::Debug {
fn as_any(&self) -> &dyn ::std::any::Any;
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any;
}