diff --git a/bok-macro/src/lib.rs b/bok-macro/src/lib.rs index c24716b..968ad85 100644 --- a/bok-macro/src/lib.rs +++ b/bok-macro/src/lib.rs @@ -195,7 +195,7 @@ pub fn package(attrs: TokenStream, input: TokenStream) -> TokenStream { } quote! { - #[derive(::bok::Package,::std::fmt::Debug)] + #[derive(::bok::Package,::std::fmt::Debug, Clone)] #ast } .into() @@ -238,8 +238,8 @@ pub fn impl_package(_attrs: TokenStream, input: TokenStream) -> TokenStream { } }; let version: ::syn::ImplItem = ::syn::parse_quote! { - fn version(&self) -> &::bok::Version { - &self.version + fn version(&self) -> ::bok::Version { + self.version.clone() } }; let base: ::syn::ImplItem = ::syn::parse_quote! { @@ -252,6 +252,16 @@ pub fn impl_package(_attrs: TokenStream, input: TokenStream) -> TokenStream { 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! { fn hash(&self) -> ::bok::Hash { use ::sha3::{Digest}; @@ -295,6 +305,8 @@ pub fn impl_package(_attrs: TokenStream, input: TokenStream) -> TokenStream { ast.items.push(version); ast.items.push(base); ast.items.push(base_mut); + ast.items.push(any); + ast.items.push(any_mut); ast.items.push(hash); ast.items.push(hash_code); @@ -562,12 +574,6 @@ pub fn derive_package(input: TokenStream) -> TokenStream { } } 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 { self } @@ -598,8 +604,19 @@ pub fn derive_package(input: TokenStream) -> TokenStream { } */ impl ::bok::PkgBuilder for #name_builder2 { - type Package = #name; - fn default_unused(&mut self) -> &mut dyn ::bok::PkgBuilder { + fn name(&self) -> ::bok::PkgName { + 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(); #(if self.#non_opt_fields5.is_none() { self.#non_opt_fields5 = Some(def.#non_opt_fields5); @@ -607,18 +624,18 @@ pub fn derive_package(input: TokenStream) -> TokenStream { self } - fn build(&mut self) -> Result<#name, ::std::boxed::Box> { + fn build(&mut self) -> Result, ::std::boxed::Box> { #(if self.#non_opt_fields2.is_none() { return ::std::result::Result::Err("unset field".into()); })* Ok( - #name { + Box::new(#name { // FIXME: user must be able to override. Trait? base: #base_type::default(), version: #name::default().version, #(#non_opt_fields3 : self.#non_opt_fields3.clone().unwrap(),)* #(#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 { self } - pub fn as_builder(&self) -> &dyn ::bok::PkgBuilder { + pub fn as_builder(&self) -> &dyn ::bok::PkgBuilder { self } - pub fn as_builder_mut(&mut self) -> &mut dyn ::bok::PkgBuilder { + pub fn as_builder_mut(&mut self) -> &mut dyn ::bok::PkgBuilder { self } #(pub fn #non_opt_fields4 (&mut self, val : #non_opt_types2) -> &mut Self { diff --git a/bok-utils/src/pkgs/mod.rs b/bok-utils/src/pkgs/mod.rs index efee455..2bf432b 100644 --- a/bok-utils/src/pkgs/mod.rs +++ b/bok-utils/src/pkgs/mod.rs @@ -58,9 +58,12 @@ impl Pkgs2 { /// override the package `two` options from the base repostiory (Pkgs1) pub fn two(&self) -> Two { use ::bok::PkgBuilder; - Two::builder() + let pkg: Box = Two::builder() .my_attr(42) .build() - .expect("Can't build package Two") + .expect("Can't build package Two"); + + let two = pkg.as_any().downcast_ref::().unwrap(); + two.clone() } } diff --git a/bok/src/collection.rs b/bok/src/collection.rs index 75bce07..5981168 100644 --- a/bok/src/collection.rs +++ b/bok/src/collection.rs @@ -21,18 +21,19 @@ use ::std::{ vec::Vec, }; -use crate::{Path, Pkg, PkgName, RepoName, Repository}; +use crate::{Path, PkgBuilder, PkgName, RepoName, Repository}; #[derive(Debug, ::thiserror::Error)] pub enum Error { #[error("package already present")] - AlreadyPresent((Arc, ArcLock)), + AlreadyPresent((Arc, ArcLock)), #[error("not found")] NotFound, } type ArcLock = Arc>; -type PkgMap = BTreeMap, (Arc, ArcLock)>; +type PkgMap = + BTreeMap, (Arc, ArcLock)>; /// Collection of packages, subset of what is present on one repository only pub struct Collection { @@ -51,7 +52,7 @@ impl Collection { pub fn add_pkg( &self, r: Arc, - p: ArcLock, + p: ArcLock, ) -> Result<(), Error> { let repo_name = r.path(); let mut repos = self.repos.write().unwrap(); @@ -85,7 +86,7 @@ impl Collection { pub fn find( &self, pkg_path: Path, - ) -> Result<(Arc, ArcLock), Error> { + ) -> Result<(Arc, ArcLock), Error> { let repos_pkgs = self.repos_pkgs.read().unwrap(); for (_, pkg_map) in repos_pkgs.iter() { match pkg_map.get(&pkg_path) { @@ -101,7 +102,7 @@ impl Collection { &self, repo_path: Path, pkg_path: Path, - ) -> Result<(Arc, ArcLock), Error> { + ) -> Result<(Arc, ArcLock), Error> { let repos_pkgs = self.repos_pkgs.read().unwrap(); match repos_pkgs.get(&repo_path) { None => Err(Error::NotFound), diff --git a/bok/src/lib.rs b/bok/src/lib.rs index 1ddfd1a..cd4d2db 100644 --- a/bok/src/lib.rs +++ b/bok/src/lib.rs @@ -20,6 +20,10 @@ mod collection; mod names; pub use collection::Collection; pub use names::{Path, PkgName, RepoName}; +mod deps { + pub struct Build(pub crate::Collection); + pub struct Runtime(pub crate::Collection); +} pub use ::bok_macro::{ impl_package, package, pkg_fn_to_code, repository, Package, Repository, @@ -86,7 +90,7 @@ macro_rules! packages { } /// Marks your struct as a repository -pub trait Repository: ::std::fmt::Debug { +pub trait Repository: ::core::fmt::Debug { fn name(&self) -> RepoName; fn path(&self) -> Path; } @@ -114,9 +118,19 @@ pub trait Pkg: { fn name(&self) -> PkgName; fn path(&self) -> Path; - fn version(&self) -> &Version; + fn version(&self) -> Version; fn base(&self) -> ::core::option::Option<&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, + build: &deps::Build, + runtime: &deps::Runtime, + ) -> Result<(), ()>; + */ fn prepare(&self) -> ::core::result::Result<(), ()> { self.base().unwrap().prepare() } @@ -168,17 +182,17 @@ pub trait Pkg: fn hash_code(&self) -> Hash; } -pub trait PkgBuilder: ::std::any::Any { - type Package; - fn default_unused( - &mut self, - ) -> &mut dyn PkgBuilder; +pub trait PkgBuilder: ::core::fmt::Debug + ::std::any::Any { + fn name(&self) -> crate::PkgName; + fn path(&self) -> crate::Path; + fn version(&self) -> crate::Version; + fn default_unused(&mut self) -> &mut dyn crate::PkgBuilder; fn build( &mut self, - ) -> Result>; + ) -> Result, ::std::boxed::Box>; } -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct PkgEmpty { version: Version, } @@ -216,8 +230,8 @@ impl Pkg for PkgEmpty { fn path(&self) -> Path { "::bok::Pkg::PkgEmpty".into() } - fn version(&self) -> &Version { - &self.version + fn version(&self) -> Version { + self.version.clone() } fn base(&self) -> Option<&dyn Pkg> { None @@ -225,6 +239,12 @@ impl Pkg for PkgEmpty { fn base_mut(&mut self) -> Option<&mut dyn Pkg> { 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<(), ()> { ::core::result::Result::Ok(()) }