tested pkg up/downcast

Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
Luca Fulchir 2024-11-11 21:16:06 +01:00
parent cfd50cf8be
commit 09cef1ff93
Signed by: luca.fulchir
GPG Key ID: 8F6440603D13A78E
4 changed files with 76 additions and 35 deletions

View File

@ -195,7 +195,7 @@ pub fn package(attrs: TokenStream, input: TokenStream) -> TokenStream {
} }
quote! { quote! {
#[derive(::bok::Package,::std::fmt::Debug)] #[derive(::bok::Package,::std::fmt::Debug, Clone)]
#ast #ast
} }
.into() .into()
@ -238,8 +238,8 @@ pub fn impl_package(_attrs: TokenStream, input: TokenStream) -> TokenStream {
} }
}; };
let version: ::syn::ImplItem = ::syn::parse_quote! { let version: ::syn::ImplItem = ::syn::parse_quote! {
fn version(&self) -> &::bok::Version { fn version(&self) -> ::bok::Version {
&self.version self.version.clone()
} }
}; };
let base: ::syn::ImplItem = ::syn::parse_quote! { let base: ::syn::ImplItem = ::syn::parse_quote! {
@ -252,6 +252,16 @@ pub fn impl_package(_attrs: TokenStream, input: TokenStream) -> TokenStream {
Some(&mut self.base) Some(&mut self.base)
} }
}; };
let any: ::syn::ImplItem = ::syn::parse_quote! {
fn as_any(&self) -> &dyn ::std::any::Any {
self
}
};
let any_mut: ::syn::ImplItem = ::syn::parse_quote! {
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
self
}
};
let hash: ::syn::ImplItem = ::syn::parse_quote! { let hash: ::syn::ImplItem = ::syn::parse_quote! {
fn hash(&self) -> ::bok::Hash { fn hash(&self) -> ::bok::Hash {
use ::sha3::{Digest}; use ::sha3::{Digest};
@ -295,6 +305,8 @@ pub fn impl_package(_attrs: TokenStream, input: TokenStream) -> TokenStream {
ast.items.push(version); ast.items.push(version);
ast.items.push(base); ast.items.push(base);
ast.items.push(base_mut); ast.items.push(base_mut);
ast.items.push(any);
ast.items.push(any_mut);
ast.items.push(hash); ast.items.push(hash);
ast.items.push(hash_code); ast.items.push(hash_code);
@ -562,12 +574,6 @@ pub fn derive_package(input: TokenStream) -> TokenStream {
} }
} }
impl #name { impl #name {
pub fn as_any(&self) -> &dyn ::std::any::Any {
self
}
pub fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
self
}
pub fn as_pkg(&self) -> &dyn ::bok::Pkg { pub fn as_pkg(&self) -> &dyn ::bok::Pkg {
self self
} }
@ -598,8 +604,19 @@ pub fn derive_package(input: TokenStream) -> TokenStream {
} }
*/ */
impl ::bok::PkgBuilder for #name_builder2 { impl ::bok::PkgBuilder for #name_builder2 {
type Package = #name; fn name(&self) -> ::bok::PkgName {
fn default_unused(&mut self) -> &mut dyn ::bok::PkgBuilder<Package = #name> { use ::bok::Pkg;
#name::default().name()
}
fn path(&self) -> ::bok::Path<::bok::PkgName> {
use ::bok::Pkg;
#name::default().path()
}
fn version(&self) -> ::bok::Version {
use ::bok::Pkg;
#name::default().version()
}
fn default_unused(&mut self) -> &mut dyn ::bok::PkgBuilder {
let def = #name::default(); let def = #name::default();
#(if self.#non_opt_fields5.is_none() { #(if self.#non_opt_fields5.is_none() {
self.#non_opt_fields5 = Some(def.#non_opt_fields5); self.#non_opt_fields5 = Some(def.#non_opt_fields5);
@ -607,18 +624,18 @@ pub fn derive_package(input: TokenStream) -> TokenStream {
self self
} }
fn build(&mut self) -> Result<#name, ::std::boxed::Box<dyn ::std::error::Error>> { fn build(&mut self) -> Result<Box<dyn ::bok::Pkg>, ::std::boxed::Box<dyn ::std::error::Error>> {
#(if self.#non_opt_fields2.is_none() { #(if self.#non_opt_fields2.is_none() {
return ::std::result::Result::Err("unset field".into()); return ::std::result::Result::Err("unset field".into());
})* })*
Ok( Ok(
#name { Box::new(#name {
// FIXME: user must be able to override. Trait? // FIXME: user must be able to override. Trait?
base: #base_type::default(), base: #base_type::default(),
version: #name::default().version, version: #name::default().version,
#(#non_opt_fields3 : self.#non_opt_fields3.clone().unwrap(),)* #(#non_opt_fields3 : self.#non_opt_fields3.clone().unwrap(),)*
#(#opt_fields2 : self.#opt_fields2.clone(),)* #(#opt_fields2 : self.#opt_fields2.clone(),)*
} })
) )
} }
} }
@ -629,10 +646,10 @@ pub fn derive_package(input: TokenStream) -> TokenStream {
pub fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any { pub fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
self self
} }
pub fn as_builder(&self) -> &dyn ::bok::PkgBuilder<Package = #name> { pub fn as_builder(&self) -> &dyn ::bok::PkgBuilder {
self self
} }
pub fn as_builder_mut(&mut self) -> &mut dyn ::bok::PkgBuilder<Package = #name> { pub fn as_builder_mut(&mut self) -> &mut dyn ::bok::PkgBuilder {
self self
} }
#(pub fn #non_opt_fields4 (&mut self, val : #non_opt_types2) -> &mut Self { #(pub fn #non_opt_fields4 (&mut self, val : #non_opt_types2) -> &mut Self {

