diff --git a/bok-macro/src/lib.rs b/bok-macro/src/lib.rs index 3e9bd00..34f2855 100644 --- a/bok-macro/src/lib.rs +++ b/bok-macro/src/lib.rs @@ -218,6 +218,31 @@ pub fn impl_package(_attrs: TokenStream, input: TokenStream) -> TokenStream { Some(&mut self.base) } }; + let hash: ::syn::ImplItem = ::syn::parse_quote! { + fn hash(&self) -> ::bok::Hash { + use ::sha3::{Digest}; + let mut hasher = ::sha3::Sha3_256::new(); + let mut pkg_vars = String::new(); + use ::std::fmt::Write; + write!(&mut pkg_vars, + "{:?}", + self, + ); + hasher.update(&pkg_vars); + hasher.update(self.to_string()); + let hash = hasher.finalize(); + ::bok::Hash::Sha3(hash) + } + }; + let hash_code: ::syn::ImplItem = ::syn::parse_quote! { + fn hash_code(&self) -> ::bok::Hash { + use ::sha3::{Digest}; + let mut hasher = ::sha3::Sha3_256::new(); + hasher.update(self.to_string()); + let hash = hasher.finalize(); + ::bok::Hash::Sha3(hash) + } + }; for mut impl_item in ast.items.iter_mut() { if let ::syn::ImplItem::Fn(ref mut fn_impl) = &mut impl_item { @@ -233,6 +258,8 @@ pub fn impl_package(_attrs: TokenStream, input: TokenStream) -> TokenStream { ast.items.push(base); ast.items.push(base_mut); + ast.items.push(hash); + ast.items.push(hash_code); quote! { #ast @@ -432,6 +459,13 @@ pub fn derive_package(input: TokenStream) -> TokenStream { let expanded = quote! { impl ::core::fmt::Display for #name { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) + ->::core::fmt::Result + { + <#name as ::bok::PkgCode>::fmt(self, f) + } + } + impl ::bok::PkgCode for #name { fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) ->::core::fmt::Result { @@ -506,13 +540,6 @@ pub fn derive_package(input: TokenStream) -> TokenStream { pub fn builder() -> #name_builder { #name_builder::default() } - pub fn hash() -> ::bok::Hash { - // FIXME: this does not capture the package field status - use ::sha3::{Digest, Sha3_256}; - let mut hasher = ::sha3::Sha3_256::new(); - let hash = hasher.finalize(); - ::bok::Hash::Sha3(hash) - } #(pub fn #all_fields2(&self) -> &#all_types { &self.#all_fields2 })* @@ -535,11 +562,13 @@ pub fn derive_package(input: TokenStream) -> TokenStream { */ impl ::bok::PkgBuilder for #name_builder2 { type Package = #name; - fn default_unused(&mut self){ + 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); })* + + self } fn build(&mut self) -> Result<#name, ::std::boxed::Box> { #(if self.#non_opt_fields2.is_none() { diff --git a/bok-utils/src/main.rs b/bok-utils/src/main.rs index eb9bf7d..51ca99e 100644 --- a/bok-utils/src/main.rs +++ b/bok-utils/src/main.rs @@ -45,7 +45,15 @@ fn main() { let b = pb.as_builder(); let a = pb.as_any_mut(); let m_pb2: Option<&mut pkgs::one::OneBuilder> = a.downcast_mut(); + use ::bok::{Pkg, PkgBuilder}; println!("m_pb2: {:?}", m_pb2); + let m_pkg = pb.default_unused().build(); + println!("m_pb2: {:?}", m_pkg); + if let Ok(pkg) = m_pkg { + println!("one: {:?}", pkg); + println!("hash one: {}", pkg.hash()); + println!("hash one code: {}", pkg.hash_code()); + } println!("pkgs1 - 1:{}", pkgs1.one().my_attr); println!("pkgs1 - 2:{}", pkgs1.two().my_attr); diff --git a/bok/src/lib.rs b/bok/src/lib.rs index 215966e..8248a86 100644 --- a/bok/src/lib.rs +++ b/bok/src/lib.rs @@ -87,9 +87,13 @@ pub trait Repository: Default {} pub struct RepositoryEmpty {} impl Repository for RepositoryEmpty {} +/// Print the code of the package +pub trait PkgCode { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result; +} /// Implement common package operations pub trait Pkg: - ::core::fmt::Debug + ::core::fmt::Display + ::std::any::Any + ::core::fmt::Debug + ::core::fmt::Display + ::std::any::Any + PkgCode { fn base(&self) -> ::core::option::Option<&dyn Pkg>; fn base_mut(&mut self) -> ::core::option::Option<&mut dyn Pkg>; @@ -140,11 +144,15 @@ pub trait Pkg: self.check()?; self.install() } + fn hash(&self) -> Hash; + fn hash_code(&self) -> Hash; } pub trait PkgBuilder: ::std::any::Any { type Package; - fn default_unused(&mut self); + fn default_unused( + &mut self, + ) -> &mut dyn PkgBuilder; fn build( &mut self, ) -> Result>; @@ -159,6 +167,12 @@ impl ::core::fmt::Display for PkgEmpty { } } +impl PkgCode for PkgEmpty { + fn fmt(&self, _f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + Ok(()) + } +} + impl Pkg for PkgEmpty { fn base(&self) -> Option<&dyn Pkg> { None @@ -206,6 +220,18 @@ impl Pkg for PkgEmpty { ret = ::core::result::Result::Ok(()); } } + fn hash(&self) -> Hash { + use ::sha3::Digest; + let mut hasher = ::sha3::Sha3_256::new(); + let hash = hasher.finalize(); + Hash::Sha3(hash) + } + fn hash_code(&self) -> Hash { + use ::sha3::Digest; + let mut hasher = ::sha3::Sha3_256::new(); + let hash = hasher.finalize(); + Hash::Sha3(hash) + } } ::bitflags::bitflags! { @@ -240,9 +266,20 @@ impl Pkg for PkgEmpty { pub struct Conf {} /// package hash +#[derive(Debug, Copy, Clone)] pub enum Hash { Sha3(::sha3::digest::Output<::sha3::Sha3_256>), } + +impl ::std::fmt::Display for Hash { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + match self { + //FIXME: move to something like zbase85 + Hash::Sha3(h) => write!(f, "{:x}", h), + } + } +} + /* pub enum Value { /// Set, only once per