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! {
#[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<Package = #name> {
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<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() {
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<Package = #name> {
pub fn as_builder(&self) -> &dyn ::bok::PkgBuilder {
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
}
#(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)
pub fn two(&self) -> Two {
use ::bok::PkgBuilder;
Two::builder()
let pkg: Box<dyn ::bok::Pkg> = 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::<Two>().unwrap();
two.clone()
}
}

View File

@ -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<dyn Repository>, ArcLock<dyn Pkg>)),
AlreadyPresent((Arc<dyn Repository>, ArcLock<dyn PkgBuilder>)),
#[error("not found")]
NotFound,
}
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
pub struct Collection {
@ -51,7 +52,7 @@ impl Collection {
pub fn add_pkg(
&self,
r: Arc<dyn Repository>,
p: ArcLock<dyn Pkg>,
p: ArcLock<dyn PkgBuilder>,
) -> 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<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();
for (_, pkg_map) in repos_pkgs.iter() {
match pkg_map.get(&pkg_path) {
@ -101,7 +102,7 @@ impl Collection {
&self,
repo_path: Path<RepoName>,
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();
match repos_pkgs.get(&repo_path) {
None => Err(Error::NotFound),

View File

@ -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<RepoName>;
}
@ -114,9 +118,19 @@ pub trait Pkg:
{
fn name(&self) -> PkgName;
fn path(&self) -> Path<PkgName>;
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<dyn Repository>,
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<Package = Self::Package>;
pub trait PkgBuilder: ::core::fmt::Debug + ::std::any::Any {
fn name(&self) -> crate::PkgName;
fn path(&self) -> crate::Path<crate::PkgName>;
fn version(&self) -> crate::Version;
fn default_unused(&mut self) -> &mut dyn crate::PkgBuilder;
fn build(
&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 {
version: Version,
}
@ -216,8 +230,8 @@ impl Pkg for PkgEmpty {
fn path(&self) -> Path<PkgName> {
"::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(())
}