View File

@ -58,9 +58,12 @@ impl Pkgs2 {
/// override the package `two` options from the base repostiory (Pkgs1) /// override the package `two` options from the base repostiory (Pkgs1)
pub fn two(&self) -> Two { pub fn two(&self) -> Two {
use ::bok::PkgBuilder; use ::bok::PkgBuilder;
Two::builder() let pkg: Box<dyn ::bok::Pkg> = Two::builder()
.my_attr(42) .my_attr(42)
.build() .build()
.expect("Can't build package Two") .expect("Can't build package Two");
let two = pkg.as_any().downcast_ref::<Two>().unwrap();
two.clone()
} }
} }

View File

@ -21,18 +21,19 @@ use ::std::{
vec::Vec, vec::Vec,
}; };
use crate::{Path, Pkg, PkgName, RepoName, Repository}; use crate::{Path, PkgBuilder, PkgName, RepoName, Repository};
#[derive(Debug, ::thiserror::Error)] #[derive(Debug, ::thiserror::Error)]
pub enum Error { pub enum Error {
#[error("package already present")] #[error("package already present")]
AlreadyPresent((Arc<dyn Repository>, ArcLock<dyn Pkg>)), AlreadyPresent((Arc<dyn Repository>, ArcLock<dyn PkgBuilder>)),
#[error("not found")] #[error("not found")]
NotFound, NotFound,
} }
type ArcLock<T> = Arc<RwLock<T>>; type ArcLock<T> = Arc<RwLock<T>>;
type PkgMap = BTreeMap<Path<PkgName>, (Arc<dyn Repository>, ArcLock<dyn Pkg>)>; type PkgMap =
BTreeMap<Path<PkgName>, (Arc<dyn Repository>, ArcLock<dyn PkgBuilder>)>;
/// Collection of packages, subset of what is present on one repository only /// Collection of packages, subset of what is present on one repository only
pub struct Collection { pub struct Collection {
@ -51,7 +52,7 @@ impl Collection {
pub fn add_pkg( pub fn add_pkg(
&self, &self,
r: Arc<dyn Repository>, r: Arc<dyn Repository>,
p: ArcLock<dyn Pkg>, p: ArcLock<dyn PkgBuilder>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let repo_name = r.path(); let repo_name = r.path();
let mut repos = self.repos.write().unwrap(); let mut repos = self.repos.write().unwrap();
@ -85,7 +86,7 @@ impl Collection {
pub fn find( pub fn find(
&self, &self,
pkg_path: Path<PkgName>, pkg_path: Path<PkgName>,
) -> Result<(Arc<dyn Repository>, ArcLock<dyn Pkg>), Error> { ) -> Result<(Arc<dyn Repository>, ArcLock<dyn PkgBuilder>), Error> {
let repos_pkgs = self.repos_pkgs.read().unwrap(); let repos_pkgs = self.repos_pkgs.read().unwrap();
for (_, pkg_map) in repos_pkgs.iter() { for (_, pkg_map) in repos_pkgs.iter() {
match pkg_map.get(&pkg_path) { match pkg_map.get(&pkg_path) {
@ -101,7 +102,7 @@ impl Collection {
&self, &self,
repo_path: Path<RepoName>, repo_path: Path<RepoName>,
pkg_path: Path<PkgName>, pkg_path: Path<PkgName>,
) -> Result<(Arc<dyn Repository>, ArcLock<dyn Pkg>), Error> { ) -> Result<(Arc<dyn Repository>, ArcLock<dyn PkgBuilder>), Error> {
let repos_pkgs = self.repos_pkgs.read().unwrap(); let repos_pkgs = self.repos_pkgs.read().unwrap();
match repos_pkgs.get(&repo_path) { match repos_pkgs.get(&repo_path) {
None => Err(Error::NotFound), None => Err(Error::NotFound),

View File

@ -20,6 +20,10 @@ mod collection;
mod names; mod names;
pub use collection::Collection; pub use collection::Collection;
pub use names::{Path, PkgName, RepoName}; pub use names::{Path, PkgName, RepoName};
mod deps {
pub struct Build(pub crate::Collection);
pub struct Runtime(pub crate::Collection);
}
pub use ::bok_macro::{ pub use ::bok_macro::{
impl_package, package, pkg_fn_to_code, repository, Package, Repository, impl_package, package, pkg_fn_to_code, repository, Package, Repository,
@ -86,7 +90,7 @@ macro_rules! packages {
} }
/// Marks your struct as a repository /// Marks your struct as a repository
pub trait Repository: ::std::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>;
} }
@ -114,9 +118,19 @@ pub trait Pkg:
{ {
fn name(&self) -> PkgName; fn name(&self) -> PkgName;
fn path(&self) -> Path<PkgName>; fn path(&self) -> Path<PkgName>;
fn version(&self) -> &Version; fn version(&self) -> Version;
fn base(&self) -> ::core::option::Option<&dyn Pkg>; fn base(&self) -> ::core::option::Option<&dyn Pkg>;
fn base_mut(&mut self) -> ::core::option::Option<&mut dyn Pkg>; fn base_mut(&mut self) -> ::core::option::Option<&mut dyn Pkg>;
fn as_any(&self) -> &dyn ::std::any::Any;
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any;
/*
fn dependencies_set(
&self,
repo: Arc<dyn Repository>,
build: &deps::Build,
runtime: &deps::Runtime,
) -> Result<(), ()>;
*/
fn prepare(&self) -> ::core::result::Result<(), ()> { fn prepare(&self) -> ::core::result::Result<(), ()> {
self.base().unwrap().prepare() self.base().unwrap().prepare()
} }
@ -168,17 +182,17 @@ pub trait Pkg:
fn hash_code(&self) -> Hash; fn hash_code(&self) -> Hash;
} }
pub trait PkgBuilder: ::std::any::Any { pub trait PkgBuilder: ::core::fmt::Debug + ::std::any::Any {
type Package; fn name(&self) -> crate::PkgName;
fn default_unused( fn path(&self) -> crate::Path<crate::PkgName>;
&mut self, fn version(&self) -> crate::Version;
) -> &mut dyn PkgBuilder<Package = Self::Package>; fn default_unused(&mut self) -> &mut dyn crate::PkgBuilder;
fn build( fn build(
&mut self, &mut self,
) -> Result<Self::Package, ::std::boxed::Box<dyn ::std::error::Error>>; ) -> Result<Box<dyn Pkg>, ::std::boxed::Box<dyn ::std::error::Error>>;
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct PkgEmpty { pub struct PkgEmpty {
version: Version, version: Version,
} }
@ -216,8 +230,8 @@ impl Pkg for PkgEmpty {
fn path(&self) -> Path<PkgName> { fn path(&self) -> Path<PkgName> {
"::bok::Pkg::PkgEmpty".into() "::bok::Pkg::PkgEmpty".into()
} }
fn version(&self) -> &Version { fn version(&self) -> Version {
&self.version self.version.clone()
} }
fn base(&self) -> Option<&dyn Pkg> { fn base(&self) -> Option<&dyn Pkg> {
None None
@ -225,6 +239,12 @@ impl Pkg for PkgEmpty {
fn base_mut(&mut self) -> Option<&mut dyn Pkg> { fn base_mut(&mut self) -> Option<&mut dyn Pkg> {
None None
} }
fn as_any(&self) -> &dyn ::std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
self
}
fn prepare(&self) -> ::core::result::Result<(), ()> { fn prepare(&self) -> ::core::result::Result<(), ()> {
::core::result::Result::Ok(()) ::core::result::Result::Ok(())
} }